You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Telethon实现Telegram多用户调查机器人的进度追踪?

嗨,作为刚接触Telethon和机器人开发的新手,遇到多用户状态追踪的问题太正常了!我来给你梳理几个实用的方案,从易到难,你可以根据自己的需求选:

一、最快速上手:内存字典存储状态

适合小型测试机器人或者临时场景,不需要额外依赖,直接用Python字典就能搞定核心逻辑。我们可以把**聊天ID(用户私人ID或群组ID)**作为键,对应的值存储该用户/群组当前的调查状态,比如所属调查ID、当前投票序号、已发送消息ID列表等。

举个简单的代码示例:

# 全局字典,用来存所有用户的调查状态
user_survey_states = {}

# 初始化用户的调查状态(用户开始调查时调用)
async def init_survey_state(chat_id, survey_id):
    user_survey_states[chat_id] = {
        "survey_id": survey_id,
        "current_step": 0,  # 当前要发送的投票序号,从0开始计数
        "sent_message_ids": [],  # 存已发送消息的ID,方便后续编辑/删除
        "last_active": datetime.now()  # 记录最后活动时间,方便清理过期状态
    }

# 处理用户回复,更新状态并发送下一条投票
async def handle_user_response(chat_id, response_msg):
    # 先判断用户是否在参与调查
    if chat_id not in user_survey_states:
        await client.send_message(chat_id, "请先发送/start_survey开始调查哦~")
        return
    
    state = user_survey_states[chat_id]
    # 这里可以加逻辑:记录用户当前回复的答案,比如存到数据库或文件
    
    # 更新当前步骤
    state["current_step"] += 1
    state["last_active"] = datetime.now()
    
    # 获取下一条投票内容(假设你有一个get_survey_question方法,根据调查ID和步骤返回内容)
    next_question = get_survey_question(state["survey_id"], state["current_step"])
    if next_question:
        # 发送下一条投票,并把消息ID存到状态里
        sent_msg = await client.send_message(
            chat_id,
            next_question["text"],
            buttons=next_question["buttons"]
        )
        state["sent_message_ids"].append(sent_msg.id)
    else:
        # 调查结束,发送感谢语并清理状态
        await client.send_message(chat_id, "调查完成!感谢你的参与😊")
        del user_survey_states[chat_id]

这个方案的优点是零成本快速实现,缺点是机器人重启后所有状态会丢失,所以只适合测试或临时使用。

二、生产环境首选:数据库持久化状态

如果你的机器人需要长期运行,或者用户量较大,一定要用数据库存储状态,避免重启丢失数据。新手可以先从轻量的SQLite入手,不需要额外安装服务,Python自带支持。

我们可以创建一个专门的表来存储用户调查状态,字段大概是这样:

字段名类型说明
chat_idINTEGER用户/群组ID(主键)
survey_idTEXT当前参与的调查ID
current_stepINTEGER当前投票序号
sent_messagesTEXT已发送消息ID列表(存JSON)
last_activeDATETIME最后活动时间

简单的SQLite操作示例:

import sqlite3
import json
from datetime import datetime

# 初始化数据库连接
conn = sqlite3.connect("survey_bot.db")
cursor = conn.cursor()

# 创建状态表(第一次运行时执行)
cursor.execute('''
CREATE TABLE IF NOT EXISTS user_survey_states (
    chat_id INTEGER PRIMARY KEY,
    survey_id TEXT NOT NULL,
    current_step INTEGER NOT NULL DEFAULT 0,
    sent_messages TEXT NOT NULL DEFAULT '[]',
    last_active DATETIME NOT NULL
)
''')
conn.commit()

# 初始化用户状态
def init_survey_state_db(chat_id, survey_id):
    cursor.execute('''
    INSERT OR REPLACE INTO user_survey_states 
    (chat_id, survey_id, current_step, last_active)
    VALUES (?, ?, 0, ?)
    ''', (chat_id, survey_id, datetime.now()))
    conn.commit()

# 更新用户状态(比如用户回复后)
def update_survey_state_db(chat_id, new_step, new_msg_id=None):
    # 先获取已有的消息ID列表
    cursor.execute('SELECT sent_messages FROM user_survey_states WHERE chat_id = ?', (chat_id,))
    result = cursor.fetchone()
    if not result:
        return
    
    sent_messages = json.loads(result[0])
    if new_msg_id:
        sent_messages.append(new_msg_id)
    
    # 更新数据库
    cursor.execute('''
    UPDATE user_survey_states
    SET current_step = ?, sent_messages = ?, last_active = ?
    WHERE chat_id = ?
    ''', (new_step, json.dumps(sent_messages), datetime.now(), chat_id))
    conn.commit()

这个方案的优点是状态永久保存,机器人重启后用户的调查进度不会丢失;缺点是需要写一些数据库操作的代码,但SQLite对新手非常友好,上手很快。

三、Telethon内置方案:Conversation对话管理

Telethon自带了Conversation类,专门用来处理一对一的对话流程,它会自动帮你区分不同用户的对话状态,不需要自己手动维护字典。不过这个方案更适合步骤固定的简单调查,如果你的调查是完全自定义、步骤数量不固定的,灵活性不如前两种方案。

示例代码:

from telethon import events, Conversation

# 定义对话状态码,对应不同的调查步骤
START, QUESTION_1, QUESTION_2, SURVEY_END = range(4)

@client.on(events.NewMessage(pattern='/start_survey'))
async def start_survey(event):
    # 创建对话,设置超时时间(比如300秒没回复就结束)
    async with Conversation(event, timeout=300) as conv:
        # 发送第一个问题
        await conv.send_message("Q1:你喜欢喝咖啡还是茶?", buttons=[["咖啡", "茶"]])
        # 等待用户回复
        response1 = await conv.get_response()
        # 记录用户答案(这里可以存到数据库)
        
        # 发送第二个问题
        await conv.send_message("Q2:你每天喝几杯?", buttons=[["1杯", "2-3杯", "4杯以上"]])
        response2 = await conv.get_response()
        # 记录答案
        
        # 调查结束
        await conv.send_message("调查完成!感谢你的参与😊")

这个方案的优点是不需要自己手动管理用户状态,Telethon会自动处理多用户的对话隔离;缺点是步骤固定,动态自定义调查的话不太方便,而且超时时间需要设置合理。

额外注意事项
  1. 群组场景的特殊处理:如果是在群组中做调查,每个用户的进度可能不一样,这时候状态的键应该用(chat_id, user_id)(群组ID+用户ID),而不是单纯的chat_id,避免不同用户的状态互相覆盖。
  2. 清理过期状态:不管用哪种方案,都要定期清理长期不活跃的用户状态(比如超过24小时没回复的),避免内存或数据库资源浪费。
  3. 消息追踪的用处:存储已发送的消息ID,后续可以用client.edit_message修改消息内容,或者用client.delete_messages清理调查相关的消息,提升用户体验。

作为新手,建议先从内存字典的方案开始尝试,熟悉逻辑后再过渡到数据库方案,这样更容易上手哦!

内容的提问来源于stack exchange,提问作者Rehman Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:22:52