Giter Site home page Giter Site logo

origamibot's Introduction

This README is temporarily a potato.

origamibot's People

Contributors

cmd410 avatar dependabot[bot] avatar hatkidchan avatar kyokoth avatar ntzex avatar t-n-u-z avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

origamibot's Issues

Handling of connection error exceptions

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.

CI is broken, for some reason.

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=

Broken sendMediaGroup

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

Markup submodule support

Hello! I want to table a proposal to add a special submodule to generate Telegram-specific markup easily.

Motivation

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.

Implementation suggestion

General explanation

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:

  • Add telegram-text as a dependency (maybe even optional)
  • Add support for message objects rendering depending on format mode (Markdown / MarkdownV2 / HTML) inside the message sending function
  • Add imports into the 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 ...

Why telegram-text module?

  • Include all rules for all markup modes
  • Almost entirely covered by tests
  • Fully documented
  • Open to contribute
  • Has a few presets and is easily expandable to add new

Example of the module:

from telegram_text import Bold, Italic, Underline

text = Underline(Bold("Bold") + "and" + Italic("italic") + "with underline.")

Usage example in the origamibot context

from 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

Remote Close Connection in get_updates()

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'))

Send Poll: Reply Markup is Optional, but needs unfold()

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'

Inline support?

It'll be nice to have proper way to create inline queries handlers

After internet reconnect the bot does not receive updates anymore

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.