Pyrofork: Message Reaction Update (#43)

* Pyrofork: Message Reaction Update

---------

Signed-off-by: Yasir Aris M <yasiramunandar@gmail.com>
Signed-off-by: wulan17 <wulan17@nusantararom.org>
Co-authored-by: shriMADhav U k <hetzner@shrimadhavuk.me>
Co-authored-by: Yasir Aris M <yasiramunandar@gmail.com>
Co-authored-by: wulan17 <wulan17@nusantararom.org>
This commit is contained in:
Yasir Aris M 2024-01-21 18:44:49 +07:00 committed by wulan17
parent 82a9222cd2
commit 4c11bcdc7f
No known key found for this signature in database
GPG key ID: 318CD6CD3A6AC0A5
25 changed files with 729 additions and 48 deletions

View file

@ -487,6 +487,11 @@ def pyrogram_api():
ForumTopicReopened ForumTopicReopened
GeneralTopicHidden GeneralTopicHidden
GeneralTopicUnhidden GeneralTopicUnhidden
Reaction
ReactionCount
ReactionType
MessageReactionUpdated
MessageReactionCountUpdated
""", """,
stories=""" stories="""
Stories Stories

View file

@ -38,6 +38,8 @@ Index
- :meth:`~Client.on_message` - :meth:`~Client.on_message`
- :meth:`~Client.on_edited_message` - :meth:`~Client.on_edited_message`
- :meth:`~Client.on_callback_query` - :meth:`~Client.on_callback_query`
- :meth:`~Client.on_message_reaction_updated`
- :meth:`~Client.on_message_reaction_count_updated`
- :meth:`~Client.on_inline_query` - :meth:`~Client.on_inline_query`
- :meth:`~Client.on_chosen_inline_result` - :meth:`~Client.on_chosen_inline_result`
- :meth:`~Client.on_chat_member_updated` - :meth:`~Client.on_chat_member_updated`
@ -58,6 +60,8 @@ Details
.. autodecorator:: pyrogram.Client.on_message() .. autodecorator:: pyrogram.Client.on_message()
.. autodecorator:: pyrogram.Client.on_edited_message() .. autodecorator:: pyrogram.Client.on_edited_message()
.. autodecorator:: pyrogram.Client.on_callback_query() .. autodecorator:: pyrogram.Client.on_callback_query()
.. autodecorator:: pyrogram.Client.on_message_reaction_updated()
.. autodecorator:: pyrogram.Client.on_message_reaction_count_updated()
.. autodecorator:: pyrogram.Client.on_inline_query() .. autodecorator:: pyrogram.Client.on_inline_query()
.. autodecorator:: pyrogram.Client.on_chosen_inline_result() .. autodecorator:: pyrogram.Client.on_chosen_inline_result()
.. autodecorator:: pyrogram.Client.on_chat_member_updated() .. autodecorator:: pyrogram.Client.on_chat_member_updated()

View file

@ -0,0 +1,8 @@
ReactionType
============
.. autoclass:: pyrogram.enums.ReactionType()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -28,6 +28,7 @@ to apply only a valid value among the expected ones.
SentCodeType SentCodeType
NextCodeType NextCodeType
UserStatus UserStatus
ReactionType
StoriesPrivacyRules StoriesPrivacyRules
StoryPrivacy StoryPrivacy
@ -49,5 +50,6 @@ to apply only a valid value among the expected ones.
SentCodeType SentCodeType
NextCodeType NextCodeType
UserStatus UserStatus
ReactionType
StoriesPrivacyRules StoriesPrivacyRules
StoryPrivacy StoryPrivacy

View file

@ -39,6 +39,8 @@ Index
- :class:`EditedMessageHandler` - :class:`EditedMessageHandler`
- :class:`DeletedMessagesHandler` - :class:`DeletedMessagesHandler`
- :class:`CallbackQueryHandler` - :class:`CallbackQueryHandler`
- :class:`MessageReactionUpdatedHandler`
- :class:`MessageReactionCountUpdatedHandler`
- :class:`InlineQueryHandler` - :class:`InlineQueryHandler`
- :class:`ChosenInlineResultHandler` - :class:`ChosenInlineResultHandler`
- :class:`ChatMemberUpdatedHandler` - :class:`ChatMemberUpdatedHandler`
@ -58,6 +60,8 @@ Details
.. autoclass:: EditedMessageHandler() .. autoclass:: EditedMessageHandler()
.. autoclass:: DeletedMessagesHandler() .. autoclass:: DeletedMessagesHandler()
.. autoclass:: CallbackQueryHandler() .. autoclass:: CallbackQueryHandler()
.. autoclass:: MessageReactionUpdatedHandler()
.. autoclass:: MessageReactionCountUpdatedHandler()
.. autoclass:: InlineQueryHandler() .. autoclass:: InlineQueryHandler()
.. autoclass:: ChosenInlineResultHandler() .. autoclass:: ChosenInlineResultHandler()
.. autoclass:: ChatMemberUpdatedHandler() .. autoclass:: ChatMemberUpdatedHandler()

View file

@ -25,9 +25,7 @@ from collections import OrderedDict
import pyrogram import pyrogram
from pyrogram import utils from pyrogram import utils
from pyrogram.handlers import ( from pyrogram.handlers import (
CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler, CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler, MessageReactionUpdatedHandler, MessageReactionCountUpdatedHandler, UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler, ConversationHandler, ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler, StoryHandler
UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler, ConversationHandler,
ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler, StoryHandler
) )
from pyrogram.raw.types import ( from pyrogram.raw.types import (
UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage, UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage,
@ -36,7 +34,9 @@ from pyrogram.raw.types import (
UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery,
UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll, UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll,
UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant, UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant,
UpdateBotChatInviteRequester, UpdateStory UpdateBotChatInviteRequester, UpdateStory,
UpdateBotMessageReaction,
UpdateBotMessageReactions
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -54,6 +54,8 @@ class Dispatcher:
CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,) CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,)
CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,) CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,)
NEW_STORY_UPDATES = (UpdateStory,) NEW_STORY_UPDATES = (UpdateStory,)
MESSAGE_BOT_NA_REACTION_UPDATES = (UpdateBotMessageReaction,)
MESSAGE_BOT_A_REACTION_UPDATES = (UpdateBotMessageReactions,)
def __init__(self, client: "pyrogram.Client"): def __init__(self, client: "pyrogram.Client"):
self.client = client self.client = client
@ -137,6 +139,18 @@ class Dispatcher:
await pyrogram.types.Story._parse(self.client, update.story, update.peer), await pyrogram.types.Story._parse(self.client, update.story, update.peer),
StoryHandler StoryHandler
) )
async def message_bot_na_reaction_parser(update, users, chats):
return (
pyrogram.types.MessageReactionUpdated._parse(self.client, update, users, chats),
MessageReactionUpdatedHandler
)
async def message_bot_a_reaction_parser(update, users, chats):
return (
pyrogram.types.MessageReactionCountUpdated._parse(self.client, update, users, chats),
MessageReactionCountUpdatedHandler
)
self.update_parsers = { self.update_parsers = {
Dispatcher.NEW_MESSAGE_UPDATES: message_parser, Dispatcher.NEW_MESSAGE_UPDATES: message_parser,
@ -149,7 +163,9 @@ class Dispatcher:
Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser, Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser,
Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser, Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser,
Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser, Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser,
Dispatcher.NEW_STORY_UPDATES: story_parser Dispatcher.NEW_STORY_UPDATES: story_parser,
Dispatcher.MESSAGE_BOT_NA_REACTION_UPDATES: message_bot_na_reaction_parser,
Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser
} }
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}

