aiogram message handler not firing for a message containing media - python

I am using aiogram 2.11.2 as Python interface to the Telegram API, but I am encountering an issue in the simplest callback: it does activate when the message is text only, but fails whenever any media is attached. This includes photos, videos, audios, stickers and GIFs, with or without caption.
I hope I'm not missing out on something.
import aiogram
class TelegramBot(object):
def __init__(self):
self.bot = aiogram.Bot(token="TOKEN")
self.dispatcher = aiogram.Dispatcher(bot=self.bot)
self.dispatcher.register_message_handler(self.on_msg,)
async def on_msg(self, msg: aiogram.types.Message):
print("Message received in telegram")

Turns out I was really missing out on something. To listen for all kinds of messages, it is sufficient to define content_type as
dispatcher.register_message_handler(self.on_msg, content_type=aiogram.types.ContentType.all())
Thanks to the answerer to my Git issue.

Related

Telegram Bot Api / Python: Trying to send voice message via my telegram bot

so im playing a little bit around with my telegram bot, now im already able to send normal messages and pictures. But now i want to be able to send pre recorded voice messages as an answer. In the documentation it says to use send_voice for this matter and it recommends using the file_id of a file thats already on the telegram servers. So thats what i did i send a voice message to the #RawDataBot and he returned to me the file_id of the voice message.
Problem is: When i try to trigger it i get the following error: telebot.apihelper.ApiTelegramException: A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: wrong file identifier/HTTP URL specified
Any ideas here on what i might be doing wrong? Here is the relevant code:
import telebot
API_KEY = <MY_API_KEY>
bot = telebot.TeleBot(API_KEY)
#start
#bot.message_handler(commands=['start'])
def start (message):
bot.send_message(message.chat.id,Textstart)
#bot.message_handler(commands=['pic'])
def start (photo):
bot.send_photo(photo.chat.id, "https://de.wikipedia.org/wiki/Zeus#/media/Datei:Zeus_Otricoli_Pio-Clementino_Inv257.jpg")
#here is the part where he is supposed to send the voice message if someone types in /audio
#bot.message_handler(commands=['audio'])
def start (voice):
bot.send_voice(voice.chat.id,"AwACAgIAAxkBAAEWjl5i5bjyudWAM9IISKWhE1Gjs5ntQgACLx8AApcNKEv97pVasPhBoCkE",)
bot.polling()
There are multiple reasons, but I think it is because of these:
file_id is unique for each individual bot and can't be transferred from one bot to another.
file_id uniquely identifies a file, but a file can have different valid file_ids even for the same bot.
See here.

How to download a file that was sent to my bot?

#dp.message_handler(content_types=types.ContentType.DOCUMENT)
async def scan_message(file: types.File):
print("downloading document")
file_path = file.file_path
destination = r"C:\users\aleks\PycharmProjects\pythonProject\file.pdf"
destination_file = bot.download_file(file_path, destination)
print("success")
I would like to be able to download a file (in this case it is pdf) that was sent to my bot by the user. But the problem is that the bot doesn't even recognize a file (when I send a file, it doesn't even print "downloading document")
TL;DR
I hope you're using aiogram v2.x.
Make sure that's the only handler for types.ContentType.DOCUMENT without filters and your bot can get needed updates, then:
#dp.message_handler(content_types=types.ContentType.DOCUMENT)
async def scan_message(message: types.Message):
print("downloading document")
destination = r"C:\users\aleks\PycharmProjects\pythonProject\file.pdf"
await message.document.download(destination)
print("success")
Detailed
Everything described below applies to stable aiogram v2.x.
aiogram.Dispatcher class parses raw telegram Update and sends it parsed and unpacked to corresponding handler, e.g. dp.message_handler will receive aiogram.types.Message for updates containing message, dp.callback_query_handler will receive aiogram.types.CallbackQuery for updates containing callback_query and so on. In your case you are expecting aiogram.types.File, which is wrong. Then dispatcher checks filters and calls corresponding handlers in registration order and stops dispatching if any handler was called.
Consider the following example:
# Some code omitted in favor of brievity
#dp.message_handler()
async def handle1(msg: types.Message):
print("handled 1")
#dp.message_handler()
async def handle2(msg: types.Message):
print("handled 2")
You send any text message then look at bot's console. There will only "handled 1" be printed because it was the first matching handler and only one handler is called.
Bots have so-called "Privacy mode" in group chats, so not every message comes to your bot in a group. This is not the case in private (direct) messages, so it's better to test your bot in private. You can read more about Privacy mode in official Bot API docs: https://core.telegram.org/bots#privacy-mode.
It's better and more readable to use shortcuts which are contained in each class, e.g. you can .reply() or .answer() to a aiogram.types.Message, which is a shortcut for aiogram.Bot.send_message(). Same with downloading file, you can just use .download() on aiogram.types.Document, aiogram.types.PhotoSize and so on. You can find more downloadable types by looking for classes that implement aiogram.types.mixins.Downloadable.
All .download() methods return destination where the file was saved. If you pass your own optional destination as the first argument to the method, it'll be useless to get it back as you already know it.
So, after these modifications, you'll get the code as in TL;DR section.
You did not specify version of aiogram. I guess it is 2.x.
All asynchronous function registered, as message handler must take the first positional parameter received message. If you like type hints you must to specify your function as
async def scan_message(message: types.Message):
for download your document you need just:
destination_file = await message.document.download(destination)
so correct handler for download document is:
async def scan_message(message: types.Message):
print("downloading document")
destination = r"C:\users\aleks\PycharmProjects\pythonProject\file.pdf"
destination_file = await message.document.download(destination)
print("success")

