Pyromod Versions Save

A monkeypatcher add-on for Pyrogram

v3.1.0

6 months ago

Breaking changes

  • Client.stop_listening is now an async function, so you must await it if you're calling it on your code. If you don't use stop_listening, there is no breaking changes for you.

Highlights of this release

  • register_next_step_handler is finally here! A lot of people that asks for conversation handling on Pyrogram (and don't know pyromod yet) actually wants something like pyTelegramBotApi does with register_next_step_handler. Well, finally you can use it in Pyrogram, with pyromod! And it's not based on Futures like listen and ask are, so those who don't like pyromod might like this new feature.

The difference from pyTelegramBotApi's approach is that with pyromod, your callback will actually receive the Client object and the received Message (or CallbackQuery). In pyTelegramBotApi, the callback receives only the Message. Also, you don't need to call any other function than register_next_step_handler. You just call it passing your callback and that's all! Check the example below:

  • Now pyromod accepts lists of values for chat_id, user_id, message_id and inline_message_id.

  • Now pyromod accepts usernames for chat_id and user_id, so the example above could also be:

Other changes

  • Thanks to @jusidama18 with #34, now pyromod will also work if you use sync filters.

Full Changelog: https://github.com/usernein/pyromod/compare/v3.0.0...v3.1.0

v3.0.0

6 months ago

What's Changed

  • The classes Client, Message, Chat and User now inherit from their respective classes in Pyrogram. This mean you can use them as if they were the original classes from Pyrogram. This is super useful for the IDEs to provide code completion and type checking of the pyromod features. image

  • Since we can now use pyromod's Client just like the original Client, there is a new way of initilizing pyromod. Before, you needed to import pyromod anywhere in your code before importing pyrogram. Now you can simply import Client from pyromod instead of pyrogram and you are good to go. image

  • The tuple identifiers that divided opinions have been removed. Now you can specify the data directly to the listen and ask methods as keyword arguments. Thanks for the suggestion, @Eikosa! (#12) image

  • Added support for inline_message_id in the listen and ask methods.

  • pyromod will now check if the CallbackQuery.chat exists before trying to get its id, since chat will be null on inline messages.

  • The order of the arguments of Client.ask has been changed. Now the first argument is the chat_id and the second is the text to send, following the same order as Client.send_message. image

  • The internal login of listeners got a lot more simple and robust. It has been hugely refactored and now it's a lot easier to understand and maintain.

  • The internal logic of the listeners state has been refactored. Now it uses Listener objects instead of a bunch of positional variables and dicts.

  • The whole code got type hints. This means that the IDEs can now provide code completion and type checking of the pyromod features. image

  • The decorators patch and patchable have been renamed to patch_into and should_patch respectively, making them more descriptive.

  • @Jusidama-Bot made a huge contribution to the project, making the monkeypatching utils so much more powerful. Awesome!

  • The classes Client, Chat, User, Message, MessageHandler and CallbackQueryHAndler, that were previously in the listen.py file were split into their own files into the listen subpackage. image

  • The classes ListenerStopped and ListenerTimeout, that were previously in the listen.py file were moved to the exceptions subpackage. image

  • The class PyrogramConfig, that was previously in the utils.py file was moved to the config subpackage. It's now called config and it's a SimpleNamespace object instead of a class. image

  • The enum ListenerTypes, that was previously in the listen.py file was moved to the brand new types subpackage. image

  • Now the ask method will only send a message if the specified text is not empty. Thanks for that, @Eikosa! image

  • The attribute request of the Message object returned by the ask method has been renamed to sent_message, much more descriptive. Thanks again, @Eikosa! image

  • @tofikdn has added support for Message.message_id, when available, like in Pyrogram v1. Thanks for that!

  • The project structure has been completely refactored. Now it's more organized and a lot easier to maintain.

pyromod/
├── __init__.py
├── helpers
│  ├── helpers.py
│  └── __init__.py
├── listen
│  ├── __init__.py
│  └── listen.py (used to contain Client, Message, Chat, User, MessageHandler, CallbackQueryHandler, ListenerStopped, ListenerTimeout and ListenerTypes)
├── nav
│  ├── __init__.py
│  └── pagination.py
└── utils
    ├── __init__.py
    └── utils.py (used to contain PyromodConfig and the functions patch and patchable)

Now it has the following structure:

pyromod/
├── __init__.py
├── config
│  └── __init__.py (contains the config object, formerly PyrogramConfig)
├── exceptions
│  ├── __init__.py
│  ├── listener_stopped.py
│  └── listener_timeout.py
├── helpers
│  ├── __init__.py
│  └── helpers.py
├── listen
│  ├── __init__.py
│  ├── callback_query_handler.py
│  ├── chat.py
│  ├── client.py
│  ├── message_handler.py
│  ├── message.py
│  └── user.py
├── nav
│  ├── __init__.py
│  └── pagination.py
├── types
│  ├── __init__.py
│  ├── identifier.py
│  ├── listener.py
│  └── listener_types.py
└── utils
    ├── __init__.py
    └── patch.py (now contains the functions patch_into and should_patch)

New Contributors

Full Changelog: https://github.com/usernein/pyromod/compare/v2.1.0...v3.0.0

v2.1.0

8 months ago

What's Changed

New Contributors

Full Changelog: https://github.com/usernein/pyromod/compare/v2.0.0...v2.1.0

v2.0.0

1 year ago
  • It became easier to create simple inline keyboards. You can now pass a string as button, which will be used as text and callback_data:
keyboard = ikb([
    ["Earth", "Mars", "Venus"],
    ["Saturn", "Jupyter"]
])
  • Added support for listening for buttons. You can use await Message.wait_for_click() to await for any click on any button on that message. By passing an user_id into the parameter from_user_id, you can restrict from which users should the bot accept the click. Any other user will see an alert (i.e. query.answer()) informing they are not supposed to click the button. You can pass a custom text to the param alert or can pass False to disable it, so no text will be shown at all. image

  • To support both messages and callback queries, a parameter named listener_type has been added. Its value must be one of the enum pyromod.ListenerTypes

  • The method cancel_listener has been renamed to stop_listening

  • Pyromod now uses "identifiers" in all its methods instead of the good old chat_id. Identifiers are basically tuples with ordered data about the messages that the listeners should listen for. It must follow this order: (chat_id, user_id, message_id). If you pass None as value, it will act as a wildcard, matching any value. Examples:

    • (1029384756, 276145711, None) means "any message sent by 276145711 in the chat 1029384756"

    • (1029384756, None, None) means "any message sent in the chat 1029384756, from any user"

    • (None, 276145711, None) means "any message from 276145711 on any chat"

    • message_id is only used when waiting for button clicks:

      • (1029384756, 276145711, 1123) means "a click done by 276145711 on a button on the message 1123 on the chat 1029384756"
      • (1029384756, None, 1123) means "a click on a button on the message 1123 on the chat 1029384756, done by any user" The listeners are used as patterns for matching against the received update data. A listener with the identifier/pattern (1029384756, 276145711, None) will match if the message data is (1029384756, 276145711, 728), but won't do if the message data is (1029384756, 200097591, 729), because the identifier specified which user_id it wants and it′s not matching. If you use mostly the bound methods, you don′t need to worry about it, since they will automatically compose the identifier for you.
    • m.chat.listen will compose (m.chat.id, None, None)

    • m.from_user.listen will compose (None, m.from_user.id, None)

    • m.from_user.ask will compose (m.from_user.id, m.from_user.id, None)

    • m.wait_for_click(from_user_id=276145711) will compose (m.chat.id, 276145711, m.id)

      Be aware that User.listen does not create a listener for messages sent by the user on the chat of the message. If using User.ask, it asks on the private chat with the user and creates a listener for messages sent by the user on the private conversation. This may change in the future to whatever makes more sense. If using User.listen, it will listen for any message from that user, anywhere.

  • Pyromod now raises pyromod.ListenerTimeout(timeout) instead of asyncio.TimeoutError

  • New exception pyromod.ListenerStopped. It raises when any listener is stopped by Client.stop_listening

  • New class pyromod.PyromodConfig. It′s a class with some static properties that hold some tweaks and error handlers.

    • timeout_handler: a callback that gets executed instead of raising asyncio.TimeoutError (now pyromod.ListenerTimeout). It receives (identifier, listener_data, timeout) as arguments.
    • stopped_handler: a callback that gets executed when a listener is stopped by stop_listening()
    • throw_exceptions: Boolean, defaults to True. If False, pyromod won't raise none of pyromod.ListenerTimeout and pyromod.ListenerStopped. The functions should just return None instead.
    • unallowed_user_alert: Boolean, defaults to True. If False, no text will be responded to unwanted user clicks.
    • unallowed_user_alert_text: the default text for unallowed user alerts. image
  • Before this release, pyromod would block other commands to work if there is a listener on the chat, but the filters doesn't match (i.e. a listener with filters.photo, but the message is just text). Now, if there′s a listener but the filters doesn't match, the message will keep propagating to other handlers. The same happens when you use a restrictive identifier, specifying the user_id. In this case, all other users will still be able to use the bot, while the bot keeps awaiting for a message from the wanted user. As it should be.

  • The parameters for stop_listening (formerly cancel_listener) has changed, due to the addition of identifiers. Before this release, you could pass the chat_id of the listener to stop and delete it. Now, with identifiers, you can either pass a message data as (chat_id, user_id, message_id) to stop the first matching listener or pass a identifier_pattern to stop the first matching listeners.

    To explain the difference between these two, let′s suppose you want to stop a listener that has (1029384756, 276145711, 19876) as identifier, but you only know the chat_id, so you can't pass the message data to match. In this case, you can pass identifier_pattern=(1029384756, None, None). This also may change in the near future, I honestly don't know why there is two ways, where identifier_pattern could handle both situations. I was sleepy. image

Full Changelog: https://github.com/usernein/pyromod/compare/v1.5...v2.0.0

v1.5

1 year ago