Skip to content

Commit 066851f

Browse files
committed
fix: connect as middlewares & unit test and enhanced logger
1 parent 9f9212b commit 066851f

34 files changed

+514
-164
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"db:generate": "pnpm -F @tg-search/db db:generate",
2121
"db:migrate": "pnpm -F @tg-search/db db:migrate",
2222
"db:push": "pnpm -F @tg-search/db db:push",
23-
"test": "pnpm -r test",
23+
"test": "pnpm -r test run",
2424
"test:coverage": "pnpm -r test:coverage"
2525
},
2626
"devDependencies": {

packages/cli/src/cli.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { Command as Commander } from 'commander'
77

88
import { registry } from './command'
99
import botCommand from './commands/bot'
10-
import connectCommand from './commands/connect'
1110
import embedCommand from './commands/embed'
1211
import exportCommand from './commands/export'
1312
import importCommand from './commands/import'
1413
import searchCommand from './commands/search'
1514
import syncCommand from './commands/sync'
1615
import watchCommand from './commands/watch'
16+
import { ensureAuthenticated } from './middlewares/connect'
1717

1818
const logger = useLogger()
1919

@@ -22,7 +22,6 @@ const logger = useLogger()
2222
*/
2323
export function registerCommands() {
2424
registry.register(botCommand)
25-
registry.register(connectCommand)
2625
registry.register(embedCommand)
2726
registry.register(exportCommand)
2827
registry.register(importCommand)
@@ -86,26 +85,8 @@ export function setupCli() {
8685
(command as { setClient: (client: TelegramAdapter) => void }).setClient(client)
8786
}
8887

89-
// Connect to Telegram
90-
logger.log('正在连接到 Telegram...')
91-
try {
92-
await client.connect()
93-
}
94-
catch (error) {
95-
// If connection failed due to authentication, use connect command
96-
if (error instanceof Error && (
97-
error.message === 'Code is required'
98-
|| error.message === '2FA password is required'
99-
|| error.message === 'Code is empty'
100-
)) {
101-
logger.debug('需要验证,使用 connect 命令...')
102-
connectCommand.setClient(client)
103-
await connectCommand.execute([], {})
104-
}
105-
else {
106-
throw error
107-
}
108-
}
88+
// Ensure authentication before executing command
89+
await ensureAuthenticated(client)
10990
}
11091

11192
// Execute command

packages/cli/src/commands/bot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class BotCommand extends TelegramCommand {
3737
forwards: message.forwards,
3838
createdAt: message.createdAt,
3939
})
40-
logger.log('消息已保存到数据库:', result)
40+
logger.withFields({ result }).log('消息已保存到数据库')
4141
}
4242
catch (error) {
4343
logger.withError(error).error('保存消息失败:')

packages/cli/src/commands/connect.ts

Lines changed: 0 additions & 90 deletions
This file was deleted.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type { TelegramAdapter } from '@tg-search/core'
2+
3+
import * as input from '@inquirer/prompts'
4+
import { useLogger } from '@tg-search/common'
5+
6+
const logger = useLogger()
7+
8+
/**
9+
* Authentication middleware to handle Telegram login
10+
* This middleware ensures that the client is authenticated before executing commands
11+
*/
12+
export async function ensureAuthenticated(client: TelegramAdapter): Promise<void> {
13+
let retryCount = 0
14+
const maxRetries = 3
15+
16+
while (retryCount < maxRetries) {
17+
try {
18+
logger.log('正在连接到 Telegram...')
19+
20+
// Try to connect with callbacks for authentication
21+
await client.connect({
22+
code: async () => {
23+
logger.log('需要验证码')
24+
const code = await input.input({ message: '请输入你收到的验证码:' })
25+
if (!code)
26+
throw new Error('需要验证码')
27+
return code
28+
},
29+
password: async () => {
30+
logger.log('需要两步验证密码')
31+
const password = await input.password({ message: '请输入两步验证密码:' })
32+
if (!password)
33+
throw new Error('需要两步验证密码')
34+
return password
35+
},
36+
})
37+
38+
logger.log('连接成功')
39+
return
40+
}
41+
catch (error) {
42+
if (error instanceof Error) {
43+
// Skip if already connected
44+
if (error.message.includes('already connected')) {
45+
logger.log('已经连接')
46+
return
47+
}
48+
49+
// Handle invalid code
50+
if (error.message.includes('PHONE_CODE_INVALID')) {
51+
logger.warn('验证码无效,请重试')
52+
retryCount++
53+
continue
54+
}
55+
56+
// Log other errors
57+
logger.withError(error).error('连接失败')
58+
}
59+
throw error
60+
}
61+
}
62+
63+
throw new Error('验证码重试次数过多,请稍后再试')
64+
}

packages/common/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"stub": "unbuild --stub",
2121
"lint": "eslint src",
2222
"lint:fix": "eslint src --fix",
23-
"typecheck": "tsc --noEmit"
23+
"typecheck": "tsc --noEmit",
24+
"test": "vitest"
2425
},
2526
"dependencies": {
2627
"@guiiai/logg": "^1.0.7",
@@ -34,6 +35,7 @@
3435
"devDependencies": {
3536
"@types/lodash": "^4.17.15",
3637
"@types/node": "^22.13.4",
37-
"unbuild": "^3.3.1"
38+
"unbuild": "^3.3.1",
39+
"vitest": "^3.0.6"
3840
}
3941
}

