I have created a bot (using python-telegram-bot) that upon choosing a type of query, the bot should randomly choose one of the available strings as the reply.
My function to create replies is as follows:
def generate_reply():
replies = """
Hello
Goodbye
Thanks!
Your welcome!
See you around!""".splitlines()
r = random.choice(replies).strip()
return r
And the functions to reply to the users are as follows:
#Inline Reply
def inlinequery(update, context):
query = update.inline_query.query
results = [InlineQueryResultArticle(id=uuid4(), title="Interact",
input_message_content=InputTextMessageContent(
generate_reply()))]
update.inline_query.answer(results)
#Normal reply
def reply(update, context):
update.message.reply_text(generate_reply())
And after creating the bot I add it to the bot using:
dp.add_handler(CommandHandler("reply", reply))
dp.add_handler(InlineQueryHandler(inlinequery))
when I use /reply in chat it works as intended, but wherever I use an inline command in a chat with another user or a group, the random choice apparently stops working.How can I get around this problem?
I found out the answer to my question. Apparently Telegram caches the answers to similar inline queries for some time. For this to work correctly you should set cache_time to something you'd like, in my case 0.
#Inline Reply
def inlinequery(update, context):
query = update.inline_query.query
results = [InlineQueryResultArticle(id=uuid4(), title="Interact",
input_message_content=InputTextMessageContent(
generate_reply()))]
update.inline_query.answer(results, cache_time=0)
Related
I'm currently working on a bot that, messages Users in a given json-file in certain time intervals. I tried this code but it doesn't do what it's supposed to nor does it give me an error I could work with.
#tasks.loop(seconds=10)
async def dm_loop():
with open("users.json" "r") as file:
users = json.load(file)
for stgru in users:
for i in users[stgru]:
user = await client.fetch_user(i)
await user.send("hello")
And just in case you're wondering: the short time Intervals and the unnecessary message: "hello", ist just for testing purposes. The "users.json"-file, mentioned in the code, has a format like this:
{
"724": ["name1#2819", "name2#2781", "name3#2891"],
"727": [],
"986": ["name4#0192"],
"840": ["name5#1221", "name6#6652"],
"798": ["name7#3312", "name8#8242", "name9#1153", "name10#3318"]
}
I already added the "dm_loop.start()"-method to my "on_ready()" but it's not working at all.
I'd be so glad if anyone could help me out here. Thanks
According to the docs, fetch_user looks up users by their ID, so you need to store the user ID instead of the user name.
https://discordpy.readthedocs.io/en/master/ext/commands/api.html?highlight=fetch_user#discord.ext.commands.Bot.fetch_user
Otherwise you can create your own UserConverter. Here's an example on how you would do that.
from discord.ext import commands
[...]
user_name = "some_tag#1234"
user = await commands.converter.UserConverter().convert(ctx, argument=user_name)
await user.send("Hello")
I do really recommend the first option though, it is a lot simpler. Since you would have to create a custom context if you are not using this in a command i believe.
I am currently using python-telegram-bot library to make a telegram bot. My problem is I am trying to have my bot respond back when using the inline command. So when a user sends the bot #botname 'text', I want the to store the 'text' as a string and then have my bot send something back with that variable.
For some reason I can not get this to work. I tried the code below, but it doesn't work...I also posted the example from the github that works but not in the way i want.
My code
def inlinequery(update, context):
"""Handle the inline query."""
query = update.inline_query.query
text = query.message_text
print(text)
update.message.reply_text(text)
Example Code
#Sends message when #botname is used
def inlinequery(update, context):
"""Handle the inline query."""
query = update.inline_query.query
results = [
InlineQueryResultArticle(
id=uuid4(),
title="Caps",
input_message_content=InputTextMessageContent(
query.upper())),
InlineQueryResultArticle(
id=uuid4(),
title="Bold",
input_message_content=InputTextMessageContent(
"*{}*".format(escape_markdown(query)),
parse_mode=ParseMode.MARKDOWN)),
InlineQueryResultArticle(
id=uuid4(),
title="Italic",
input_message_content=InputTextMessageContent(
"_{}_".format(escape_markdown(query)),
parse_mode=ParseMode.MARKDOWN))]
update.inline_query.answer(results)
def main():
# Get the dispatcher to register handlers
dp = updater.dispatcher
dp.add_handler(InlineQueryHandler(inlinequery))
# Start the Bot
updater.start_polling()
if __name__ == '__main__':
main()
You can use the User object of the inline query to send them a message. Keep in mind that the user has to have started a private chat with the bot before the bot can send them messages.
I modified your attempt. It should work, but i have not tested it:
def inlinequery(update, context):
"""Handle the inline query."""
query = update.inline_query
text = query.query
print(text)
query.from_user.send_message(text)
Related docs:
InlineQuery.user
User.send_message
I'm using telebot (https://github.com/eternnoir/pyTelegramBotAPI) to create a bot to send photos to its users. The point is I didn't see a way to restrict the access to this bot as I intend to share private images through this bot.
I read in this forum that through python-telegram-bot there is a way to limit the access from the sender's message (How To Limit Access To A Telegram Bot), but I didn't know if via pyTelegramBotAPI it is possible.
Do you know how can I solve it?
A bit late tot the party - perhaps for future post readers. You can wrap the function to disallow access.
An example below:
from functools import wraps
def is_known_username(username):
'''
Returns a boolean if the username is known in the user-list.
'''
known_usernames = ['username1', 'username2']
return username in known_usernames
def private_access():
"""
Restrict access to the command to users allowed by the is_known_username function.
"""
def deco_restrict(f):
#wraps(f)
def f_restrict(message, *args, **kwargs):
username = message.from_user.username
if is_known_username(username):
return f(message, *args, **kwargs)
else:
bot.reply_to(message, text='Who are you? Keep on walking...')
return f_restrict # true decorator
return deco_restrict
Then where you are handling commands you can restrict access to the command like this:
#bot.message_handler(commands=['start'])
#private_access()
def send_welcome(message):
bot.reply_to(message, "Hi and welcome")
Keep in mind, order matters. First the message-handler and then your custom decorator - or it will not work.
The easiest way is probably a hard coded check on the user id.
# The allowed user id
my_user_id = '12345678'
# Handle command
#bot.message_handler(commands=['picture'])
def send_picture(message):
# Get user id from message
to_check_id = message.message_id
if my_user_id = to_check_id:
response_message = 'Pretty picture'
else:
response_message = 'Sorry, this is a private bot!'
# Send response message
bot.reply_to(message, response_message)
I would like to forward every updates from channels to my bot.
Is it Possible with ForwardMessagesRequest ?
I tried to use this Telethon example to build my personal code:
https://github.com/LonamiWebs/Telethon/wiki/Forwarding-messages
But i wasn't able to do it. And i don't know if it's possible to use that part of code inside a callback function. Someone can help me? Thank you
Ok, i'm really confused so let's go back.
In this code I just try to retrieve last messages from an user chat and forward them to my bot:
def callback(update):
source_chat_id = "here i put the user id"
source_hash = "here i put his access_hash"
source_chat = InputPeerUser(source_chat_id, source_hash)
total_count, messages, senders = client.get_message_history(
source_chat, limit=10)
for msg in reversed(messages):
print ("msg:", msg.id, msg)
msg = messages[0]
print ("msg id:", msg.id)
dest_chat = "here i tried to put the number of my bot ID"
result = client.invoke(ForwardMessagesRequest(from_peer=source_chat, id=[msg.id], random_id=[generate_random_long()], to_peer=dest_chat))
client.add_update_handler(callback)
The print was correct but i didn't receive anything to my bot chat.
I know that there will be a lot of errors so please be patient and sorry.
I try use python-telegram-bot
I do not understand how to handle InlineKeyboardButton correctly.
def start(bot, update):
currencies = [currency for currency in API().get_currencies()]
keyboard = [[InlineKeyboardButton("{}".format(c), callback_data='{}'.format(c))] for c in currencies]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text('Select the currency you want to exchange:', reply_markup=reply_markup)
updater.dispatcher.add_handler(CommandHandler('start', start))
Now, I need to process the selection by passing it to another function with the help of ChosenInlineResultHandler, but I do not understand how to do this.
You are using Inline Buttons and the query coming back is simply CallbackQuery but not InlineQuery, yes the names are a bit confusing by the Telegram Bot API.
You can use telegram.ext.CallbackQueryHandler to catch the queries upon buttons pressed.
def button_callback(bot, update):
# data is the callback_data where you declared in the buttons
query = update.callback_query.data
if query == "something":
# do something here
updater.dispatcher.add_handler(CallbackQueryHandler(button_callback))
This is a minimal example of how to catch the buttons' data. You can check here for a complete example.