Get poll's results and user selections from Telegram's bot API - python

I would like to know if there is a way to find user's replies to a non anonymous poll, using bot API.
I'm able to get the number of votes, but I would like to know the actual choice from a specific user.

Yes, for non-anonymous polls you get an update when a user makes a vote. Those are the updates with update.poll_answer, see https://core.telegram.org/bots/api#update and https://core.telegram.org/bots/api#pollanswer.
Because you used the corresponding tag, I'm assuming that you're using the python-telegram-bot library. In that case you can use the PollAnswerHandler to catch those updates. Please also have a look at the pollbot.py example, which summarizes some common use cases for polls.
Disclaimer: I'm the maintainer of python-telegram-bot.

Related

Users banned by my Telegram bot do not stay banned?

TL;DR: Methods listed in "Attempts" are not working as they should. Whenever I run those Python methods, they end up only kicking the user (or maybe banning them for at maximum 2-3 minutes), regardless if I include until_date or not. All group permissions are enabled and in BotFather both group privacy mode and "allow groups?" are disabled.
I am new to Stack Overflow, so I'm not sure if the formatting of my question is fine and if a lengthy description is preferable.
Context: I have a (private) Telegram group with a little bit over 700 users. There are two other admins and five bots (Rose, Group Help, Combot and two that I coded). In the past couple of weeks I have been facing issues with banning users through my own bot, while Rose and Group Help bots seem to be able to.
Issue: My bot limits the amount of entries (per user) to the group to avoid people lurking, or just raiding the group when I share an invitation link. Group help bot and Rose kick people out if they don't solve the captcha and present themselves in the first 5 minutes upon entering. I keep Combot to avoid letting known spammers in my group. The problem I'm facing is that whenever the ban is issued by my own bot, the user will simply be kicked out. I tried various methods to ban a user in my Python script, but nothing worked. I tried switching from python-telegram-bot to AIOgram, but it still doesn't work. I am not sure if it's caused by a conflict between bots (which wouldn't make much sense), wrong methods, or if it's a group/account-related problem. I tried my bot in a "test group" and it worked fine.
Screenshot of an example of the anomaly from the group logs channel: Since I can't embed pictures yet, here is the imgur link.
Part of the current (pseudo)code using AIOgram:
#dp.message_handler(content_types=["new_chat_members"])
async def newUser(message: types.Message):
for user in message.new_chat_members:
con = psycopg2.connect(...)
#[...SQL query fetching number of entries of a user...]
if "DB is empty":
#..Initialize..
else:
cur.execute(sql_script) #cur is the cursor
#Returns a list with at most one tuple, where the first instance is the number of entries
entries_list = cur.fetchall()
if len(entries_list) == 0 or None:
#Adds user to a table in Heroku DB and initializes entry = 1
insertUser(tablename, userid, 1)
await bot.send_message(channel_id, log_message)
con.close()
elif entries_list[0][0] < 2:
updateUserEntries(tablename, entries_list[0][0] + 1, userid)
await bot.send_message(channel_id, log_message)
con.close()
else: #Ban on third entry
await chat.kick(userid, until_date = datetime.now() + timedelta(hours = 6))
await bot.send_message(chat.id, ban_message)
await bot.send_message(channel_id, log_message)
#Removes user from the table (i.e. resets the entry count)
removeUser(tablename, userid)
con.close()
Attempts: The methods I tried using to ban users with are:
update.effective_chat.ban_member(chat_id, user_id) (python-telegram-bot),
bot.kick_chat_member(chat_id, user_id) (python-telegram-bot),
bot.ban_chat_member(chat_id, user_id) (python-telegram-bot – which suggested me to use kick_chat_member instead) and
message.chat.kick(user_id) (aiogram – where message is passed whenever a new user joins the group through Dispatcher.message_handler(content_types='new_chat_members')).
I originally only wanted to temporarily ban the users, so there should be an extra until_date parameter too. But I also tried permanently banning them, which according to the documentation any time less than 30 seconds or more than 366 days counts as a permanent ban. Nothing worked. (By the way, the script in general works and runs great. I am not sharing the full script because I am not comfortable with it being public, and the problem also does not pertain to the whole script anyways.)
Further details: My bot has all group permissions enabled except for adding admins and "remain anonymous". In BotFather it has both group privacy mode and "allow groups?" disabled (because I only use it for my group). At the moment the library I'm using for the bot (in Python) is AIOgram. Previously, it was all written using python-telegram-bot. I am using it in conjunction with psycopg2 to store user data in Heroku's database. At one point I even tried creating a "ban table" in my database, but it still failed to keep the users out since the ban didn't actually ban people. The ban actually only acts as a "kick".
I was thinking about setting up a webhook, but I am not familiar with Flask or Django, and webhooks in general. So that might take me some time. However, I'm not sure it would make a difference since it should not differ much, except maybe speed and memory wise.
I am not sure what I'm doing wrong. I tried to solve the problem in every way that I am capable of (considering that I am pretty new to Telegram API and Telegram python libraries, especially AIOgram).
If anyone has any ideas on how I can go about solving this issue, I would really appreciate it!
(Sidenote: I contacted Telegram support more than a week ago, but I haven't received any response.)
It's not obvious to me what goes wrong here, but I have a few hints/remarks:
which library you use to make the api request should be irrelevant. you can even make the request manually via the browser/curl/whatever if you like to
webhooks have nothing to do with this - how you fetch updates is indpendent of making requests to the api
python-telegram-bot interprets timezone-naive datetimes as UTC - that may have an effect how you pass the until_date
Dislaimer: I'm currently the maintainer of python-telegram-bot.
Thank you, #CallMeStag for your remarks! I ended up "solving" the problem as I describe below. Although, I am still not sure why this worked but using any of the methods I listed in the question didn't.
Disclaimer: This is not an efficient way to approach the issue, and I do not guarantee it will work. I also don't have a high traffic of people joining the group, so these solutions might not work for you.
Partial (non-)solutions: I think there is a "phantom issue" between my bot and Telegram. Somehow Telegram (or Python, I'm not sure) doesn't understand the "kick" methods as "ban", whether I include until_date or not. (Also, Telegram support is non-existent). So, I thought of three (or four) alternative ways to ban someone without having to actually ban them:
Solution 1: Create a table in your database that will contain all the users that you will eventually ban. For your "ban" function, include a message handler that listens for new chat members. Whenever a new user joins (use new_chat_members to catch the event), make it run through all the entries in the table you created (e.g. you could use SELECT COUNT(*) FROM {BANTABLENAME} WHERE USERID = {USERID}) so that it will tell you if the user is banned. If the query returns a value greater than 0, you can just make an IF statement and kick the user out. (You can obviously make it a bit more complicated by manually adding an until_date). The downside is that it can fail to keep a user out since there is a bit of latency/delay when you run SQL queries.
Solution 2: This solution still requires that you create a table of banned users in your database. But instead of letting people join your group directly, direct them to your bot's chat first. Add a command handler for "/start". Whenever a user starts the bot, make it run through the table entries and depending on the result, the bot will either reply with the group link or a message informing them that they can't join (or nothing).
Solution 3: Set up a webhook. I don't know how to do it yet, so you should look it up on the internet. It will require you to learn at least Flask, or Django. This is definitely a nicer solution compared to the other ones. Usually, this "ban problem" does not pertain to whether you're using a webhook or not (like CallMeStag said). But compared to my next proposal (which works somehow), this is definitely a better practice.
Solution 4 (Verified): I was curious and wanted a more direct solution, so I decided I would just try manually making requests through www.api.telegram.org/bot<TOKEN>/METHOD?PARAMETERS using GET and POST HTTPS methods in Python. This is definitely not an ideal solution if you have a high traffic of users. Because you might get errors due to too many requests. Also, depending on what you're trying to do, it might be too slow. So definitely use webhooks instead. In my case, I only need to POST the ban using the banChatMember method, which also happens with a pretty low frequency. So I should not encounter problems. (I will update if I do).
Further doubts: I am not sure why solution 4 works, but directly banning with python-telegram-bot or AIOgram doesn't. I did not try Telethon or Pyrogram. They should be similar, but they also allow you to log-in as a user (i.e. it will start a session of your account through the bot), which could potentially work.
Update: It doesn't work. Banned users still don't get banned. It only works when I manually do it for some reason. The whole thing really doesn't make any sense. It's like it doesn't work while polling, but it works if I manually send out www.api.telegram.org/bot<token>/banChatMember?chat_id=<chatid>&user_id=<userid>.

How to send messages to multiple users via bot to individually irrespective of others in discord.py?

So, I'm making a text based game and I want that whenever a user types a command my bit DMS the user and starts the story for that user. I'm not sure how to do this for multiple users. Like if a game has already been initiated and someone else wants to start a new one they should be able to irrespective to the progress of the user that is already playing
Well since you haven't provided any code it will have to be a description based answer.
For storing data in cache use a dictionary
data = {}
...
data[member.id] = {level: 0, money: 0}
This would storage the variables level and money inside the data variable you can access it with data[member.id].
If you are wanting to store data over long term have a look at databases such as MongoDB or MySQL/MariaDB.
Your code must be async otherwise there will be blocking while things are being calculated. For example, if you are fetching data using requests use aiohttp or another asynchronous library for it.

How to send different messages to users with different settings? discord.py

First of all, I'm a beginner at discord.py. It's hard to explain my problem but I'll try my best:
I'm trying to make a single command which sends different messages to users with different settings.
For example:
Let's say my bot has 2 commands !command and !settings.
A user changes his/her setting with the setting command: "!settings (setting1/setting2/setting3/setting4...)"
If the user uses the !command with (setting1), it will send "response1". But if user has (setting2) it will send "response2", and if user has (setting3) it will send "response3" and so on...
I will appreciate any help :)
I will try my best to explain to you!
To make it happen, we need to store those data in the database!(what is database? to store some data which we can update, delete, and use anytime.) So, we are going to store it in the database. (what we are going to store? we are going to store each user's settings)
For Example! if a person used !settings 1 then we are going to store it in database like this.
{ "user_id": discord_user_id_here,"settings":1}
the discord user id of each person is unique so we use that to store it in the database!.(but where we are going to store it? there is a free best company called "MongoDB" is providing us free database! we will save our data there. and we can completely control it with python)
Now we have saved that user in database and we can do anything in that! but now the important thing, after saved when he uses the first command "!command", we need to fetch the settings from the database! and we can run anything according to his settings!.
LINKS:
MongoDB - https://www.mongodb.com/
MongoDB python Docs - https://pymongo.readthedocs.io/en/stable/
Complete Best Tutorial For MongoDB python - https://www.youtube.com/watch?v=rE_bJl2GAY8

How to get general user information with SteamID64?

I am having problem with doing simple things using Steams 64 bit id.
How can i use SteamAPI to get the general information? like displaying name, username, location.
I used SteamAuth to make my social authentication on website, which only has the function, that gets the id.
Example:
steamid = GetSteamID64()
username = GetUsername()
displayname = GetDisplay()
...
Does SteamAPI on have features related to this? is there any library in python that could support such thing?
There are a whole lot of WebAPI methods to get details about a Steam user. You seem to be looking for GetPlayerSummaries.
You'll need an API key to use it.

Number of visitors in Django

In Django, how can I see the number of current visitors? Or how do I determine the number of active sessions?
Is this a good method?
use django.contrib.sessions.models.Session, set the expiry time short. Every time when somebody does something on the site, update expiry time. Then count the number of sessions that are not expired.
You might want to look into something like django-tracking for this.
django-tracking is a simple attempt at
keeping track of visitors to
Django-powered Web sites. It also
offers basic blacklisting
capabilities.
Edit: As for your updated question... [Answer redacted after being corrected by muhuk]
Alternatively, I liked the response to this question: How do I find out total number of sessions created i.e. number of logged in users?
You might want to try that instead.
django-tracking2
can be helpful to track the visitors.
As specially this is easy to configure in the deployment like AWS, because it is not required any dependency and environment variables.
django-tracking2 tracks the length of time visitors and registered users spend on your site. Although this will work for websites, this is more applicable to web applications with registered users. This does not replace (nor intend) to replace client-side analytics which is great for understanding aggregate flow of page views.
There is also a little application django-visits to track visits https://bitbucket.org/jespino/django-visits
Edit: Added some more information about why I present this answer here. I found chartbeat when I tried to answer this same question for my django based site. I don't work for them.
Not specifically Django, but chartbeat.com is very interesting to add to a website as well.
django-tracking is great, +1 for that answer, etc.
Couple of things I could not do with django-tracking, that chartbeat helped with; tracked interactions with completely cached pages which never hit the django tracking code and pages not delivered through django (e.g. wordpress, etc.)

Categories

Resources