i have this code for the message:
#FBot.message_handler(commands=["spy"])
def SpyInit(message):
spyInstance = game.Spy(1, message)
markup = types.InlineKeyboardMarkup()
startButton = types.InlineKeyboardButton("start", callback_data=spyInstance.id.id)
markup.add(startButton)
message = FBot.reply_to(message, "reply on this message to be added to the game", reply_markup = markup)
SpyList.append(spyInstance)
and this:
#FBot.callback_query_handler(func=lambda call : True)
def callback_query(call):
print(call.data)
for instance in SpyList:
if call.data == instance.id.id:
instance.Start()
Spy = instance
for player in Spy.PlayerList:
if Spy.spy == player:
FBot.send_message(player.id, "you are the spy")
else:
FBot.send_message(player.id, Spy.word)
the problem is, i get the first message with the start button but clicking the button does nothing.
Related
ive been trying to create a stream client using tweepy to fetch new tweets under a user-given hashtag. I've managed to achieve this using the following code successfully.
import tweepy
class IDPrinter(tweepy.StreamingClient):
def on_tweet(self,tweet):
#now = datetime.now()
#current_time = now.strftime("%H:%M:%S")
#print("Current Time =", current_time)
print(f"{tweet.id} \n {tweet.created_at} \n {tweet.author_id} \n {tweet.text}")
#https://docs.tweepy.org/en/v3.4.0/streaming_how_to.html
def on_error(self, tweet_code):
if tweet_code == 420:
return False
def cleanUP(self,printer):
print("test")
rule_ids = []
rules = printer.get_rules()
if str(rules).find("id") == -1:
print(rules)
return
else:
for rule in rules.data:
rule_ids.append(rule.id)
if(len(rule_ids) > 0):
printer.delete_rules(rule_ids)
print("rules have been reset")
else:
print("no rules to delete")
def Caller(self,value,printer):
#print("test")
printer.add_rules(tweepy.StreamRule(f"#{value} lang:en -is:retweet"))
printer.filter(expansions="author_id", tweet_fields="created_at")
But I want the user to be able to stop the stream of new tweets whenever he wants to. Ive been testing the following code but I can't get the tweepy stream loop to terminate on button click. This is my current attempt but I can't understand why is not working.
def on_button_clicked(event):
global break_cicle
break_cicle = False
print("Button pressed: break_cicle:", break_cicle)
class IDPrinter(tweepy.StreamingClient):
def on_tweet(self,tweet):
print(f"{tweet.id} \n {tweet.created_at} \n {tweet.author_id} \n {tweet.text}")
#https://docs.tweepy.org/en/v3.4.0/streaming_how_to.html
def on_error(self, tweet_code):
if tweet_code == 420:
return False
def cleanUP(self,printer):
print("test")
rule_ids = []
rules = printer.get_rules()
if str(rules).find("id") == -1:
print(rules)
return
else:
for rule in rules.data:
rule_ids.append(rule.id)
if(len(rule_ids) > 0):
printer.delete_rules(rule_ids)
print("rules have been reset")
else:
print("no rules to delete")
def Call(self,value,printer):
while break_cicle:
button.on_click(on_button_clicked)
printer.add_rules(tweepy.StreamRule(f"#{value} lang:en -is:retweet"))
printer.filter(expansions="author_id", tweet_fields="created_at")
time.sleep(1)
printer = IDPrinter("bearer key")
printer.cleanUP(printer)
hashtag = input("Give a hashtag: ")
button = widgets.Button(description="STOP!")
output = widgets.Output()
display(button, output)
break_cicle = True
button.on_click(on_button_clicked)
threading.Thread(target=printer.Call(hashtag,printer)).start()
basically i tried to create a button which on event click will change the variable break_circle and terminate the while loop onside def call.
I am trying to do an optional input, and have this code
bot.send_chat_action(message.from_user.id, 'typing')
markup = types.InlineKeyboardMarkup()
markup.add(types.InlineKeyboardButton("Лечу только в одну сторону", callback_data="one_way"))
msg = bot.send_message(message.from_user.id, '✅Хорошо. Теперь введите дату возвращения:', reply_markup=markup)
bot.register_next_step_handler(msg, get_return_date)
This code sends user a message with button to skip this step, and registers function get_return_date(), that waits for a date value. Message
And if user clicks the button, query handler register another function get_adults(), that waits for numeric value:
#bot.callback_query_handler(func=lambda call: call.data == "one_way")
def is_one_way(call):
msg = bot.send_message(call.from_user.id,
'✅Хорошо. Сколько взрослых (пассажиров старше 12-ти лет на момент полёта) полетят 🤵👩💼?')
bot.register_next_step_handler(msg, get_adults)
return
And, trouble is that - if user clicks the button to skip, both get_return_date() and get_adults() are waiting for a value and work at one time:
Problem
Any ideas what should i do?
You can do this:
bot.send_chat_action(message.from_user.id, 'typing')
msg = bot.send_message(message.from_user.id, '✅Хорошо. Теперь введите дату возвращения: (you can skip this passage with /skip)')
bot.register_next_step_handler(msg, get_return_date)
def get_retourn_date(message):
if message.text == '/skip':
get_adults()
return
# write here the actual function code
i use query callbacks and i put this func at the begining of the callback:
bot.clear_step_handler_by_chat_id(call.message.chat.id)
u can use it like this
def gen_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton("Button 1", callback_data="one"),
InlineKeyboardButton("Button 2", callback_data="two"))
def ButtonOneFunc(message):
#do whatever u want here
def ButtonTwoFunc(message):
#do whatever u want here
#bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
bot.clear_step_handler_by_chat_id(call.message.chat.id)
if call.data == "one":
sent= bot.reply_to(call.message, "This is Button 1")
bot.register_next_step_handler(sent, ButtonOneFunc)
elif call.data == "two":
sent= bot.reply_to(call.message, "This is Button 2")
bot.register_next_step_handler(sent, ButtonTwoFunc)
what will happen here is, whenever the user will click a button, it will clear all next_register_handler that were open
and then enter the new call.data and set the handler which the user clicked on
Is it available to wait inline button push or text message simultaneously in Telethon conversation?
async with bot.conversation(chat_id) as conv:
buttons = [[Button.inline('Yes'), Button.inline('No')]]
conv.send_message('To be or not no be? Answer yes|no, or write your own opinion', buttons=buttons)
#This way we can wait for button press
def press_event(user_id):
return events.CallbackQuery(func=lambda e: e.sender_id == user_id)
press = await conv.wait_event(press_event(sender_id))
#...and this way we can wait for text message
response = await conv.get_response()
#And how can we wait for press event OR text message simultaneously?
So, here is the solution (thanks to Lonami)
#bot.on(events.NewMessage(pattern='/test'))
async def worklogs(event):
chat_id = event.message.chat.id
sender = await event.get_sender()
sender_id = sender.id
async with bot.conversation(chat_id) as conv:
def my_press_event(user_id):
return events.CallbackQuery(func=lambda e: e.sender_id == user_id)
buttons = [[Button.inline('Yes'), Button.inline('No')]]
await conv.send_message('To be or not no be? Answer yes|no, or write your own opinion', buttons=buttons)
tasks = [conv.wait_event(my_press_event(sender_id)), conv.get_response()]
done, pendind = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
event = done.pop().result()
if type(event) is events.callbackquery.CallbackQuery.Event:
selected = event.data.decode('utf-8')
print(f'Got button: "{selected}"')
elif type(event) is tl.patched.Message:
message = event.text
print(f'Got text message: "{message}"')
I'm building a Telegram bot with the library https://github.com/eternnoir/pyTelegramBotAPI
I'm trying to make when I press a menu button, it sends a message to the user.
How could I do it?
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
TELEGRAM_TOKEN = '<TOKEN>'
bot = telebot.TeleBot(TELEGRAM_TOKEN)
def gen_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton("Yes", callback_data="cb_yes"),
InlineKeyboardButton("No", callback_data="cb_no"))
return markup
#bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
if call.data == "cb_yes":
bot.answer_callback_query(call.id, "Answer is Yes")
elif call.data == "cb_no":
bot.answer_callback_query(call.id, "Answer is No")
#bot.message_handler(func=lambda message: True)
def message_handler(message):
bot.send_message(message.chat.id, "Yes/no?", reply_markup=gen_markup())
bot.polling(none_stop=True)
You can use data of your call object as the user id(call.from_user.id) of the sender to send a message:
if call.data == "cb_yes":
bot.answer_callback_query(call.id, "Answer is Yes")
bot.send_message(call.from_user.id,"Your answer was Yes!")
elif call.data == "cb_no":
bot.answer_callback_query(call.id, "Answer is No")
bot.send_message(call.from_user.id,"Your answer was No!")
I am building a telegram robot with python-telegram-bot
I want to do something in the loop and the user clicks on the menu to stop that command in the loop.
But the back button and menu do not work, so the back button does not work until the loop is finished.
my code
def callback_menu(update, context):
if update.message.text == "menu":
update = update.message
key = [["🔔 shopping line"], ["🛒 Sales queue"]]
markup = ReplyKeyboardMarkup(key, one_time_keyboard=True, resize_keyboard=True)
update.reply_text('Select', reply_markup=markup)
if update.message.text == '🔔 shopping line':
key = [["menu"]]
markup = ReplyKeyboardMarkup(key, resize_keyboard=True)
list = ["saba", "vmelate", "folad", "shasta", "zobe"]
for i in list:
if update.message.text!="🔔 shopping line":
break
update.message.reply_text('{}shopping line ✅'.format(i), reply_markup=markup)
time.sleep(random.randrange(1, 4))
updater.dispatcher.add_handler(MessageHandler(Filters.text, callback_menu))