cmd410 / origamibot Goto Github PK
View Code? Open in Web Editor NEWA pythonic Telegram bot API library
License: MIT License
A pythonic Telegram bot API library
License: MIT License
I'm running OrigamiBot as part of a multi thread server process.
From within the telegram communication thread, I run bot.start() (which starts more Origamibot threads in the background), then I use that thread for forwarding messages from the system to the bot asynchronously (i.e.: from the main thread, not triggered by incoming bot messages; I don't use the asyncio concept).
This all works quite well.
Things seem to become a bit ugly when for example the network is down, or the server is not reachable for any other reason.
This leads to a flurry of messages like these:
2024-03-11 19:23:03,398 | bot.py:1443 | PID 2282 | ERROR | Exception while polling
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 169, in _new_conn
conn = connection.create_connection(
File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 73, in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
File "/usr/lib/python3.10/socket.py", line 955, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -3] Temporary failure in name resolution
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 700, in urlopen
httplib_response = self._make_request(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 383, in _make_request
self._validate_conn(conn)
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 1017, in _validate_conn
conn.connect()
File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 353, in connect
conn = self._new_conn()
File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 181, in _new_conn
raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPSConnection object at 0x7b90347264d0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/requests/adapters.py", line 439, in send
resp = conn.urlopen(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 756, in urlopen
retries = retries.increment(
File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 574, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.telegram.org', port=443): Max retries exceeded with url: /BOTID:BOTTOKEN/getUpdates (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7b90347264d0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/marc/.local/lib/python3.10/site-packages/origamibot/core/bot.py", line 1441, in _listen_loop
updates = self.get_updates()
File "/home/marc/.local/lib/python3.10/site-packages/origamibot/core/bot.py", line 314, in get_updates
updates = get_updates(
File "/home/marc/.local/lib/python3.10/site-packages/origamibot/core/api_request.py", line 115, in get_updates
updates = request(
File "/home/marc/.local/lib/python3.10/site-packages/origamibot/core/api_request.py", line 91, in request
response = requests.post(
File "/usr/lib/python3/dist-packages/requests/api.py", line 119, in post
return request('post', url, data=data, json=json, **kwargs)
File "/usr/lib/python3/dist-packages/requests/api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/lib/python3/dist-packages/requests/sessions.py", line 544, in request
resp = self.send(prep, **send_kwargs)
File "/usr/lib/python3/dist-packages/requests/sessions.py", line 657, in send
r = adapter.send(request, **kwargs)
File "/usr/lib/python3/dist-packages/requests/adapters.py", line 516, in send
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.telegram.org', port=443): Max retries exceeded with url: /BOTID:BOTTOKEN/getUpdates (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7b90347264d0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))
(Bot data has been replaced with BOTID and BOTTOKEN in above log).
I would like to somewhat gracefully catch these, log them as a single concise message to syslog ("Telegram Server Connection lost"), and then try to recover (i.e. the system should continue to operate, and silently try to reconnect to the telegram server in the background).
How is this best done? Is it even possible with Origamibot? Is the above behavior a bug? Or am I doing something wrong?
My code looks about as this (edited for brevity):
bot = Bot(bot_token)
bot.add_listener(MessageListener(bot))
bot.add_commands(BotsCommands(bot))
bot.start()
...
while(True):
bot.send_message(chat_id, "testmessage") # chat_id stored globally, the chat we want to send info to
# sleep for a while
Funny: The bot seems to reconnect, and commands I type in the telegram channel do get through to the system. But messages my systems send to the telegram channel via the bot (see above example) are lost.
Publishing releases through Github actions fails on "Build and publish" stage with the last lines being:
++ git describe --tags --abbrev=0
fatal: detected dubious ownership in repository at '/github/workspace'
To add an exception for this directory, call:
git config --global --add safe.directory /github/workspace
+ version=
sendMediaGroup
request does not work for some reason
Server returns data:
{"ok":false,"error_code":400,"description":"Bad Request: can't parse media JSON object"}
Data sent by bot:
{"chat_id": <chat_id>,
"media": [{"media": "<link/to/image.jpg>",
"type": "photo"},
{"media": "<link/to/image.jpg>",
"type": "photo"}]}
seems to be in line with documentation, still doesn't not work.
Code is in fixme_broken_send_media_group branch
Hello! I want to table a proposal to add a special submodule to generate Telegram-specific markup easily.
A common markdown format that every programmer uses is really simple and doesn’t require special utils for that, but MarkdownV2 and HTML which let include spoiler, strikethrough and other telegram innovations are different. For example, MarkdownV2 also requires to escape 18 characters, and if it’s not, reject the request. This may make the task of designing markup generation for bots that include business logic complicated enough and I suppose it’s better to have a ready-made out-of-the-box solution for this.
I have recently worked on a related challenge and I’m writing this to propose to re-use my solution. It’s the telegram-text
module. The general structure in the context of the origamibot
module I propose to implement is the following:
telegram-text
as a dependency (maybe even optional)origamibot
module core to import styles and other needed classes as from origamibot import ...
. Or it’s quite pretty to add a separated file (text.py
or markup.py
for example) to import as from origamibot.text import ...
telegram-text
module?Example of the module:
from telegram_text import Bold, Italic, Underline
text = Underline(Bold("Bold") + "and" + Italic("italic") + "with underline.")
origamibot
contextfrom origamibot import OrigamiBot as Bot
from origamibot.listener import Listener
from origamibot.text import Spoiler, InlineCode, PlainText
TOKEN: str
class BotsCommands:
def __init__(self, bot: Bot):
self.bot = bot
def echo(self, message, value: str):
self.bot.send_message(message.chat.id, Spoiler(value)) # Spoiler text
class MessageListener(Listener):
def __init__(self, bot: Bot):
self.bot = bot
def on_command_failure(self, message, err=None):
if err is None:
self.bot.send_message(message.chat.id, 'Command failed to bind arguments!') # A std str object
else:
self.bot.send_message(message.chat.id, PlainText('Error in command:') + InlineCode(err)) # Combined plain and code text
if __name__ == '__main__':
bot = Bot(TOKEN)
bot.add_listener(MessageListener(bot))
bot.add_commands(BotsCommands(bot))
bot.start()
while True:
pass
Hello,
My Bot stops to listen for messages after an amount of time due to a Remote Close Connection. It seems to happen in /core/api_request.py Autoposting or other actions stated in the main thread still work as expected.
This is my log:
*** | Exception while polling
*** | Traceback (most recent call last):
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
*** | httplib_response = self._make_request(
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 449, in _make_request
*** | six.raise_from(e, None)
*** | File "<string>", line 3, in raise_from
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 444, in _make_request
*** | httplib_response = conn.getresponse()
*** | File "/usr/local/lib/python3.10/http/client.py", line 1374, in getresponse
*** | response.begin()
*** | File "/usr/local/lib/python3.10/http/client.py", line 318, in begin
*** | version, status, reason = self._read_status()
*** | File "/usr/local/lib/python3.10/http/client.py", line 287, in _read_status
*** | raise RemoteDisconnected("Remote end closed connection without"
*** | http.client.RemoteDisconnected: Remote end closed connection without response
*** |
*** | During handling of the above exception, another exception occurred:
*** |
*** | Traceback (most recent call last):
*** | File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 489, in send
*** | resp = conn.urlopen(
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 787, in urlopen
*** | retries = retries.increment(
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/util/retry.py", line 550, in increment
*** | raise six.reraise(type(error), error, _stacktrace)
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/packages/six.py", line 769, in reraise
*** | raise value.with_traceback(tb)
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
*** | httplib_response = self._make_request(
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 449, in _make_request
*** | six.raise_from(e, None)
*** | File "<string>", line 3, in raise_from
*** | File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 444, in _make_request
*** | httplib_response = conn.getresponse()
*** | File "/usr/local/lib/python3.10/http/client.py", line 1374, in getresponse
*** | response.begin()
*** | During handling of the above exception, another exception occurred:
*** |
*** | Traceback (most recent call last):
*** | File "/usr/local/lib/python3.10/site-packages/origamibot/core/bot.py", line 1440, in _listen_loop
*** | updates = self.get_updates()
*** | File "/usr/local/lib/python3.10/site-packages/origamibot/core/bot.py", line 313, in get_updates
*** | updates = get_updates(
*** | File "/usr/local/lib/python3.10/site-packages/origamibot/core/api_request.py", line 109, in get_updates
*** | updates = request(
*** | File "/usr/local/lib/python3.10/site-packages/origamibot/core/api_request.py", line 86, in request
*** | response = requests.post(url, data=json_data, headers=headers)
*** | File "/usr/local/lib/python3.10/site-packages/requests/api.py", line 115, in post
*** | return request("post", url, data=data, json=json, **kwargs)
*** | File "/usr/local/lib/python3.10/site-packages/requests/api.py", line 59, in request
*** | return session.request(method=method, url=url, **kwargs)
*** | File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 587, in request
*** | resp = self.send(prep, **send_kwargs)
*** | File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 701, in send
*** | r = adapter.send(request, **kwargs)
*** | File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 547, in send
*** | raise ConnectionError(err, request=request)
*** | requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection
without response'))
Hi!
Thank you for making this great project. I got a bot up and running in Minutes!
I think I discovered a little bug: In the send_poll method, you marked reply_markup
as optional.
However, in the implementation, you call reply_markup.unfold()
without checking whether it is None, leading to the following exception:
File "/home/user/.local/lib/python3.10/site-packages/origamibot/core/api_request.py", line 736, in send_poll
'reply_markup': reply_markup.unfold(),
AttributeError: 'NoneType' object has no attribute 'unfold'
It'll be nice to have proper way to create inline queries handlers
I am running OrigamiBot on my homeserver and the ISP forces a reconnect every 24 hours.
After that the bot does not receive updates/new messages anymore.
To reproduce this you can also manually disconnect and reconnect the internet connection e.g. by unplugging the LAN cable.
I think that the request (long polling) is still waiting for an answer but because of the short internet lack the polling waits endless.
Probably it is enough to set a timeout for the requests.
I will try it and if it works I will make a pull request.
Nevertheless it is always useful to set a timeout for requests. See https://dev.to/bearer/the-importance-of-request-timeouts-l3n
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.