投票功能是Telegram Bot中极具交互性的特性之一,广泛用于社区决策、问卷调研或趣味互动。然而,很多开发者对如何创建投票并高效统计结果感到困惑。本文将系统讲解Telegram Bot投票的创建、用户响应监听以及最终统计的实现方法,帮助你构建功能完整的投票机器人。
一、Telegram Bot投票功能概览
Telegram Bot API提供了sendPoll方法,允许机器人在聊天中发送原生投票消息。用户可以直接点击选项参与投票,无需额外输入。投票类型支持匿名或公开,甚至可以在测验(quiz)模式下提供正确答案。而统计结果则依赖于两个关键点:监听poll_answer更新以获取实时投票状态,以及调用stopPoll在结束时获取最终统计数据。
二、使用sendPoll创建投票
发起投票只需调用sendPoll,核心参数如下:
- chat_id:目标聊天或频道的ID。
- question:投票问题,长度限制为1-300个字符。
- options:字符串数组,数量必须在2-10个之间。
- is_anonymous:布尔值,默认
True表示匿名投票。 - type:
regular(普通投票)或quiz(测验模式)。 - allows_multiple_answers:是否允许多选。
- open_period:投票自动关闭的秒数(5-600)。
- close_date:投票自动关闭的Unix时间戳。
示例请求(Python的requests库):
import requests
TOKEN = "YOUR_BOT_TOKEN"
URL = f"https://api.telegram.org/bot/sendPoll"
payload = {
"chat_id": "@my_group",
"question": "你最喜欢的编程语言?",
"options": ["Python", "JavaScript", "Go"],
"is_anonymous": False
}
requests.post(URL, json=payload)
发送成功后,Bot会收到包含poll对象的更新,其中poll对象带有唯一的poll_id和消息ID,务必保存这两个值供后续统计使用。
三、监听poll_answer更新实时统计
用户投票后,Telegram会向Bot推送poll_answer更新,包含poll_id、user以及用户选择的选项索引(option_ids)。通过监听这些更新,你可以实时记录每个选项的票数变化。
以下是一个简单的统计控制器(使用Python和python-telegram-bot库):
from telegram import Update
from telegram.ext import Application, MessageHandler, filters
# 存储每个poll的票数,格式:{poll_id: {option_id: count}}
poll_stats = {}
async def handle_poll_answer(update: Update, context):
answer = update.poll_answer
poll_id = answer.poll_id
option_ids = answer.option_ids
# 初始化poll statistics
if poll_id not in poll_stats:
return # 或者从数据库加载历史数据
# 简单计数(实际开发中需考虑取消投票或修改选择)
for opt_id in option_ids:
poll_stats[poll_id][opt_id] += 1
# 注册处理器
def main():
app = Application.builder().token("YOUR_BOT_TOKEN").build()
app.add_handler(MessageHandler(filters.POLL_ANSWER, handle_poll_answer))
app.run_polling()
注意:Telegram对重复投票的处理是替换前一次选择,因此你需要记录用户ID并维护其当前选择,再更新计数。上面的简单实现仅用于演示。
四、使用stopPoll获取最终结果
当投票结束(到期或手动关闭)后,调用stopPoll可以获取每个选项的最终票数。该方法的参数是chat_id和message_id。调用后,Telegram返回一个Poll对象,其options数组中包含每个选项的voter_count。
示例:
import requests
TOKEN = "YOUR_BOT_TOKEN"
URL = f"https://api.telegram.org/bot/stopPoll"
payload = {
"chat_id": "@my_group",
"message_id": 123456,
}
resp = requests.post(URL, json=payload).json()
print(resp["result"]["options"]) # 输出每个选项及voter_count
获取结果后,你可以将其持久化到数据库,或生成统计图表发送给管理员。
五、完整示例:创建投票并统计
下面是一个完整的Python示例,演示了创建匿名投票、监听回答并汇总结果(使用python-telegram-bot v20+):
import logging
from telegram import Update
from telegram import Bot
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
# 存储投票数据
poll_data = {} # poll_id -> {message_id, chat_id, options}
votes = {} # user_id -> (poll_id, option_id)
async def create_poll(update: Update, context: ContextTypes.DEFAULT_TYPE):
question = "你更喜欢哪个框架?"
options = ["Flask", "Django", "FastAPI"]
message = await context.bot.send_poll(
chat_id=update.effective_chat.id,
question=question,
options=options,
is_anonymous=False
)
poll_id = message.poll.id
poll_data[poll_id] = {
"message_id": message.message_id,
"chat_id": update.effective_chat.id,
"options": options
}
# 初始化票数
votes[poll_id] = [0] * len(options)
async def handle_poll_answer(update: Update, context: ContextTypes.DEFAULT_TYPE):
answer = update.poll_answer
poll_id = answer.poll_id
user_id = answer.user.id
selected = answer.option_ids
# 如果之前投过票,先取消旧票(示例为单选)
if user_id in votes and votes[user_id][0] == poll_id:
old_opt = votes[user_id][1]
votes[poll_id][old_opt] -= 1
# 记录新票,假设单选
votes[poll_id][selected[0]] += 1
votes[user_id] = (poll_id, selected[0])
async def poll_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):
poll_id = list(poll_data.keys())[-1]
stats = votes[poll_id]
await update.message.reply_text(
f"最新统计:\n" +
"\n".join([f": " for opt, cnt in zip(poll_data[poll_id]["options"], stats)])
)
# 主入口
app = ApplicationBuilder().token("YOUR_BOT_TOKEN").build()
app.add_handler(CommandHandler("createpoll", create_poll))
app.add_handler(CommandHandler("stats", poll_stats))
app.add_poll_answer_handler(handle_poll_answer)
app.run_polling()
实际项目中,你需要考虑多选、匿名、并发以及将数据持久化到数据库,以上代码仅展示核心思路。
六、实用建议与注意事项
- 匿名性:匿名投票中,
poll_answer不包含用户信息,仅统计选项;公开投票才有user信息。 - 修改投票:用户可重复投票以修改选择,因此监听更新时要处理“取消旧选”逻辑。
- 自动关闭:使用
open_period或close_date可以自动关闭投票,无需手动调用stopPoll。 - 多选处理:如果允许多选,
option_ids是一个数组,需要相应调整存储结构。 - 数据一致性:使用数据库记录投票状态,避免只依赖内存导致重启丢失。
总结
通过sendPoll创建投票、监听poll_answer实时更新、在结束时调用stopPoll获取最终统计,我们可以构建完整的投票机器人流程。理解这些API的用法和参数,是开发健壮投票功能的基石。希望本文能帮助你快速上手,打造属于自己的Telegram投票工具。