I'm here to ask you a way to ignore incoming messages from a user in python-telegram-bot.
I'm just specifying my situation to let you aware about what the purpose of the code i'm looking for.
So this is a code for a robot, the user sends the command /order and the bot asks which drink the user wants to order.
At this point, in order to avoid useless overlflow, i want to block the specific user (about 5 minutes) whom have just ordered for the sake of leaving the bot "free" for the others users.
Years ago, i looked at the specific option telegram had for groups, such as a timer chat, isn't it?
But i think is no possible at all in the private chat with the bot.
This is a simplified version of the code i'm working on.
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
ConversationHandler,
CallbackContext,
)
WORK = range(1)
def cancel(update: Update, context: CallbackContext) -> int:
"""Cancels and ends the conversation."""
user = update.message.from_user
update.message.reply_text(
'Bye! I hope we can talk again some day.', reply_markup=ReplyKeyboardRemove()
)
return ConversationHandler.END
def order(update: Update, context: CallbackContext) -> int:
update.message.reply_text("please choose a drink")
update.message.reply_text("Sangria | Martini | Analcolico")
return WORK
def work(update: Update, context: CallbackContext)-> int:
ord_drink= update.message.text
update.message.reply_text("Okay i've just received your drink, you can order your drink in 5 MINUTES")
return ConversationHandler.END
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
#blocks the user after the first order for n minutes
conv_handler2 = ConversationHandler(
entry_points=[CommandHandler('order', order)],
states={
WORK : [MessageHandler(Filters.text & ~Filters.command, work)],
},
fallbacks=[CommandHandler('cancel', cancel)],
)
dispatcher.add_handler(conv_handler2)
# Start the Bot
updater.start_polling()
#updater.stop()
# Run the bot until you press Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == '__main__':
main()
LOOK AT IT:
The blocking function for the user must be called after his order, obviously, but the bot should be free for other users
If this bot is running locally you can create a temporary array in which you store the id of the user that just ordered.
At the same time, you start a Job that will execute 5 minutes later and in this Job you pop the id from the array.
# on top of the file
silented_user = []
# in the main function
j = updater.job_queue
# before the order is sent
if update.effective_user.id not in silented_user:
...
# after the order is sent
silented_user.append(update.effective_user.id)
j.run_one(pop_user, 5*60, context={'cid_to_pop':update.effective_user.id})
def pop_user(context):
silented_user.pop(context.job.context['cid_to_pop'])
Related
I want to send a Message(call a function) every day at a given Time. Sadly this is not possible with message.reply_text('Test'). Is there any way i can do this? I could not find anything.
This is my current code:
import telegram.ext
from telegram.ext import CommandHandler, MessageHandler, Filters
import schedule
import time
API_KEY = 'XXXXXXXXXXX'
updater = telegram.ext.Updater(API_KEY)
dispatcher = updater.dispatcher
def start(update, context):
update.message.reply_text('Welcome!')
# problem:
def Test(update, context):
update.message.reply_text('Works!!!')
# running special functions every Day at a given Time
schedule.every().day.at("10:00").do(Test)
while True:
schedule.run_pending()
time.sleep(1)
def main():
# add handlers for start and help commands
dispatcher.add_handler(CommandHandler("start", start))
# start your bot
updater.start_polling()
# run the bot until Ctrl-C
updater.idle()
The schedule part works, I just don`t know how to send this Message.
Thanks for your help!
Update object, inside of the message field, has the from field which is a User Telegram object containing the user's ID.
Once you have the user's ID, you can use the sendMessage method in order to reply him easily.
To conclude, instead of:
update.message.reply_text('Welcome!')
You could do like so:
user_id = update.message.from.id
updater.sendmessage(chat_id=user_id, text="Welcome!")
Is it possible to force one command handler to run another in the same way as if the user did it him/herself, the example below is taken from the repo over at github for ``python-telegram-bot```
The goal is to trigger the /help command when the user chooses a any button from start
"""
Basic example for a bot that uses inline keyboards. For an in-depth explanation, check out
https://git.io/JOmFw.
"""
import logging
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, CallbackContext
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def start(update: Update, context: CallbackContext) -> None:
"""Sends a message with three inline buttons attached."""
keyboard = [
[
InlineKeyboardButton("Option 1", callback_data='1'),
InlineKeyboardButton("Option 2", callback_data='2'),
],
[InlineKeyboardButton("Option 3", callback_data='3')],
]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text('Please choose:', reply_markup=reply_markup)
def button(update: Update, context: CallbackContext) -> None:
"""Parses the CallbackQuery and updates the message text."""
query = update.callback_query
# CallbackQueries need to be answered, even if no notification to the user is needed
# Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery
query.answer()
query.edit_message_text(text=f"Selected option: {query.data}")
def help_command(update: Update, context: CallbackContext) -> None:
"""Displays info on how to use the bot."""
update.message.reply_text("Use /start to test this bot.")
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(button))
updater.dispatcher.add_handler(CommandHandler('help', help_command))
# Start the Bot
updater.start_polling()
# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT
updater.idle()
if __name__ == '__main__':
main()
I looked everywhere and search but no one seems to have a clear and straight forward explanation if this is doable or not
Yes, you can directly call another function with the update and context from the function the program is in. To demonstrate I added a line in your button function. Also mind the rewrites necessary in help_command since it wants to reply to a message. There is no message when this function is called from button:
def button(update: Update, context: CallbackContext) -> None:
"""Parses the CallbackQuery and updates the message text."""
query = update.callback_query
# CallbackQueries need to be answered, even if no notification to the user is needed
# Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery
query.answer()
query.edit_message_text(text=f"Selected option: {query.data}")
help_command(update, context)
def help_command(update: Update, context: CallbackContext) -> None:
"""Displays info on how to use the bot."""
# update.message.reply_text("Use /start to test this bot.")
context.bot.send_message(update.effective_user.id, "Use /start to test this bot.")
If for some reason you'd insist on using the reply_text function, you could rewrite help_command like this:
def help_command(update: Update, context: CallbackContext) -> None:
"""Displays info on how to use the bot."""
if hasattr(update.message, "reply_text"):
update.message.reply_text("Use /start to test this bot.")
else:
context.bot.send_message(update.effective_user.id, "Use /start to test this bot.")
Hope this helps.
Is there a way to send a message (call a function), without a command from the bot's user? For example when a certain condition is met?
Currently I have only been able to call a function with a command.
I have been trying the following:
from telegram.ext import Updater, CommandHandler, CallbackContext
from telegram import Update
from datetime import datetime
import telebot as tb
import logging
bot = tb.TeleBot(API_KEY)
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def messager(update: Update, context: CallbackContext) -> None:
"""this function messages at a specific time"""
update.message.reply_text("message back")
if __name__ == "__main__":
updater = Updater(API_KEY)
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler("message", messager))
condition = False #I have been changing this when testing
if (condition == True):
messager() # how to call messager here? how to pass update and context arguments?
updater.start_polling()
updater.idle()
Any possible way to achieve this would be great.
You cannot call a function using update and context since there is no update from the telegram servers to act on. In other words there is no event to perform a callback on.
Depending on what you want to do you could use a MessageHandler instead of a CommandHandler to reply to any message with Filters to filter out which ones to reply to
or if you want to send a message every time you start your bot and you know who to send a message to (i.e you have their chat_id) you can do
if condition:
updater.bot.send_message(chat_id=CHAT_ID, text="message back")
or if you just want to send a message every time some user starts a chat with your bot you could use the start command which is sent by default to start a chat with a bot
I use python-telegram-bot
this is my main.py
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, CallbackContext
def start(update: Update, context: CallbackContext) -> None:
"""Sends a message with inline buttons attached."""
keyboard = [
[
InlineKeyboardButton("Connect wallet", callback_data='connectwallet'),
],
update.message.reply_text('Please choose:', reply_markup=reply_markup)
def button(update: Update, context: CallbackContext) -> None:
"""Parses the CallbackQuery and updates the message text."""
query = update.callback_query
query.answer()
if query.data == 'connectwallet':
context.bot.send_message(chat_id=chat_id, text=f'This is test msg')
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater('180666756:AAGX__token__WdNO_YOVa7nA35EBXc')
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(button))
updater.dispatcher.add_handler(CommandHandler('help', help_command))
# Start the Bot
updater.start_polling( )
# timeout=300
# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT
updater.idle()
if __name__ == '__main__':
main()
But whenever I shut down main.py, change some code and restart it( Using ctrl+c and then python3 main.py)
Telegram bot freezes and stops responding to user commands. Sometimes it get's back to life, sometimes it doesn't and i need to restart bot from telegram.
I've tried to search a solution but didn't find it.
Any help would be appreciated.
That's because of telegram api limitations and if you are in local host maybe your ram and internet be slow. use heroku for deploying. Hope it will work also if you know threading you can use it it's good with its issue. Also make sure to enable logging if you need codes ask me I will give.
I'm using pyTelegramBotAPI as framework to create a telegram bot.
I'm having some troubles with handle audio messages and I can't understand where I am wrong.
Here my code:
# If user send an audio and it's a private chat
#bot.message_handler(content_types=["audio"])
def react_to_audio(message):
if message.chat.type == "private":
bot.reply_to(message, """What a nice sound! I'm not here to listen to some audio, tho. My work is to wish a good night to all members of a group chat""")
Can anyone help me?
i don't specifically know well how to use pyTelegramBotAPI because also i got problems i couldn't solve so i abandoned it for python-telegram-bot which is better documented in comparison to pyTelegramBotAPI, has a bigger community, is more actively developed and also have an active Telegram group where you can directly ask for help from other developers using this wrapper.
So if you are interested to change to python-telegram-bot, the code for your bot would look something like this:
from telegram import Update
from telegram.ext import Updater, MessageHandler, Filters
token = "" #Insert your token here
def message_handler(update, context):
update.message.reply_text("Hello")
def audio_handler(update, context):
if update.message.chat.type == "private": #Checks if the chat is private
update.message.reply_text("What a nice sound! I'm not here to listen to some audio, tho. My work is to wish a good night to all members of a group chat")
def main():
"""Start the bot."""
updater = Updater(token, use_context=True)
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
# on noncommand i.e message
# Use this if you want to handle also other messages
dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, message_handler))
dispatcher.add_handler(MessageHandler(Filters.audio & ~Filters.command, audio_handler))
# Start the Bot
updater.start_polling()
# Run the bot until you press Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == '__main__':
main()
Here are also some official examples of bots made with this wrapper and the that you can use to better understand the wrapper, if you want more info regard this feel free to DM me on telegram #Husnainn.