I am trying to run a code that will automatically send out a telegram poll during certain events, and analyze the answers immediately.
I found an example code that can achieve what I want but I would like to execute self.poll() immediately upon running this piece of code instead of waiting for a user to input '/poll'. I am not yet familiar with this style of coding and can't seem to find a way to do so... could someone help me out?
The issue is mainly in line 83 of the code. (see comment on that part)
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()
poll
is a handler callback, i.e. to work it needs an incoming update
and the context
associated with that update. More precisely, your poll
function uses the chat_id
contained in the update
to send the message to, context.bot_data
to store data in and context.bot
to make the request to Telegram. What you can do is factor out the update
- and context
-related logic into another function, e.g.
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)
(Note that it would be even easier if you e.g. stored self.bot = updater.bot
in run
- then you don't need to pass bot
to poll
but can just use self.bot
.)
Then you can call poll
in your run
function as
self.poll(some_chat_id, dispatcher.bot_data)
Note that context.bot_data
is always the same objects as dispatcher.bot_data
, that's why this works.
Disclaimer: I'm currently the maintainer of python-telegram-bot