首页 > 解决方案 > 如何在电报机器人python代码中立即执行轮询功能?

问题描述

我正在尝试运行一个代码,该代码将在某些事件期间自动发送电报投票,并立即分析答案。

我找到了一个可以实现我想要的示例代码,但我想在运行这段代码时立即执行 self.poll() 而不是等待用户输入'/poll'。我还不熟悉这种编码风格,似乎无法找到这样做的方法......有人可以帮助我吗?

问题主要在代码的第 83 行。(见那部分的评论)

from telegram import (
    Poll,
    ParseMode,
    KeyboardButton,
    KeyboardButtonPollType,
    ReplyKeyboardMarkup,
    ReplyKeyboardRemove,
    Update,
)
from telegram.ext import (
    Updater,
    CommandHandler,
    PollAnswerHandler,
    PollHandler,
    MessageHandler,
    Filters,
    CallbackContext,
)
from telegram import Bot
import time

class TelegramBot:
    def __init__(self, api_key, chat_id):
        self.api_key = api_key
        self.chat_id = chat_id
        self.options = ['0', '1', '2']

    def send_message(self, message):
        self.tel = Bot(token=self.api_key)
        self.tel.sendMessage(self.chat_id, message)

    def poll(self, update: Update , context: CallbackContext) -> None:
        """Sends a predefined poll"""
        options = self.options
        message = context.bot.send_poll(
            update.effective_chat.id,
            "What is the number?",
            options,
            is_anonymous=False,
            allows_multiple_answers=False
        )

        # Save some info about the poll the bot_data for later use in receive_poll_answer
        payload = {
            message.poll.id: {
                "options": options,
                "message_id": message.message_id,
                "chat_id": update.effective_chat.id,
                "answers": 0,
            }
        }
        context.bot_data.update(payload)

    def receive_poll_answer(self, update: Update, context: CallbackContext) -> None:
        """Summarize a users poll vote"""
        answer = update.poll_answer
        poll_id = answer.poll_id
        try:
            options = context.bot_data[poll_id]["options"]
        # this means this poll answer update is from an old poll, we can't do our answering then
        except KeyError:
            return
        selected_options = answer.option_ids
        answer_string = ""
        for option_id in selected_options:
            if option_id != selected_options[-1]:
                answer_string += options[option_id] + " and "
            else:
                answer_string += options[option_id]

        context.bot_data[poll_id]["answers"] += 1
        # Close poll after 50 participants voted
        if context.bot_data[poll_id]["answers"] == 50:
            context.bot.stop_poll(
                context.bot_data[poll_id]["chat_id"], context.bot_data[poll_id]["message_id"]
            )

    def run(self) -> None:
        """Run bot."""
        # Create the Updater and pass it your bot's token.
        updater = Updater(self.api_key)
        dispatcher = updater.dispatcher
        dispatcher.add_handler(CommandHandler('poll', self.poll)) # <---- I want to run self.poll right here when I execute this whole function run(). Currently it's only possible to trigger it by user input command '/poll'
        dispatcher.add_handler(PollAnswerHandler(self.receive_poll_answer))
        # Start the Bot
        updater.start_polling()
        updater.idle()

telegram_bot = TelegramBot('api_key', 'chat_id')
telegram_bot.send_message('/poll') # I tried sending /poll using the bot itself before executing run(), but it does not seem to register bot messages
telegram_bot.run()

标签: pythontelegramtelegram-botpython-telegram-bot

解决方案


poll是一个处理程序回调,即它需要一个传入updatecontext与该更新相关联的工作。更准确地说,您的poll函数使用 中chat_id包含的向 Telegramupdate发送消息、context.bot_data存储数据context.bot并向 Telegram 发出请求。您可以做的是将update- 和 -context相关的逻辑分解到另一个函数中,例如


def poll(self, chat_id, bot, bot_data):
    # what `poll` currently does but replace `update.effective_chat.id` with `chat_id`
   # and `context.{bot_data, bot}` with `bot_data`/`bot`

def poll_callback(self, update, context):
    self.poll(update.effective_chat.id, context.bot, context.bot_data)

self.bot = updater.bot(请注意,如果您将其存储在run- 那么您不需要传递botpoll但可以使用它会更容易self.bot。)

然后你可以调用poll你的run函数

self.poll(some_chat_id, dispatcher.bot_data)

请注意,context.bot_data它总是与 相同的对象dispatcher.bot_data,这就是它起作用的原因。


免责声明:我目前是python-telegram-bot


推荐阅读