packages/common/src/composable/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function loadYamlConfig(configPath: string): Partial<Config> {
8181
return yaml.parse(content)
8282
}
8383
catch {
84-
const logger = useLogger('config')
84+
const logger = useLogger()
8585
logger.debug(`Failed to load config file: ${configPath}`)
8686
return {}
8787
}
@@ -108,7 +108,7 @@ function validateConfig(config: Config) {
108108
}
109109

110110
export function initConfig() {
111-
const logger = useLogger('config')
111+
const logger = useLogger()
112112

113113
try {
114114
// Find config directory
@@ -140,7 +140,7 @@ export function initConfig() {
140140
}
141141

142142
// Log merged config
143-
logger.withFields({ mergedConfig: JSON.stringify(mergedConfig, null, 2) }).debug('Config initialized successfully')
143+
logger.withFields({ mergedConfig: JSON.stringify(mergedConfig) }).debug('Config initialized successfully')
144144

145145
// Validate configuration
146146
validateConfig(mergedConfig)

packages/common/src/composable/db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getConfig } from './config'
77
let dbInstance: ReturnType<typeof drizzle>
88

99
export function initDB() {
10-
const logger = useLogger('db')
10+
const logger = useLogger()
1111
logger.debug('Initializing database...')
1212

1313
// Database connection
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, expect, it } from 'vitest'
2+
3+
import { initLogger, useLogger } from './logger'
4+
5+
describe('logger', () => {
6+
describe('initLogger', () => {
7+
it('should initialize logger without error', () => {
8+
expect(() => initLogger()).not.toThrow()
9+
})
10+
})
11+
12+
describe('useLogger', () => {
13+
it('should create logger with provided name', () => {
14+
const logger = useLogger('test')
15+
expect(logger).toBeDefined()
16+
expect(logger.log).toBeInstanceOf(Function)
17+
expect(logger.debug).toBeInstanceOf(Function)
18+
expect(logger.warn).toBeInstanceOf(Function)
19+
expect(logger.error).toBeInstanceOf(Function)
20+
expect(logger.withFields).toBeInstanceOf(Function)
21+
expect(logger.withError).toBeInstanceOf(Function)
22+
})
23+
24+
it('should create logger with auto-detected name', () => {
25+
const logger = useLogger()
26+
expect(logger).toBeDefined()
27+
})
28+
29+
it('should log message with fields', () => {
30+
const logger = useLogger('test')
31+
expect(() => {
32+
logger.log('test message', { field: 'value' })
33+
logger.debug('test message', { field: 'value' })
34+
logger.warn('test message', { field: 'value' })
35+
logger.error('test message', { field: 'value' })
36+
}).not.toThrow()
37+
})
38+
39+
it('should log message without fields', () => {
40+
const logger = useLogger('test')
41+
expect(() => {
42+
logger.log('test message')
43+
logger.debug('test message')
44+
logger.warn('test message')
45+
logger.error('test message')
46+
}).not.toThrow()
47+
})
48+
49+
it('should chain withFields and withError', () => {
50+
const logger = useLogger('test')
51+
const error = new Error('test error')
52+
53+
expect(() => {
54+
logger.withFields({ field: 'value' }).log('test message')
55+
logger.withError(error).error('test message')
56+
}).not.toThrow()
57+
})
58+
})
59+
})

0 commit comments

Comments
 (0)