I'm programming a telegram bot in Python using the Telegram bot API. I'm facing the problem of managing questions that need an answer of the user. The problem arises when the program is waiting for an answer of one user and another user request information or ask another question before the first user responds.
The Telegram API uses a code to handle the request. When you ask for updates you include a code. If the code you send is higher than a request code, it is mark as handled and telegram delete it and no longer appears in the updates. This code is sequential, so if you mark update 3 as handled, updates 1 and 2 are erased as well.
The question is why is the best phytonic/elegant way to handle multiple requests that needs an answer for the users?
There is not a most pythonic way of doing this. It is a problem you have to program to solve.
Basically, you have to maintain some state variables concerning each user. When a new message arrives, the bot checks what state that user is in, and responds accordingly.
Suppose you have a function, handle(msg), that gets called for each arriving message:
user_states = {}
def handle(msg):
chat_id = msg['chat']['id']
if chat_id not in user_states:
user_states[chat_id] = some initial state ...
state = user_states[chat_id]
# respond according to `state`
This will do for a simple program.
For more complicated situations, I recommend using telepot, a Python framework I have created for Telegram Bot API. It has features that specifically solve this kind of problems.
For example, below is a bot that counts how many messages have been sent by an individual user. If no message is received after 10 seconds, it starts over (timeout). The counting is done per chat - that's the important point.
import sys
import telepot
from telepot.delegate import per_chat_id, create_open
class MessageCounter(telepot.helper.ChatHandler):
def __init__(self, seed_tuple, timeout):
super(MessageCounter, self).__init__(seed_tuple, timeout)
self._count = 0
def on_message(self, msg):
self._count += 1
self.sender.sendMessage(self._count)
TOKEN = sys.argv[1] # get token from command-line
bot = telepot.DelegatorBot(TOKEN, [
(per_chat_id(), create_open(MessageCounter, timeout=10)),
])
bot.notifyOnMessage(run_forever=True)
Run the program by:
python messagecounter.py <token>
Go to the project page to learn more if you are interested. There are a lot of documentations and non-trivial examples.
In my bots I use webhooking. If you can to use web hooks - do it, it's more comfortable way to interactive with telegram bots.
If you can't webhooking (ssl problems, for example), there is workaround for you. Use ForceReply in order to get previous bot answer and write logic based on user replies.
Check if update contains reply (reply_to_message key), then make bot answer based on this reply. These actions must be asynchronous in order to get high bot performance.
If you are python programmer, I recommend Tornado for these purposes.
Related
My goal is to make a Telegram Bot using Python that does the following:
The user types a command
The bot explains what the user should type next.
The user types certain information
I use that info to fetch a value in a python dictionary.
The bot replies with that info
I have already created the bot and set the command. The problem is that I don't know how to keep the bot "listening" . I have looked up in the docs but I have only found getUpdates, which gets the user's responses but only when you hit run.
res=requests.get(url=f"https://api.telegram.org/bot{bot_token}/getUpdates")
I would like to set a webhook, and I know there is a method for this but I'm not shure about how this works.
When you are a PHP programmer, setting the webhook through a URL and using setWebhook would do the trick and telegram will send the result to this link whenever a user sends an update to the bot. But, Python programmers have to use a different approach, I think. The main, and while, the easiest approach to make the bot listen permanently to the request is to python-telegram-bot module.
There are a few links that can help to build your first pythonic bot that can respond to users' updates.:
Python-Telegram-Bot Repository, which is the repository of the module.
A few examples of bots created using this module, can give you insight into the process of creating your first bot.
A conversation bot
i'm developing a python telegram bot and i have a script that is always running (for receiving new command from telegram) and i want the bot to send messages when the user perform a action in a website.
example: the user start the bot, the bot send a link to perform an action in the website (like login to the user's account and connect the telegram id with the user id) and then send a confirmation message on telegram that all's good.
my problem is how i can tell the python script that the action in the browser is done? for now i'm constantly query a database but my solution is pretty dumb because if the user don't perform any action the query can go forever.
any suggestion how to do it correctly?
thx <3
I see two viable solutions here:
Send the message directly from the website. While only one process is allowed to fetch updates at a time, you can make other requests from as many servers as you like. Depending on how your website works, you can make a plain HTTP request to the Bot API or use an API wrapper like python-telegram-bot or a wrapper in a different language to make the request. e.g. if you're running a php-based website, you could use a php API wrapper.
If for some reason 1. is not an option for you, you can try to inform your running process about the user login. the PTB FAQ have an entry that should help you get started. If your website & bot are running on the same server, it might be possible to make the update_queue directly available to the website process. If not, you can try to set up a webhook for your bot and post an update to the webhook that you then enqueue into the update_queue
Approach 1. has the downside that you don't have all the bot logic in one place, but it should be by far easier to implement than 2.
Disclaimer: I'm currently the maintainer of python-telegram-bot
I have 2 discord client instances a bot and a user account. I have already figured out how to copy messages from one channel to another channel, basically a on_message event. However, I want to know if there is a way I can use the user account to fetch the messages, I've tried fetching messages in different guilds but they didn't work because the bot was not in the server and the bot is fetching messages. I've tried using the user account instance to do it but it didn't really work.
The comments were there as a guide for myself because I'm not that familiar with Python it's fairly new to me. If anyone knows how I can use the user account to get or fetch the messages I'd appreciate the help...
PS: I know that some of the code isn't needed, I haven't removed anything that isn't needed. I wanted to actually finish the project before inspecting it.
I just wanted to know that I have tried this myself and it is not possible. Because from discord.py's Docs. Which you can find down below, does not allow users (user account) to transfer data to a bot since you would need to request from discord API which leads to user getting banned (Very quickly) theere are some work arrounds but I would suggest not doing so since self botting is against the TOS of discord
https://discordpy.readthedocs.io/en/stable/
EDIT: Another thing is that discord API blocks users from fetching or getting anything using a user account with discord.py
I am making a discord bot and I want to know how I can add a basic implementation of seeing which users are active daily on the server and how long they're active. The definition of active is not accurate but it could be if they sent a message in the group throughout the day. What would be the code to implement something like this in my discord bot? Thanks a lot!
Checking to see who has sent a message is simple enough to do,
You could use the on_message function to see who has sent a message in your server, using this method you could get the user and append them to a list and then delete the list every so often (eg. daily, or you could wait for an admin to call a command within the server).
The positive side of this method is that you can control what counts as active, for example you could also use on_reaction_add and its opposite.
This is a simple example of a bot that checks the users that have sent messages in the server and adds them to a list. Note: This script doesn't delete the list, meaning that members will be permanently in the active list, you should be able to implement this in your code fairly easily.
import discord
client = discord.Client()
activeMembers = [] #We create an empty list to hold the users that have been active
#client.event
async def on_message(message):
if message.author not in activeMembers:
activeMembers.append(message.author)
client.run("YOUR TOKEN HERE")
I've missed out some things that you probably have if you've started your bot already. If you haven't, fear not as there are multiple articles and tutorials on creating a bot.
The problem is that you want to see how long a member is active on your server, so what you could do is log the times they have sent messages, and then calculate the time they've been active on the server by deducting one value for another. This isn't accurate as you've stated, but is the best solution in my mind. The biggest problem here is that someone could send a message early in the morning and then go off about their day and then send a message at night, this would mean that the bot would think they are active for many hours (seeing as their first message was sent much much earlier) when in fact they are not. A simple workaround is to check every users last message time, and use a threshold time (if you will) to see who is no longer active.
For example, if someone sent their last message half an hour ago, they would no longer be seen as active and their total time would be calculated based on their first message and their last message. Their data would then be purged, so that if they send a message much later on, the bot doesn't use their first message of the day to calculate how long they've been on for.
Looking back on this this explanation is a bit shoddy, so Ill try quickly summarise it in a timeline sort of fashion.
A user sends a message in a channel and the bot records their id and the time they sent it -> They send another message five minutes later, the bot records the same data -> The user hasn't sent a message in half an hour (example of a threshold time, you could make yours shorter or longer) and the bot calculates their time and removes their message times. This time is then added to their total time.
This can be done using .create_task() where you pass in a function to run in the background. The function you would pass would regularly check when users sent their last message.
Should you want to define active as things other than reactions or sending messages, visit discord.py to find out the different things you can do.
Best of luck,
Ben
I'm building a chatbot with wit.ai and python and integrating it with Facebook Messenger. I have set up webhooks as well as send function and fb_message function exactly like in this tutorial: https://github.com/wit-ai/pywit/blob/master/examples/messenger.py
My bot works fine when I test it in wit.ai or in console, but when I test it in actual Facebook Messenger, it gives each reply twice. It doesn't matter which function inside the bot gets called, I always get two replies.
My most simple action is this:
def defaultAnswer(request):
context = request['context']
return context
(This returns always the same string, which is defined in wit.ai engine.)
If your bot is subscribed to events other than pages_messaging, like messaging_deliveries, make sure you're handling this event as well.
What's happening is your that bot is receiving the message request, then receiving another one by another event, and your code is handling them both as messages.
I think this is the problem, and if it's not, give us more details about it.
Someone might have a case like mine.
My case:
I mistakenly subscribe my two different bots to one facebook page on the developer.facebook.com.
Due to the this mistake, when i write a specific command(e.g. restart) to my facebook page, bot replies exactly same two messages(e.g. "Bot Restarted", "Bot Restarted") to me.
It made me a crazy to find out the problem.
You should subscribe one bot to your facebook page at most.
I had this issue before and it turns out, the message_echoes was enabled. What happens essentially if this is enabled is that the Bot will try to echo whatever you text you entered.
My logic ended up catching the echo and then responded with the same response. I do have a handler to catch similar responses so I was able to avoid the infinite loop.