Can't respond to messages in message request in fbchat

I'm trying to make a bot so that when someone sends it a message the bot sends back a joke but I've noticed this only works with people in my friends list but if random people sent to the bot then their message gets stuck in message request on messenger and even the fbchat library recognizes this and tells me in the console that there is a new pending message so is there a way to respond to those too?
Here is my code:
from fbchat import Client,ThreadLocation
class JokesBot(Client):
def onMessage(self, author_id, message_object, thread_id, thread_type, **kwargs):
self.moveThread(ThreadLocation.PENDING,thread_id,thread_type)
self.markAsDelivered(thread_id, message_object.uid)
self.markAsRead(thread_id)
# If you're not the author, echo
if author_id != self.uid:
self.send(Message(text='wiso tefl hehe'), thread_id=thread_id, thread_type=thread_type)
client = JokesBot('email', 'password')
client.listen()
Bare in mind I still didn't implement the jokes so it's missing from the code
Thanks in advance
onMessage event called only when connected facebook friend sends you a message.
for unconnected facebook users(not friends) you should use another event onPendingMessage but unlike onMessage' in pending message things are getting more complex:
take a look at fbchat documentation
after the event called you should call the method: "fetchThreadList" in oreder to see the incoming message

How do you get authenticated with steam in a websocket connection?

I'm trying to automate interaction with a website that uses websockets. In theory all I need to do is get authenticated with steam and then send 1 piece of data, but I'm having trouble getting authenticated.
I manage to get the connection set up. But after I send my steam token (replicating what I see happens in the devtools of my browser), it replies that I am not logged in.
Below is the code I currently have. Locally it doesn't work at all. But on repl.it (an online editor) it has the effect it's supposed to have but the websocket still replies that I am not logged in.
The code:
import asyncio
import websockets
import json
import time
import sys
token = "YOUR_STEAM_TOKEN_HERE"
adress = 'wss://eu.pug.champ.gg/socket.io/?EIO=3&transport=websocket'
authtemplate = '42["authenticate",{{"token":{0}}}]'
rolesupdatetemplate = '42["updateAvailability",{0}]'
async def add(roles):
async with websockets.connect(adress) as websocket:
await websocket.send(authtemplate.format(token))
roles_string = json.dumps(roles)
await websocket.send(rolesupdatetemplate.format(roles_string))
asyncio.get_event_loop().run_until_complete(add({'roles': ['roamer', 'pocket'], 'captain': False})
)
Some extra info:
When on the site normally, the websocket I'm connected to according to the developer tools has an extra argument compared to the one I use in my code. The extra argument being: sid=....
However, adding this manually gives me error code 400.
I've tried looking up how to do this but I can't find the answer anywhere. Do I need to send cookies?
Do I need to get the websocket address in another way rather than manually?
What am I missing?

why aren't my slack client rtm messages showing in slack

Hi I'm a using the python slack client library and I cannot work out why my messages are not showing up when using the
from slackclient import SlackClient
token = 'XXXXXXXX' # my token
sc = SlackClient(token)
if sc.rtm_connect(): # connect to a Slack RTM websocket
sc.rtm_send_message('general', 'I need coffee')
else:
print('Connection Failed, invalid token?')
My Bot is part of the public channel I am trying to send the message too, I don't receive any errors but nothing is showing up in the channel I'm sending it too. I have tried both the channel name and its id.
The following does work
import json
from slackclient import SlackClient
def list_channels():
channels_call = slack_client.api_call("channels.list")
if channels_call.get('ok'):
return channels_call['channels']
return None
def send_message(channel_id, message):
slack_client.api_call(
"chat.postMessage",
channel=channel_id,
text=message,
username='mybot',
icon_emoji=':robot_face:'
)
slack_client = SlackClient('XXXXXXXXX')
channels = list_channels()
if channels:
for c in channels:
if c['name'] == 'general':
send_message(c['id'], 'I need coffee.')
else:
print("Unable to authenticate.")
And I see the message come up almost instantly in my channel.
I have confirmed through both the slack website and the api that my bot is a member of this channel.
Am I missing something about the way this works?
I think you should use your bot token instead of your user token. There 2 types of token in slack and if you want the bot to reply to the slack channel you should use bot token.

Categories

Resources