Skip to content

Commit 446df72

Browse files
committed
refactor: comprehensive codebase optimization and restructuring
Major changes: - Migrated API framework from Elysia to Fastify - Removed duplicate dependencies (tmp-promise, undici) - Consolidated duplicate utilities (MIME, date, temp, convert, encoding) - Flattened directory structure (interfaces/api, features/recall, features/media, etc.) - Removed unnecessary single-file directories - Merged src/app into src/index.ts - Created shared utilities (registerDualRoute, ErrorResponses, TTLCache) - Standardized file naming (camelCase for utilities) - Fixed RecallFeature dynamic imports for better testability - Fixed all test failures (40/40 tests passing) This refactoring significantly improves code maintainability, reduces duplication, and simplifies the project structure.
1 parent e4fa7a3 commit 446df72

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2399
-1783
lines changed

main/package-lock.json

Lines changed: 1288 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

main/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131
"vitest": "^4.0.15"
3232
},
3333
"dependencies": {
34-
"@bogeychan/elysia-polyfills": "^0.6.4",
35-
"@elysiajs/html": "^1.4.0",
34+
"@fastify/cors": "^11.1.0",
35+
"@fastify/static": "^8.3.0",
3636
"@kitajs/html": "^4.2.11",
3737
"@mtcute/core": "^0.27.2",
3838
"@mtcute/dispatcher": "^0.27.2",
3939
"@mtcute/node": "^0.27.2",
4040
"@prisma/adapter-pg": "7.1.0",
4141
"@prisma/client": "7.1.0",
42-
"elysia": "^1.4.18",
42+
"fastify": "^5.6.2",
4343
"file-type": "^21.1.1",
4444
"node-napcat-ts": "^0.4.20",
4545
"pg": "^8.16.3",

main/src/app/index.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

main/src/features/FeatureManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { getLogger } from '../shared/logger';
22
import type { IQQClient } from '../infrastructure/clients/qq';
33
import type Telegram from '../infrastructure/clients/telegram/client';
44
import type Instance from '../domain/models/Instance';
5-
import { RecallFeature } from './recall/RecallFeature';
6-
import { MediaFeature } from './media/MediaFeature';
5+
import { RecallFeature } from './RecallFeature';
6+
import { MediaFeature } from './MediaFeature';
77
import { CommandsFeature } from './commands/CommandsFeature';
88
import { ForwardFeature } from './forward/ForwardFeature';
99

main/src/features/media/MediaFeature.ts renamed to main/src/features/MediaFeature.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { getLogger } from '../../shared/logger';
2-
import type { IQQClient } from '../../infrastructure/clients/qq';
3-
import type { UnifiedMessage, ImageContent, VideoContent, AudioContent } from '../../domain/message';
4-
import type Telegram from '../../infrastructure/clients/telegram/client';
5-
import type Instance from '../../domain/models/Instance';
1+
import { getLogger } from '../shared/logger';
2+
import type { IQQClient } from '../infrastructure/clients/qq';
3+
import type { UnifiedMessage, ImageContent, VideoContent, AudioContent } from '../domain/message';
4+
import type Telegram from '../infrastructure/clients/telegram/client';
5+
import type Instance from '../domain/models/Instance';
66

77
import { createReadStream } from 'fs';
8-
import { file as createTempFile } from '../../shared/utils/temp';
8+
import { file as createTempFile } from '../shared/utils/temp';
99
import fsP from 'fs/promises';
1010

1111
const logger = getLogger('MediaFeature');

main/src/features/recall/RecallFeature.ts renamed to main/src/features/RecallFeature.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { getLogger } from '../../shared/logger';
2-
import type { IQQClient } from '../../infrastructure/clients/qq';
3-
import type { RecallEvent } from '../../domain/message';
4-
import type Telegram from '../../infrastructure/clients/telegram/client';
5-
import type Instance from '../../domain/models/Instance';
6-
import db from '../../domain/models/db';
1+
import { getLogger } from '../shared/logger';
2+
import type { IQQClient } from '../infrastructure/clients/qq';
3+
import type { RecallEvent } from '../domain/message';
4+
import type Telegram from '../infrastructure/clients/telegram/client';
5+
import type Instance from '../domain/models/Instance';
6+
import db from '../domain/models/db';
7+
import env from '../domain/models/env';
78

89
const logger = getLogger('RecallFeature');
910

@@ -40,7 +41,6 @@ export class RecallFeature {
4041
logger.info(`QQ message recalled: ${event.messageId}`);
4142

4243
// 检查是否启用自动撤回
43-
const { default: env } = await import('../../domain/models/env');
4444
if (!env.ENABLE_AUTO_RECALL) {
4545
logger.debug('Auto recall is disabled, skipping TG message deletion');
4646
return;
@@ -96,7 +96,6 @@ export class RecallFeature {
9696
logger.info(`TG messages deleted in ${chatId}: ${messageIds.join(', ')}`);
9797

9898
// 检查是否启用自动撤回
99-
const { default: env } = await import('../../domain/models/env');
10099
if (!env.ENABLE_AUTO_RECALL) {
101100
logger.debug('Auto recall disabled, skipping QQ message recall');
102101
return;

main/src/features/__tests__/media.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect, beforeEach, vi } from 'vitest';
2-
import { MediaFeature } from '../media/MediaFeature';
2+
import { MediaFeature } from '../MediaFeature';
33
import type { ImageContent, VideoContent, AudioContent } from '../../domain/message';
44

55
// Mock global fetch

main/src/features/__tests__/recall.test.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
import { describe, it, expect, beforeEach, vi } from 'vitest';
2-
import { RecallFeature } from '../recall/RecallFeature';
3-
import type { RecallEvent } from '../../domain/message';
4-
import type { IQQClient } from '../../infrastructure/clients/qq';
52

63
// Mock database
74
vi.mock('../../domain/models/db', () => ({
@@ -13,6 +10,21 @@ vi.mock('../../domain/models/db', () => ({
1310
},
1411
}));
1512

13+
// Mock environment
14+
vi.mock('../../domain/models/env', () => ({
15+
default: {
16+
ENABLE_AUTO_RECALL: true,
17+
LOG_FILE: '/tmp/test-logs/app.log',
18+
LOG_LEVEL: 'off',
19+
LOG_FILE_LEVEL: 'off',
20+
DATA_DIR: '/tmp/test-data',
21+
},
22+
}));
23+
24+
// Now import after mocks are set up
25+
import { RecallFeature } from '../RecallFeature';
26+
import type { RecallEvent } from '../../domain/message';
27+
import type { IQQClient } from '../../infrastructure/clients/qq';
1628
import db from '../../domain/models/db';
1729

1830
const createMockQQClient = (): IQQClient => ({
@@ -152,7 +164,13 @@ describe('RecallFeature', () => {
152164
};
153165

154166
(db.message.findFirst as any).mockResolvedValue(mockDbEntry);
155-
mockTgBot.deleteMessages.mockRejectedValue(new Error('TG API Error'));
167+
(db.message.update as any).mockResolvedValue({ ...mockDbEntry, ignoreDelete: true });
168+
169+
// Mock getChat to return a chat with failing deleteMessages
170+
const mockChat = {
171+
deleteMessages: vi.fn().mockRejectedValue(new Error('TG API Error')),
172+
};
173+
mockTgBot.getChat.mockResolvedValue(mockChat);
156174

157175
await expect(
158176
recallFeature['handleQQRecall'](recallEvent)

0 commit comments

Comments
 (0)