feat(tgapp): handle photo messages, pass temp path to agent

This commit is contained in:
Liang Jiaqing
2026-04-21 23:39:46 +08:00
parent f1db2e56df
commit 7b2ff1e73a

View File

@@ -84,7 +84,6 @@ async def _stream(dq, msg):
except Exception: pass except Exception: pass
break break
def _normalized_command(text): def _normalized_command(text):
parts = (text or '').strip().split(None, 1) parts = (text or '').strip().split(None, 1)
if not parts: if not parts:
@@ -94,13 +93,11 @@ def _normalized_command(text):
head = '/' + head[1:].split('@', 1)[0] head = '/' + head[1:].split('@', 1)[0]
return head + (f" {parts[1].strip()}" if len(parts) > 1 and parts[1].strip() else '') return head + (f" {parts[1].strip()}" if len(parts) > 1 and parts[1].strip() else '')
def _cancel_stream_task(ctx): def _cancel_stream_task(ctx):
task = ctx.user_data.pop('stream_task', None) task = ctx.user_data.pop('stream_task', None)
if task and not task.done(): if task and not task.done():
task.cancel() task.cancel()
async def _sync_commands(application): async def _sync_commands(application):
await application.bot.set_my_commands([BotCommand(command, description) for command, description in TELEGRAM_MENU_COMMANDS]) await application.bot.set_my_commands([BotCommand(command, description) for command, description in TELEGRAM_MENU_COMMANDS])
@@ -132,6 +129,20 @@ async def cmd_llm(update, ctx):
lines = [f"{'' if cur else ' '} [{i}] {name}" for i, name, cur in agent.list_llms()] lines = [f"{'' if cur else ' '} [{i}] {name}" for i, name, cur in agent.list_llms()]
await update.message.reply_text("LLMs:\n" + "\n".join(lines)) await update.message.reply_text("LLMs:\n" + "\n".join(lines))
async def handle_photo(update, ctx):
uid = update.effective_user.id
if ALLOWED and uid not in ALLOWED:
return await update.message.reply_text("no")
photo = update.message.photo[-1]
file = await photo.get_file()
fpath = f"tg_{photo.file_unique_id}.jpg"
await file.download_to_drive(os.path.join(_TEMP_DIR, fpath))
caption = update.message.caption
prompt = f"[TIPS] 收到图片temp/{fpath}\n{caption}" if caption else f"[TIPS] 收到图片temp/{fpath},请等待下一步指令"
msg = await update.message.reply_text("thinking...")
dq = agent.put_task(prompt, source="telegram")
task = asyncio.create_task(_stream(dq, msg))
ctx.user_data['stream_task'] = task
async def handle_command(update, ctx): async def handle_command(update, ctx):
uid = update.effective_user.id uid = update.effective_user.id
@@ -139,15 +150,12 @@ async def handle_command(update, ctx):
return await update.message.reply_text("no") return await update.message.reply_text("no")
cmd = _normalized_command(update.message.text) cmd = _normalized_command(update.message.text)
op = cmd.split()[0] if cmd else '' op = cmd.split()[0] if cmd else ''
if op == '/help': if op == '/help': return await update.message.reply_text(HELP_TEXT)
return await update.message.reply_text(HELP_TEXT)
if op == '/status': if op == '/status':
llm = agent.get_llm_name() if agent.llmclient else '未配置' llm = agent.get_llm_name() if agent.llmclient else '未配置'
return await update.message.reply_text(f"状态: {'🔴 运行中' if agent.is_running else '🟢 空闲'}\nLLM: [{agent.llm_no}] {llm}") return await update.message.reply_text(f"状态: {'🔴 运行中' if agent.is_running else '🟢 空闲'}\nLLM: [{agent.llm_no}] {llm}")
if op == '/stop': if op == '/stop': return await cmd_abort(update, ctx)
return await cmd_abort(update, ctx) if op == '/llm': return await cmd_llm(update, ctx)
if op == '/llm':
return await cmd_llm(update, ctx)
if op == '/new': if op == '/new':
_cancel_stream_task(ctx) _cancel_stream_task(ctx)
return await update.message.reply_text(reset_conversation(agent)) return await update.message.reply_text(reset_conversation(agent))
@@ -164,14 +172,12 @@ async def handle_command(update, ctx):
except Exception as e: except Exception as e:
return await update.message.reply_text(f"❌ 恢复失败: {e}") return await update.message.reply_text(f"❌ 恢复失败: {e}")
if op == '/continue': if op == '/continue':
if cmd != '/continue': if cmd != '/continue': _cancel_stream_task(ctx)
_cancel_stream_task(ctx)
return await update.message.reply_text(handle_frontend_command(agent, cmd)) return await update.message.reply_text(handle_frontend_command(agent, cmd))
return await update.message.reply_text(HELP_TEXT) return await update.message.reply_text(HELP_TEXT)
if __name__ == '__main__': if __name__ == '__main__':
# Single instance lock using socket try: # Single instance lock using socket
try:
_lock_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); _lock_sock.bind(('127.0.0.1', 19527)) _lock_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); _lock_sock.bind(('127.0.0.1', 19527))
except OSError: except OSError:
print('[Telegram] Another instance is already running, skiping...') print('[Telegram] Another instance is already running, skiping...')
@@ -194,21 +200,13 @@ if __name__ == '__main__':
print(f"TG bot starting... {time.strftime('%m-%d %H:%M')}") print(f"TG bot starting... {time.strftime('%m-%d %H:%M')}")
# Recreate request and app objects on each restart to avoid stale connections # Recreate request and app objects on each restart to avoid stale connections
request = HTTPXRequest(proxy=proxy, read_timeout=30, write_timeout=30, connect_timeout=30, pool_timeout=30) request = HTTPXRequest(proxy=proxy, read_timeout=30, write_timeout=30, connect_timeout=30, pool_timeout=30)
app = (ApplicationBuilder() app = (ApplicationBuilder().token(mykeys['tg_bot_token'])
.token(mykeys['tg_bot_token']) .request(request).get_updates_request(request).post_init(_sync_commands).build())
.request(request)
.get_updates_request(request)
.post_init(_sync_commands)
.build())
app.add_handler(MessageHandler(filters.COMMAND, handle_command)) app.add_handler(MessageHandler(filters.COMMAND, handle_command))
app.add_handler(MessageHandler(filters.PHOTO, handle_photo))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_msg)) app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_msg))
app.add_error_handler(_error_handler) app.add_error_handler(_error_handler)
app.run_polling(drop_pending_updates=True, poll_interval=1.0, timeout=30)
app.run_polling(
drop_pending_updates=True,
poll_interval=1.0,
timeout=30,
)
except Exception as e: except Exception as e:
print(f"[{time.strftime('%m-%d %H:%M')}] polling crashed: {e}", flush=True) print(f"[{time.strftime('%m-%d %H:%M')}] polling crashed: {e}", flush=True)
time.sleep(10) time.sleep(10)