refactor: platform

This commit is contained in:
Acbox
2026-01-15 15:24:40 +08:00
parent a61a1e76b2
commit afc6dc6cb1
15 changed files with 286 additions and 270 deletions
+1 -1
View File
@@ -10,7 +10,6 @@
"memoh-tg-bot": "./src/bot.ts"
},
"scripts": {
"start": "bun run src/bot.ts",
"dev": "bun run --watch src/bot.ts"
},
"keywords": [],
@@ -20,6 +19,7 @@
"dependencies": {
"@memoh/client": "workspace:*",
"@memoh/platform": "workspace:*",
"@memoh/shared": "workspace:*",
"dotenv": "^16.4.7",
"ioredis": "^5.9.1",
"telegraf": "^4.16.3",
-52
View File
@@ -1,52 +0,0 @@
#!/usr/bin/env bun
/**
* Telegram Bot Standalone Entry Point
*
* This file allows running the Telegram bot as a standalone process
*/
import { TelegramPlatform } from './index'
async function main() {
const botToken = process.env.BOT_TOKEN
const redisUrl = process.env.REDIS_URL
const apiUrl = process.env.API_BASE_URL
if (!botToken) {
console.error('❌ BOT_TOKEN environment variable is required')
process.exit(1)
}
console.log('🚀 Starting Telegram bot...')
console.log(`📡 API URL: ${apiUrl || 'http://localhost:7002'}`)
console.log(`💾 Redis URL: ${redisUrl || 'redis://localhost:6379'}`)
const platform = new TelegramPlatform()
try {
platform.serve()
console.log('✅ Bot is running...')
console.log('Press Ctrl+C to stop')
// Graceful shutdown
process.once('SIGINT', async () => {
console.log('\n🛑 Stopping bot...')
await platform.stop()
process.exit(0)
})
process.once('SIGTERM', async () => {
console.log('\n🛑 Stopping bot...')
await platform.stop()
process.exit(0)
})
} catch (error) {
console.error('❌ Failed to start bot:', error)
process.exit(1)
}
}
main()
+6 -35
View File
@@ -1,65 +1,38 @@
import { Telegraf, type Context } from 'telegraf'
import { BasePlatform, SendSchema } from '@memoh/platform'
import { BasePlatform, PlatformMessage } from '@memoh/platform'
import { handleLogin, handleLogout, handleWhoami, requireAuth } from './auth'
import { chatStreamAsync, type StreamEvent } from '@memoh/client'
import { getTokenStorage } from './storage'
import z from 'zod'
import Redis from 'ioredis'
import { Platform } from '@memoh/shared'
export interface TelegramPlatformConfig {
botToken: string
redisUrl?: string
apiUrl?: string
}
export class TelegramPlatform extends BasePlatform {
name = 'telegram'
description = 'Telegram Bot platform for Memoh'
config = z.object({
botToken: z.string(),
})
port = 7101
description = 'Telegram Bot platform'
private bot?: Telegraf
redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379')
// private storage?: TelegramRedisStorage
override async start(config: z.infer<typeof this.config>): Promise<void> {
const botToken = config.botToken as string
if (!botToken) {
throw new Error('Bot token is required')
}
// // Initialize storage
// this.storage = new TelegramRedisStorage({
// redisUrl: config.redisUrl as string,
// apiUrl: config.apiUrl as string,
// })
// Initialize bot
async start({ botToken }: TelegramPlatformConfig): Promise<void> {
this.bot = new Telegraf(botToken)
// Register commands
this.registerCommands()
// Start bot
this.bot.launch()
console.log('✅ Telegram bot started successfully')
}
async stop(): Promise<void> {
if (this.bot) {
this.bot.stop('SIGTERM')
console.log('🛑 Telegram bot stopped')
}
// if (this.storage) {
// await this.storage.close()
// console.log('🛑 Redis connection closed')
// }
}
async send({ userId, message }: z.infer<typeof SendSchema>): Promise<void> {
async send({ message, userId }: PlatformMessage): Promise<void> {
const pattern = 'memoh:telegram:*:userId'
let cursor = '0'
let telegramUserId: string | null = null
@@ -74,11 +47,9 @@ export class TelegramPlatform extends BasePlatform {
)
cursor = nextCursor
// 检查每个 key 的值是否匹配目标 userId
for (const key of keys) {
const storedUserId = await this.redis.get(key)
if (storedUserId === userId) {
// 从 key 中提取 telegramUserId: memoh:telegram:{telegramUserId}:userId
const match = key.match(/^memoh:telegram:(.+):userId$/)
if (match) {
telegramUserId = match[1]