View file

@ -30,6 +30,7 @@ from .next_code_type import NextCodeType
from .parse_mode import ParseMode from .parse_mode import ParseMode
from .poll_type import PollType from .poll_type import PollType
from .profile_color import ProfileColor from .profile_color import ProfileColor
from .reaction_type import ReactionType
from .reply_color import ReplyColor from .reply_color import ReplyColor
from .sent_code_type import SentCodeType from .sent_code_type import SentCodeType
from .stories_privacy_rules import StoriesPrivacyRules from .stories_privacy_rules import StoriesPrivacyRules
@ -51,6 +52,7 @@ __all__ = [
'ParseMode', 'ParseMode',
'PollType', 'PollType',
'ProfileColor', 'ProfileColor',
'ReactionType',
'ReplyColor', 'ReplyColor',
'SentCodeType', 'SentCodeType',
"StoriesPrivacyRules", "StoriesPrivacyRules",

View file

@ -0,0 +1,29 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class ReactionType(AutoName):
"""Reaction type enumeration used in :obj:`~pyrogram.types.ReactionType`."""
EMOJI = auto()
"""Emoji reaction type."""
CUSTOM_EMOJI = auto()
"""Custom emoji reaction type."""

View file

@ -31,3 +31,5 @@ from .poll_handler import PollHandler
from .raw_update_handler import RawUpdateHandler from .raw_update_handler import RawUpdateHandler
from .user_status_handler import UserStatusHandler from .user_status_handler import UserStatusHandler
from .story_handler import StoryHandler from .story_handler import StoryHandler
from .message_reaction_updated_handler import MessageReactionUpdatedHandler
from .message_reaction_count_updated_handler import MessageReactionCountUpdatedHandler

View file

@ -0,0 +1,51 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Callable
from .handler import Handler
class MessageReactionCountUpdatedHandler(Handler):
"""The MessageReactionCountUpdated handler class.
Used to handle changes in the anonymous reaction of a message.
It is intended to be used with :meth:`~pyrogram.Client.add_handler`.
For a nicer way to register this handler, have a look at the
:meth:`~pyrogram.Client.on_message_reaction_count_updated` decorator.
Parameters:
callback (``Callable``):
Pass a function that will be called when a new MessageReactionCountUpdated event arrives. It takes
*(client, message_reaction_count_updated)* as positional arguments (look at the section below for a detailed
description).
filters (:obj:`Filters`):
Pass one or more filters to allow only a subset of updates to be passed in your callback function.
Other parameters:
client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the handler.
message_reaction_count_updated (:obj:`~pyrogram.types.MessageReactionCountUpdated`):
The received message reaction count update.
"""
def __init__(self, callback: Callable, filters=None):
super().__init__(callback, filters)

View file

@ -0,0 +1,51 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Callable
from .handler import Handler
class MessageReactionUpdatedHandler(Handler):
"""The MessageReactionUpdated handler class.
Used to handle changes in the reaction of a message.
It is intended to be used with :meth:`~pyrogram.Client.add_handler`.
For a nicer way to register this handler, have a look at the
:meth:`~pyrogram.Client.on_message_reaction_updated` decorator.
Parameters:
callback (``Callable``):
Pass a function that will be called when a new MessageReactionUpdated event arrives. It takes
*(client, message_reaction_updated)* as positional arguments (look at the section below for a detailed
description).
filters (:obj:`Filters`):
Pass one or more filters to allow only a subset of updates to be passed in your callback function.
Other parameters:
client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the handler.
message_reaction_updated (:obj:`~pyrogram.types.MessageReactionUpdated`):
The received message reaction update.
"""
def __init__(self, callback: Callable, filters=None):
super().__init__(callback, filters)

View file

@ -30,6 +30,8 @@ from .on_poll import OnPoll
from .on_raw_update import OnRawUpdate from .on_raw_update import OnRawUpdate
from .on_user_status import OnUserStatus from .on_user_status import OnUserStatus
from .on_story import OnStory from .on_story import OnStory
from .on_message_reaction_updated import OnMessageReactionUpdated
from .on_message_reaction_count_updated import OnMessageReactionCountUpdated
class Decorators( class Decorators(
@ -45,6 +47,8 @@ class Decorators(
OnChosenInlineResult, OnChosenInlineResult,
OnChatMemberUpdated, OnChatMemberUpdated,
OnChatJoinRequest, OnChatJoinRequest,
OnStory OnStory,
OnMessageReactionUpdated,
OnMessageReactionCountUpdated
): ):
pass pass

View file

@ -0,0 +1,60 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Callable
import pyrogram
from pyrogram.filters import Filter
class OnMessageReactionCountUpdated:
def on_message_reaction_count_updated(
self=None,
filters=None,
group: int = 0
) -> Callable:
"""Decorator for handling anonymous reaction changes on messages.
This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
:obj:`~pyrogram.handlers.MessageReactionCountUpdatedHandler`.
Parameters:
filters (:obj:`~pyrogram.filters`, *optional*):
Pass one or more filters to allow only a subset of updates to be passed in your function.
group (``int``, *optional*):
The group identifier, defaults to 0.
"""
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
self.add_handler(pyrogram.handlers.MessageReactionCountUpdatedHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
if not hasattr(func, "handlers"):
func.handlers = []
func.handlers.append(
(
pyrogram.handlers.MessageReactionCountUpdatedHandler(func, self),
group if filters is None else filters
)
)
return func
return decorator

View file

@ -0,0 +1,60 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Callable
import pyrogram
from pyrogram.filters import Filter
class OnMessageReactionUpdated:
def on_message_reaction_updated(
self=None,
filters=None,
group: int = 0
) -> Callable:
"""Decorator for handling reaction changes on messages.
This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
:obj:`~pyrogram.handlers.MessageReactionUpdatedHandler`.
Parameters:
filters (:obj:`~pyrogram.filters`, *optional*):
Pass one or more filters to allow only a subset of updates to be passed in your function.
group (``int``, *optional*):
The group identifier, defaults to 0.
"""
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
self.add_handler(pyrogram.handlers.MessageReactionUpdatedHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
if not hasattr(func, "handlers"):
func.handlers = []
func.handlers.append(
(
pyrogram.handlers.MessageReactionUpdatedHandler(func, self),
group if filters is None else filters
)
)
return func
return decorator

View file

@ -1,26 +1,26 @@
# Pyrofork - Telegram MTProto API Client Library for Python # PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan> # Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of PyroFork.
# #
# Pyrofork is free software: you can redistribute it and/or modify # PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from typing import Union, List from typing import Union, List
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import raw, types
class SendReaction: class SendReaction:
@ -30,9 +30,14 @@ class SendReaction:
message_id: int = None, message_id: int = None,
story_id: int = None, story_id: int = None,
emoji: Union[int, str, List[Union[int, str]]] = None, emoji: Union[int, str, List[Union[int, str]]] = None,
big: bool = False big: bool = False,
) -> bool: add_to_recent: bool = False
"""Send a reaction to a message. ) -> "types.MessageReactions":
"""Use this method to send reactions on a message/stories.
Service messages can't be reacted to.
Automatically forwarded messages from
a channel to its discussion group have the
same available reactions as messages in the channel.
.. include:: /_includes/usable-by/users-bots.rst .. include:: /_includes/usable-by/users-bots.rst
@ -42,7 +47,7 @@ class SendReaction:
You can also use chat public link in form of *t.me/<username>* (str). You can also use chat public link in form of *t.me/<username>* (str).
message_id (``int``, *optional*): message_id (``int``, *optional*):
Identifier of the message. Identifier of the target message. If the message belongs to a media group, the reaction is set to the first non-deleted message in the group instead.
story_id (``int``, *optional*): story_id (``int``, *optional*):
Identifier of the story. Identifier of the story.
@ -51,14 +56,18 @@ class SendReaction:
Reaction emoji. Reaction emoji.
Pass None as emoji (default) to retract the reaction. Pass None as emoji (default) to retract the reaction.
Pass list of int or str to react multiple emojis. Pass list of int or str to react multiple emojis.
big (``bool``, *optional*): big (``bool``, *optional*):
Pass True to show a bigger and longer reaction. Pass True to set the reaction with a big animation.
For message reactions only.
Defaults to False. Defaults to False.
for message reaction only.
add_to_recent (``bool``, *optional*):
Pass True if the reaction should appear in the recently used reactions.
This option is applicable only for users.
Returns: Returns:
``bool``: On success, True is returned. :obj:`~pyrogram.types.MessageReactions`: On success, True is returned.
Example: Example:
.. code-block:: python .. code-block:: python
@ -75,7 +84,7 @@ class SendReaction:
await app.send_reaction(chat_id, story_id=story_id) await app.send_reaction(chat_id, story_id=story_id)
""" """
if isinstance(emoji, list): if isinstance(emoji, list):
emoji = [ reaction = [
raw.types.ReactionCustomEmoji(document_id=i) raw.types.ReactionCustomEmoji(document_id=i)
if isinstance(i, int) if isinstance(i, int)
else raw.types.ReactionEmoji(emoticon=i) else raw.types.ReactionEmoji(emoticon=i)
@ -83,26 +92,31 @@ class SendReaction:
] if emoji else None ] if emoji else None
else: else:
if isinstance(emoji, int): if isinstance(emoji, int):
emoji = [raw.types.ReactionCustomEmoji(document_id=emoji)] reaction = [raw.types.ReactionCustomEmoji(document_id=emoji)]
else: else:
emoji = [raw.types.ReactionEmoji(emoticon=emoji)] if emoji else None reaction = [raw.types.ReactionEmoji(emoticon=emoji)] if emoji else None
if message_id is not None: if message_id is not None:
await self.invoke( r = await self.invoke(
raw.functions.messages.SendReaction( raw.functions.messages.SendReaction(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
msg_id=message_id, msg_id=message_id,
reaction=emoji, reaction=reaction,
big=big big=big,
add_to_recent=add_to_recent
) )
) )
for i in r.updates:
if isinstance(i, raw.types.UpdateMessageReactions):
return types.MessageReactions._parse(self, i.reactions)
elif story_id is not None: elif story_id is not None:
await self.invoke( await self.invoke(
raw.functions.stories.SendReaction( raw.functions.stories.SendReaction(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
story_id=story_id, story_id=story_id,
reaction=raw.types.ReactionEmoji(emoticon=emoji) if emoji else None reaction=raw.types.ReactionEmoji(emoticon=emoji) if emoji else None,
add_to_recent=add_to_recent
) )
) )
return True
else: else:
raise ValueError("You need to pass one of message_id/story_id!") raise ValueError("You need to pass one of message_id!")
return True

View file

@ -1,20 +1,21 @@
# Pyrogram - Telegram MTProto API Client Library for Python # PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrogram. # This file is part of PyroFork.
# #
# Pyrogram is free software: you can redistribute it and/or modify # PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrogram is distributed in the hope that it will be useful, # PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from .animation import Animation from .animation import Animation
from .audio import Audio from .audio import Audio
@ -35,6 +36,8 @@ from .photo import Photo
from .poll import Poll from .poll import Poll
from .poll_option import PollOption from .poll_option import PollOption
from .reaction import Reaction from .reaction import Reaction
from .reaction_type import ReactionType
from .reaction_count import ReactionCount
from .sticker import Sticker from .sticker import Sticker
from .stickerset import StickerSet from .stickerset import StickerSet
from .stories_privacy_rules import StoriesPrivacyRules from .stories_privacy_rules import StoriesPrivacyRules
@ -49,6 +52,8 @@ from .web_page import WebPage
from .web_page_empty import WebPageEmpty from .web_page_empty import WebPageEmpty
from .web_page_preview import WebPagePreview from .web_page_preview import WebPagePreview
from .message_reactions import MessageReactions from .message_reactions import MessageReactions
from .message_reaction_updated import MessageReactionUpdated
from .message_reaction_count_updated import MessageReactionCountUpdated
from .message_story import MessageStory from .message_story import MessageStory
from .story import Story from .story import Story
from .story_deleted import StoryDeleted from .story_deleted import StoryDeleted
@ -60,5 +65,5 @@ from .exported_story_link import ExportedStoryLink
__all__ = [ __all__ = [
"Animation", "Audio", "Contact", "Document", "Game", "Giveaway", "GiveawayLaunched", "GiveawayResult", "Location", "MediaArea", "MediaAreaChannelPost", "MediaAreaCoordinates", "Message", "MessageEntity", "Photo", "Thumbnail", "Animation", "Audio", "Contact", "Document", "Game", "Giveaway", "GiveawayLaunched", "GiveawayResult", "Location", "MediaArea", "MediaAreaChannelPost", "MediaAreaCoordinates", "Message", "MessageEntity", "Photo", "Thumbnail",
"StrippedThumbnail", "Poll", "PollOption", "Sticker", "StickerSet", "Venue", "Video", "VideoNote", "Voice", "WebPage", "WebPageEmpty", "WebPagePreview", "Dice", "StrippedThumbnail", "Poll", "PollOption", "Sticker", "StickerSet", "Venue", "Video", "VideoNote", "Voice", "WebPage", "WebPageEmpty", "WebPagePreview", "Dice",
"Reaction", "WebAppData", "MessageReactions", "MessageStory", "Story", "StoryDeleted", "StorySkipped", "StoryViews", "StoryForwardHeader", "StoriesPrivacyRules", "ExportedStoryLink" "Reaction", "WebAppData", "MessageReactions", "ReactionCount", "ReactionType", "MessageReactionUpdated", "MessageReactionCountUpdated", "MessageStory", "Story", "StoryDeleted", "StorySkipped", "StoryViews", "StoryForwardHeader", "StoriesPrivacyRules", "ExportedStoryLink"
] ]

View file

@ -4360,7 +4360,7 @@ class Message(Object, Update):
else: else:
await self.reply(button, quote=quote) await self.reply(button, quote=quote)
async def react(self, emoji: str = "", big: bool = False) -> bool: async def react(self, emoji: str = "", big: bool = False, add_to_recent: bool = True) -> "types.MessageReactions":
"""Bound method *react* of :obj:`~pyrogram.types.Message`. """Bound method *react* of :obj:`~pyrogram.types.Message`.
Use as a shortcut for: Use as a shortcut for:
@ -4386,9 +4386,13 @@ class Message(Object, Update):
big (``bool``, *optional*): big (``bool``, *optional*):
Pass True to show a bigger and longer reaction. Pass True to show a bigger and longer reaction.
Defaults to False. Defaults to False.
add_to_recent (``bool``, *optional*):
Pass True if the reaction should appear in the recently used reactions.
This option is applicable only for users.
Returns: Returns:
``bool``: On success, True is returned. :obj: `~pyrogram.types.MessageReactions`: On success, True is returned.
Raises: Raises:
RPCError: In case of a Telegram RPC error. RPCError: In case of a Telegram RPC error.

View file

@ -0,0 +1,89 @@
# PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of PyroFork.
#
# PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
from typing import Dict, List
import pyrogram
from pyrogram import raw, types, utils
from ..object import Object
from ..update import Update
class MessageReactionCountUpdated(Object, Update):
"""Reactions to a message with anonymous reactions were changed.
These updates are heavy and their changes may be delayed by a few minutes.
Parameters:
chat (:obj:`~pyrogram.types.Chat`):
The chat containing the message the user reacted to
message_id (``int``):
Unique identifier of the message inside the chat
date (:py:obj:`~datetime.datetime`):
Date of change of the reaction
reactions (:obj:`~pyrogram.types.ReactionCount`):
List of reactions that are present on the message
"""
def __init__(
self,
*,
client: "pyrogram.Client" = None,
chat: "types.Chat",
message_id: int,
date: datetime,
reactions: List["types.ReactionCount"]
):
super().__init__(client)
self.chat = chat
self.message_id = message_id
self.date = date
self.reactions = reactions
@staticmethod
def _parse(
client: "pyrogram.Client",
update: "raw.types.UpdateBotMessageReactions",
users: Dict[int, "raw.types.User"],
chats: Dict[int, "raw.types.Chat"]
) -> "MessageReactionUpdated":
chat = None
peer_id = utils.get_peer_id(update.peer)
raw_peer_id = utils.get_raw_peer_id(update.peer)
if peer_id > 0:
chat = types.Chat._parse_user_chat(client, users[raw_peer_id])
else:
chat = types.Chat._parse_chat_chat(client, chats[raw_peer_id])
return MessageReactionCountUpdated(
client=client,
chat=chat,
message_id=update.msg_id,
date=utils.timestamp_to_datetime(update.date),
reactions=[
types.ReactionCount._parse(
client,
rt
) for rt in update.reactions
]
)

View file

@ -0,0 +1,124 @@
# PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of PyroFork.
#
# PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
from typing import Dict, List
import pyrogram
from pyrogram import raw, types, utils
from ..object import Object
from ..update import Update
class MessageReactionUpdated(Object, Update):
"""This object represents a change of a reaction on a message performed by a user.
A reaction to a message was changed by a user.
The update isn't received for reactions set by bots.
These updates are heavy and their changes may be delayed by a few minutes.
Parameters:
id (``int``):
Unique identifier of the message inside the chat
chat (:obj:`~pyrogram.types.Chat`):
The chat containing the message the user reacted to
from_user (:obj:`~pyrogram.types.User`, *optional*):
The user that changed the reaction, if the user isn't anonymous
actor_chat (:obj:`~pyrogram.types.Chat`, *optional*):
The chat on behalf of which the reaction was changed, if the user is anonymous
date (:py:obj:`~datetime.datetime`):
Date of change of the reaction
old_reaction (:obj:`~pyrogram.types.ReactionType`):
Previous list of reaction types that were set by the user
new_reaction (:obj:`~pyrogram.types.ReactionType`):
New list of reaction types that have been set by the user
"""
def __init__(
self,
*,
client: "pyrogram.Client" = None,
id: int,
from_user: "types.User",
actor_chat: "types.Chat",
date: datetime,
chat: "types.Chat",
old_reaction: List["types.ReactionType"],
new_reaction: List["types.ReactionType"]
):
super().__init__(client)
self.id = id
self.from_user = from_user
self.actor_chat = actor_chat
self.date = date
self.chat = chat
self.old_reaction = old_reaction
self.new_reaction = new_reaction
@staticmethod
def _parse(
client: "pyrogram.Client",
update: "raw.types.UpdateBotMessageReaction",
users: Dict[int, "raw.types.User"],
chats: Dict[int, "raw.types.Chat"]
) -> "MessageReactionUpdated":
chat = None
peer_id = utils.get_peer_id(update.peer)
raw_peer_id = utils.get_raw_peer_id(update.peer)
if peer_id > 0:
chat = types.Chat._parse_user_chat(client, users[raw_peer_id])
else:
chat = types.Chat._parse_channel_chat(client, chats[raw_peer_id])
from_user = None
actor_chat = None
raw_actor_peer_id = utils.get_raw_peer_id(update.actor)
actor_peer_id = utils.get_peer_id(update.actor)
if actor_peer_id > 0:
from_user = types.User._parse(client, users[raw_actor_peer_id])
else:
actor_chat = types.Chat._parse_channel_chat(client, chats[raw_actor_peer_id])
return MessageReactionUpdated(
client=client,
id=update.msg_id,
from_user=from_user,
date=utils.timestamp_to_datetime(update.date),
chat=chat,
actor_chat=actor_chat,
old_reaction=[
types.ReactionType._parse(
rt
) for rt in update.old_reactions
],
new_reaction=[
types.ReactionType._parse(
rt
) for rt in update.new_reactions
]
)

View file

@ -51,6 +51,8 @@ class MessageReactions(Object):
return MessageReactions( return MessageReactions(
client=client, client=client,
reactions=[types.Reaction._parse_count(client, reaction) reactions=[
for reaction in message_reactions.results] types.Reaction._parse_count(client, reaction)
for reaction in message_reactions.results
]
) )

View file

@ -1,20 +1,21 @@
# Pyrogram - Telegram MTProto API Client Library for Python # PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrogram. # This file is part of PyroFork.
# #
# Pyrogram is free software: you can redistribute it and/or modify # PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrogram is distributed in the hope that it will be useful, # PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional from typing import Optional

View file

@ -0,0 +1,63 @@
# PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of PyroFork.
#
# PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional
from pyrogram import raw
from .reaction_type import ReactionType
from ..object import Object
class ReactionCount(Object):
"""Represents a reaction added to a message along with the number of times it was added.
Parameters:
type (:obj:`~pyrogram.types.ReactionType`):
Reaction type.
total_count (``int``):
Total reaction count.
chosen_order (``int``):
Chosen reaction order.
Available for chosen reactions.
"""
def __init__(
self,
*,
type: ReactionType,
total_count: int,
chosen_order: int
):
super().__init__()
self.type = type
self.total_count = total_count
self.chosen_order = chosen_order
@staticmethod
def _parse(
update: "raw.types.ReactionCount",
) -> Optional["ReactionCount"]:
return ReactionCount(
type=ReactionType._parse(
update.reaction
),
total_count=update.count,
chosen_order=update.chosen_order
)

View file

@ -0,0 +1,74 @@
# PyroFork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of PyroFork.
#
# PyroFork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyroFork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PyroFork. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional
from pyrogram import enums, raw
from ..object import Object
class ReactionType(Object):
"""Contains information about a reaction.
Parameters:
type (``enums.ReactionType``, *optional*):
Reaction type.
emoji (``str``, *optional*):
Reaction emoji.
custom_emoji_id (``int``, *optional*):
Custom emoji id.
"""
def __init__(
self,
*,
type: str = "enums.ReactionType",
emoji: str = None,
custom_emoji_id: str = None
):
super().__init__()
self.type = type
self.emoji = emoji
self.custom_emoji_id = custom_emoji_id
@staticmethod
def _parse(
update: "raw.types.Reaction",
) -> Optional["ReactionType"]:
if isinstance(update, raw.types.ReactionEmpty):
return None
elif isinstance(update, raw.types.ReactionEmoji):
return ReactionType(
type=enums.ReactionType.EMOJI,
emoji=update.emoticon
)
elif isinstance(update, raw.types.ReactionCustomEmoji):
return ReactionType(
type=enums.ReactionType.CUSTOM_EMOJI,
custom_emoji_id=update.document_id
)
def write(self):
if self.type == enums.ReactionType.EMOJI:
return raw.types.ReactionEmoji(
emoticon=self.emoji
)
if self.type == enums.ReactionType.CUSTOM_EMOJI:
return raw.types.ReactionCustomEmoji(
document_id=self.custom_emoji_id
)

View file

@ -474,7 +474,10 @@ class Chat(Object):
if isinstance(full_chat.exported_invite, raw.types.ChatInviteExported): if isinstance(full_chat.exported_invite, raw.types.ChatInviteExported):
parsed_chat.invite_link = full_chat.exported_invite.link parsed_chat.invite_link = full_chat.exported_invite.link
parsed_chat.available_reactions = types.ChatReactions._parse(client, full_chat.available_reactions) parsed_chat.available_reactions = types.ChatReactions._parse(
client,
full_chat.available_reactions
)
return parsed_chat return parsed_chat

View file

@ -62,8 +62,12 @@ class ChatReactions(Object):
if isinstance(chat_reactions, raw.types.ChatReactionsSome): if isinstance(chat_reactions, raw.types.ChatReactionsSome):
return ChatReactions( return ChatReactions(
client=client, client=client,
reactions=[types.Reaction._parse(client, reaction) reactions=[
for reaction in chat_reactions.reactions] types.ReactionType._parse(reaction)
for reaction in chat_reactions.reactions
]
) )
if isinstance(chat_reactions, raw.types.ChatReactionsNone):
return None
return None return None