Add support for stories

This commit is contained in:
wulan17 2023-10-13 22:11:52 +03:00 committed by KurimuzonAkuma
parent f2b417a16d
commit 3a01fea2c2
47 changed files with 3513 additions and 53 deletions

View File

@ -26,7 +26,7 @@ from pyrogram import utils
from pyrogram.handlers import (
CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler,
UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler,
ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler
ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler, StoryHandler
)
from pyrogram.raw.types import (
UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage,
@ -35,7 +35,7 @@ from pyrogram.raw.types import (
UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery,
UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll,
UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant,
UpdateBotChatInviteRequester
UpdateBotChatInviteRequester, UpdateStory
)
log = logging.getLogger(__name__)
@ -52,6 +52,7 @@ class Dispatcher:
POLL_UPDATES = (UpdateMessagePoll,)
CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,)
CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,)
NEW_STORY_UPDATES = (UpdateStory,)
def __init__(self, client: "pyrogram.Client"):
self.client = client
@ -127,6 +128,12 @@ class Dispatcher:
ChatJoinRequestHandler
)
async def story_parser(update, _, __):
return (
await pyrogram.types.Story._parse(self.client, update.story, update.peer),
StoryHandler
)
self.update_parsers = {
Dispatcher.NEW_MESSAGE_UPDATES: message_parser,
Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser,
@ -137,7 +144,8 @@ class Dispatcher:
Dispatcher.POLL_UPDATES: poll_parser,
Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_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
}
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}

View File

@ -29,21 +29,25 @@ from .next_code_type import NextCodeType
from .parse_mode import ParseMode
from .poll_type import PollType
from .sent_code_type import SentCodeType
from .stories_privacy import StoriesPrivacy
from .stories_privacy_rules import StoriesPrivacyRules
from .user_status import UserStatus
__all__ = [
'ChatAction',
'ChatEventAction',
'ChatMemberStatus',
'ChatMembersFilter',
'ChatType',
'MessageEntityType',
'MessageMediaType',
'MessageServiceType',
'MessagesFilter',
'NextCodeType',
'ParseMode',
'PollType',
'SentCodeType',
'ChatAction',
'ChatEventAction',
'ChatMemberStatus',
'ChatMembersFilter',
'ChatType',
'MessageEntityType',
'MessageMediaType',
'MessageServiceType',
'MessagesFilter',
'NextCodeType',
'ParseMode',
'PollType',
'SentCodeType',
'StoriesPrivacy',
'StoriesPrivacyRules',
'UserStatus'
]

View File

@ -68,3 +68,6 @@ class MessageMediaType(AutoName):
GAME = auto()
"Game media"
STORY = auto()
"Story media"

View File

@ -0,0 +1,39 @@
# 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 enum import auto
from .auto_name import AutoName
class StoriesPrivacy(AutoName):
"""Stories privacy type enumeration used in :obj:`~pyrogram.method.SendStory`."""
PUBLIC = auto()
"Public stories"
CLOSE_FRIENDS = auto()
"Close friends stories"
CONTACTS = auto()
"Contacts only stories"
PRIVATE = auto()
"Private stories"
NO_CONTACTS = auto()
"Hide stories from contacts"

View File

@ -0,0 +1,39 @@
# 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 enum import auto
from .auto_name import AutoName
class StoriesPrivacyRules(AutoName):
"""Stories privacy rules type enumeration used in :obj:`~pyrogram.method.SendStory`."""
PUBLIC = auto()
"Public stories"
CLOSE_FRIENDS = auto()
"Close friends stories"
CONTACTS = auto()
"Contacts only stories"
PRIVATE = auto()
"Private stories"
NO_CONTACTS = auto()
"Hide stories from contacts"

View File

@ -27,4 +27,5 @@ from .inline_query_handler import InlineQueryHandler
from .message_handler import MessageHandler
from .poll_handler import PollHandler
from .raw_update_handler import RawUpdateHandler
from .story_handler import StoryHandler
from .user_status_handler import UserStatusHandler

View File

@ -0,0 +1,49 @@
# 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 StoryHandler(Handler):
"""The Story handler class. Used to handle new stories.
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_story` decorator.
Parameters:
callback (``Callable``):
Pass a function that will be called when a new Stories arrives. It takes *(client, story)*
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 stories 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 story handler.
story (:obj:`~pyrogram.types.Story`):
The received story.
"""
def __init__(self, callback: Callable, filters=None):
super().__init__(callback, filters)

View File

@ -26,6 +26,7 @@ from .invite_links import InviteLinks
from .messages import Messages
from .password import Password
from .users import Users
from .stories import Stories
from .utilities import Utilities
@ -37,6 +38,7 @@ class Methods(
Password,
Chats,
Users,
Stories,
Messages,
Decorators,
Utilities,

View File

@ -28,6 +28,7 @@ from .on_message import OnMessage
from .on_poll import OnPoll
from .on_raw_update import OnRawUpdate
from .on_user_status import OnUserStatus
from .on_story import OnStory
class Decorators(
@ -42,6 +43,7 @@ class Decorators(
OnPoll,
OnChosenInlineResult,
OnChatMemberUpdated,
OnChatJoinRequest
OnChatJoinRequest,
OnStory
):
pass

View File

@ -0,0 +1,61 @@
# 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 OnStory:
def on_story(
self=None,
filters=None,
group: int = 0
) -> Callable:
"""Decorator for handling new stories.
This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
:obj:`~pyrogram.handlers.StoryHandler`.
Parameters:
filters (:obj:`~pyrogram.filters`, *optional*):
Pass one or more filters to allow only a subset of stories 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.StoryHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
if not hasattr(func, "handlers"):
func.handlers = []
func.handlers.append(
(
pyrogram.handlers.StoryHandler(func, self),
group if filters is None else filters
)
)
return func
return decorator

View File

@ -48,6 +48,7 @@ class SendAnimation:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -123,6 +124,9 @@ class SendAnimation:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -230,12 +234,13 @@ class SendAnimation:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -46,6 +46,7 @@ class SendAudio:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -116,6 +117,9 @@ class SendAudio:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -217,12 +221,13 @@ class SendAudio:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -36,6 +36,7 @@ class SendCachedMedia:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -84,6 +85,9 @@ class SendCachedMedia:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -102,12 +106,13 @@ class SendCachedMedia:
await app.send_cached_media("me", file_id)
"""
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=utils.get_input_media_from_file_id(file_id),
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -32,6 +32,7 @@ class SendDice:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -69,6 +70,9 @@ class SendDice:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -94,12 +98,13 @@ class SendDice:
# Send a basketball
await app.send_dice(chat_id, "🏀")
"""
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=raw.types.InputMediaDice(emoticon=emoji),
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -44,6 +44,7 @@ class SendDocument:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -108,6 +109,9 @@ class SendDocument:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -195,12 +199,13 @@ class SendDocument:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -45,6 +45,7 @@ class SendMediaGroup:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
) -> List["types.Message"]:
@ -72,6 +73,9 @@ class SendMediaGroup:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -395,12 +399,13 @@ class SendMediaGroup:
)
)
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMultiMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
multi_media=multi_media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content
),

View File

@ -35,6 +35,7 @@ class SendMessage:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -78,6 +79,9 @@ class SendMessage:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -128,12 +132,13 @@ class SendMessage:
message, entities = (await utils.parse_text_entities(self, text, parse_mode, entities)).values()
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMessage(
peer=await self.resolve_peer(chat_id),
peer=peer,
no_webpage=disable_web_page_preview or None,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
reply_markup=await reply_markup.write(self) if reply_markup else None,

View File

@ -42,6 +42,7 @@ class SendPhoto:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -99,6 +100,9 @@ class SendPhoto:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -179,12 +183,13 @@ class SendPhoto:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -38,6 +38,7 @@ class SendSticker:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -77,6 +78,9 @@ class SendSticker:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -154,12 +158,13 @@ class SendSticker:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -49,6 +49,7 @@ class SendVideo:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -129,6 +130,9 @@ class SendVideo:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message.
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -236,12 +240,13 @@ class SendVideo:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -40,6 +40,7 @@ class SendVideoNote:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -91,6 +92,9 @@ class SendVideoNote:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -178,12 +182,13 @@ class SendVideoNote:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -42,6 +42,7 @@ class SendVoice:
disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None,
reply_to_story_id: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
reply_markup: Union[
@ -94,6 +95,9 @@ class SendVoice:
reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message
reply_to_story_id (``int``, *optional*):
Unique identifier for the target story.
schedule_date (:py:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent.
@ -179,12 +183,13 @@ class SendVoice:
while True:
try:
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id, peer, reply_to_story_id),
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,

View File

@ -0,0 +1,46 @@
# 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 .apply_boost import ApplyBoost
from .delete_stories import DeleteStories
from .edit_story import EditStory
from .export_story_link import ExportStoryLink
from .get_all_stories import GetAllStories
from .get_peer_stories import GetPeerStories
from .get_stories_archive import GetStoriesArchive
from .get_stories import GetStories
from .increment_story_views import IncrementStoryViews
from .read_stories import ReadStories
from .send_story import SendStory
from .toggle_stories_pinned import ToggleStoriesPinned
class Stories(
ApplyBoost,
DeleteStories,
EditStory,
ExportStoryLink,
GetAllStories,
GetPeerStories,
GetStories,
GetStoriesArchive,
IncrementStoryViews,
ReadStories,
SendStory,
ToggleStoriesPinned
):
pass

View File

@ -0,0 +1,53 @@
# 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 Union
import pyrogram
from pyrogram import raw
class ApplyBoost:
async def apply_boost(
self: "pyrogram.Client",
chat_id: Union[int, str],
) -> bool:
"""Apply boost
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
Returns:
``str``: On success, a bool is returned.
Example:
.. code-block:: python
# Apply boost to chat id
app.apply_boost(chat_id)
"""
r = await self.invoke(
raw.functions.stories.ApplyBoost(
peer=await self.resolve_peer(chat_id),
)
)
return r

View File

@ -0,0 +1,67 @@
# 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 List, Union, Iterable
import pyrogram
from pyrogram import raw
from pyrogram import types
class DeleteStories:
async def delete_stories(
self: "pyrogram.Client",
chat_id: Union[int, str],
story_ids: Union[int, Iterable[int]],
) -> List[int]:
"""Delete stories.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
story_ids (``int`` | ``list``):
Unique identifier (int) or list of unique identifiers (list of int) for the target stories.
Returns:
List of ``int``: List of deleted stories IDs
Example:
.. code-block:: python
# Delete a single story
app.delete_stories(chat_id, 1)
# Delete multiple stories
app.delete_stories(chat_id, [1, 2])
"""
is_iterable = not isinstance(story_ids, int)
ids = list(story_ids) if is_iterable else [story_ids]
r = await self.invoke(
raw.functions.stories.DeleteStories(
peer=await self.resolve_peer(chat_id),
id=ids
)
)
return types.List(r)

View File

@ -0,0 +1,233 @@
# 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/>.
import os
import re
from typing import List, Union, BinaryIO, Callable
import pyrogram
from pyrogram import enums, raw, types, utils, StopTransmission
from pyrogram.errors import FilePartMissing
class EditStory:
async def edit_story(
self: "pyrogram.Client",
chat_id: Union[int, str],
story_id: int,
media: Union[str, BinaryIO] = None,
caption: str = None,
duration: int = 0,
width: int = 0,
height: int = 0,
thumb: Union[str, BinaryIO] = None,
supports_streaming: bool = True,
file_name: str = None,
privacy: "enums.StoriesPrivacyRules" = None,
allowed_users: List[int] = None,
denied_users: List[int] = None,
allowed_chats: List[int] = None,
denied_chats: List[int] = None,
parse_mode: "enums.ParseMode" = None,
caption_entities: List["types.MessageEntity"] = None,
progress: Callable = None,
progress_args: tuple = ()
) -> "types.Story":
"""Edit story.
.. include:: /_includes/usable-by/users.rst
Note: You must pass one of following paramater *animation*, *photo*, *video*
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
media (``str`` | ``BinaryIO``, *optional*):
Video or photo to send.
Pass a file_id as string to send a animation that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get a animation from the Internet,
pass a file path as string to upload a new animation that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
caption (``str``, *optional*):
Story caption, 0-1024 characters.
duration (``int``, *optional*):
Duration of sent video in seconds.
width (``int``, *optional*):
Video width.
height (``int``, *optional*):
Video height.
thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
privacy (:obj:`~pyrogram.enums.StoriesPrivacyRules`, *optional*):
Story privacy.
Defaults to :obj:`~pyrogram.enums.StoriesPrivacyRules.PUBLIC`
allowed_chats (List of ``int``, *optional*):
List of chat_id which participant allowed to view the story.
denied_chats (List of ``int``, *optional*):
List of chat_id which participant denied to view the story.
allowed_users (List of ``int``, *optional*):
List of user_id whos allowed to view the story.
denied_users (List of ``int``, *optional*):
List of user_id whos denied to view the story.
parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
List of special entities that appear in the caption, which can be specified instead of *parse_mode*.
progress (``Callable``, *optional*):
Pass a callback function to view the file transmission progress.
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
detailed description) and will be called back each time a new file chunk has been successfully
transmitted.
progress_args (``tuple``, *optional*):
Extra custom arguments for the progress callback function.
You can pass anything you need to be available in the progress callback scope; for example, a Message
object or a Client instance in order to edit the message with the updated progress status.
Returns:
:obj:`~pyrogram.types.Story` a single story is returned.
Example:
.. code-block:: python
# Send new photo story
photo_id = "abcd12345"
await app.send_story(photo=photo_id, caption='Hello guys.')
Raises:
ValueError: In case of invalid arguments.
"""
# TODO: media_areas
if privacy:
privacy_rules = [types.StoriesPrivacyRules(type=privacy)]
message, entities = (await utils.parse_text_entities(self, caption, parse_mode, caption_entities)).values()
try:
if isinstance(media, str):
if os.path.isfile(media):
thumb = await self.save_file(thumb)
file = await self.save_file(media, progress=progress, progress_args=progress_args)
mime_type = self.guess_mime_type(file.name)
if mime_type == "video/mp4":
media = raw.types.InputMediaUploadedDocument(
mime_type=mime_type,
file=file,
thumb=thumb,
attributes=[
raw.types.DocumentAttributeVideo(
duration=duration,
w=width,
h=height,
),
raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(media))
]
)
else:
media = raw.types.InputMediaUploadedPhoto(
file=file,
)
elif re.match("^https?://", media):
mime_type = self.guess_mime_type(media)
if mime_type == "video/mp4":
media = raw.types.InputMediaDocumentExternal(
url=media,
)
else:
media = raw.types.InputMediaPhotoExternal(
url=media,
)
else:
media = utils.get_input_media_from_file_id(media)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(media, progress=progress, progress_args=progress_args)
mime_type = self.guess_mime_type(file.name)
if mime_type == "video/mp4":
media = raw.types.InputMediaUploadedDocument(
mime_type=mime_type,
file=file,
thumb=thumb,
attributes=[
raw.types.DocumentAttributeVideo(
supports_streaming=supports_streaming or None,
duration=duration,
w=width,
h=height,
),
raw.types.DocumentAttributeFilename(file_name=file_name or media.name)
]
)
else:
media = raw.types.InputMediaUploadedPhoto(
file=file,
)
if allowed_chats:
chats = [await self.resolve_peer(chat_id) for chat_id in allowed_chats]
privacy_rules.append(raw.types.InputPrivacyValueAllowChatParticipants(chats=chats))
if denied_chats:
chats = [await self.resolve_peer(chat_id) for chat_id in denied_chats]
privacy_rules.append(raw.types.InputPrivacyValueDisallowChatParticipants(chats=chats))
if allowed_users:
users = [await self.resolve_peer(user_id) for user_id in allowed_users]
privacy_rules.append(raw.types.InputPrivacyValueAllowUsers(users=users))
if denied_users:
users = [await self.resolve_peer(user_id) for user_id in denied_users]
privacy_rules.append(raw.types.InputPrivacyValueDisallowUsers(users=users))
while True:
try:
r = await self.invoke(
raw.functions.stories.EditStory(
peer=await self.resolve_peer(chat_id),
id=story_id,
media=media,
caption=message,
entities=entities,
privacy_rules=privacy_rules,
)
)
except FilePartMissing as e:
await self.save_file(media, file_id=file.id, file_part=e.value)
else:
for i in r.updates:
if isinstance(i, raw.types.UpdateStory):
return await types.Story._parse(self, i.story, i.peer)
except StopTransmission:
return None

View File

@ -0,0 +1,61 @@
# 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 Union
import pyrogram
from pyrogram import raw
from pyrogram import types
class ExportStoryLink:
async def export_story_link(
self: "pyrogram.Client",
chat_id: Union[int, str],
story_id: int,
) -> "types.ExportedStoryLink":
"""Export a story link.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
story_id (``int``):
Unique identifier of the target story.
Returns:
``str``: On success, a link to the exported story is returned.
Example:
.. code-block:: python
# Export a story link
link = app.export_story_link(chat_id, 1)
"""
r = await self.invoke(
raw.functions.stories.ExportStoryLink(
peer=await self.resolve_peer(chat_id),
id=story_id
)
)
return r.link

View File

@ -0,0 +1,61 @@
# 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 AsyncGenerator, Union, Optional
import pyrogram
from pyrogram import raw
from pyrogram import types
class GetAllStories:
async def get_all_stories(
self: "pyrogram.Client",
next: Optional[bool] = None,
hidden: Optional[bool] = None,
state: Optional[str] = None,
) -> Optional[AsyncGenerator["types.Story", None]]:
"""Get all active stories.
.. include:: /_includes/usable-by/users.rst
Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.Story` objects is returned.
Example:
.. code-block:: python
# Get all active story
async for story in app.get_all_stories():
print(story)
Raises:
ValueError: In case of invalid arguments.
"""
r = await self.invoke(
raw.functions.stories.GetAllStories(
next=next,
hidden=hidden,
state=state
)
)
for peer_story in r.peer_stories:
for story in peer_story.stories:
yield await types.Story._parse(self, story, peer_story.peer)

View File

@ -0,0 +1,63 @@
# 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 AsyncGenerator, Union, Optional
import pyrogram
from pyrogram import raw
from pyrogram import types
class GetPeerStories:
async def get_peer_stories(
self: "pyrogram.Client",
chat_id: Union[int, str]
) -> Optional[AsyncGenerator["types.Story", None]]:
"""Get all active stories from an user by using user identifiers.
.. include:: /_includes/usable-by/users.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target user.
For your personal story you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.Story` objects is returned.
Example:
.. code-block:: python
# Get all active story from spesific user
async for story in app.get_peer_stories(chat_id):
print(story)
Raises:
ValueError: In case of invalid arguments.
"""
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.stories.GetPeerStories(
peer=peer
)
)
for story in r.stories.stories:
yield await types.Story._parse(self, story, peer)

View File

@ -0,0 +1,76 @@
# 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 Union, Iterable
import pyrogram
from pyrogram import raw
from pyrogram import types
class GetStories:
async def get_stories(
self: "pyrogram.Client",
chat_id: Union[int, str],
story_ids: Union[int, Iterable[int]],
) -> "types.Stories":
"""Get stories by id.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target user.
For your personal story you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
story_ids (List of ``int`` ``32-bit``):
Pass a single story identifier or an iterable of story ids (as integers) to get the content of the
story themselves.
Returns:
:obj:`~pyrogram.types.Story` | List of :obj:`~pyrogram.types.Story`: In case *story_ids* was not
a list, a single story is returned, otherwise a list of stories is returned.
Example:
.. code-block:: python
# Get stories by id
stories = await app.get_stories_by_id(chat_id, [1, 2, 3])
for story in stories:
print(story)
"""
is_iterable = not isinstance(story_ids, int)
ids = list(story_ids) if is_iterable else [story_ids]
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.stories.GetStoriesByID(
peer=peer,
id=ids
)
)
stories = []
for i in r.updates:
if isinstance(i, raw.types.stories.PeerStories):
stories = [await types.Story._parse(self, story, peer) for story in r.stories]
return types.List(stories) if is_iterable else stories[0]

View File

@ -0,0 +1,74 @@
# 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 AsyncGenerator, Union, Optional
import pyrogram
from pyrogram import raw
from pyrogram import types
class GetStoriesArchive:
async def get_stories_archive(
self: "pyrogram.Client",
chat_id: Union[int, str],
limit: int = 0,
offset_id: int = 0
) -> Optional[AsyncGenerator["types.Story", None]]:
"""Get stories archive.
.. include:: /_includes/usable-by/users.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
limit (``int``, *optional*):
Limits the number of stories to be retrieved.
By default, no limit is applied and all stories are returned.
offset_id (``int``, *optional*):
Identifier of the first story to be returned.
Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.Story` objects is returned.
Example:
.. code-block:: python
# Get story archive
async for story in app.get_stories_archive(chat_id):
print(story)
Raises:
ValueError: In case of invalid arguments.
"""
peer = await self.resolve_peer(chat_id)
r = await self.invoke(
raw.functions.stories.GetStoriesArchive(
peer=peer,
offset_id=offset_id,
limit=limit
)
)
for story in r.stories:
yield await types.Story._parse(self, story, peer)

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 Union
import pyrogram
from pyrogram import raw
class IncrementStoryViews:
async def increment_story_views(
self: "pyrogram.Client",
chat_id: Union[int, str],
story_id: int,
) -> bool:
"""Increment story views.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
story_id (``int``):
Unique identifier of the target story.
Returns:
``bool``: On success, True is returned.
Example:
.. code-block:: python
# Increment story views
await app.increment_story_views(chat_id, 1)
"""
r = await self.invoke(
raw.functions.stories.IncrementStoryViews(
peer=await self.resolve_peer(chat_id),
id=story_id
)
)
return r

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 List, Union
import pyrogram
from pyrogram import raw, types
class ReadStories:
async def read_stories(
self: "pyrogram.Client",
chat_id: Union[int, str],
max_id: int = 0,
) -> List[int]:
"""Read stories.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
max_id (``int``, *optional*):
Maximum identifier of the target story to read.
Returns:
List of ``int``: On success, a list of read stories is returned.
Example:
.. code-block:: python
# Read stories
await app.read_stories(chat_id)
"""
r = await self.invoke(
raw.functions.stories.ReadStories(
peer=await self.resolve_peer(chat_id),
max_id=max_id
)
)
return types.List(r)

View File

@ -0,0 +1,252 @@
# 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/>.
import os
import re
from typing import List, Union, BinaryIO, Callable
import pyrogram
from pyrogram import enums, raw, types, utils, StopTransmission
from pyrogram.errors import FilePartMissing
class SendStory:
async def send_story(
self: "pyrogram.Client",
chat_id: Union[int, str],
media: Union[str, BinaryIO],
caption: str = None,
period: int = None,
duration: int = 0,
width: int = 0,
height: int = 0,
thumb: Union[str, BinaryIO] = None,
supports_streaming: bool = True,
file_name: str = None,
privacy: "enums.StoriesPrivacyRules" = None,
allowed_users: List[int] = None,
denied_users: List[int] = None,
allowed_chats: List[int] = None,
denied_chats: List[int] = None,
pinned: bool = None,
protect_content: bool = None,
parse_mode: "enums.ParseMode" = None,
caption_entities: List["types.MessageEntity"] = None,
progress: Callable = None,
progress_args: tuple = ()
) -> "types.Story":
"""Send new story.
.. include:: /_includes/usable-by/users.rst
Note: You must pass one of following paramater *animation*, *photo*, *video*
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
media (``str`` | ``BinaryIO``):
Video or photo to send.
Pass a file_id as string to send a animation that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get a animation from the Internet,
pass a file path as string to upload a new animation that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
caption (``str``, *optional*):
Story caption, 0-1024 characters.
period (``int``, *optional*):
How long the story will posted, in secs.
only for premium users.
duration (``int``, *optional*):
Duration of sent video in seconds.
width (``int``, *optional*):
Video width.
height (``int``, *optional*):
Video height.
thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
privacy (:obj:`~pyrogram.enums.StoriesPrivacyRules`, *optional*):
Story privacy.
Defaults to :obj:`~pyrogram.enums.StoriesPrivacyRules.PUBLIC`
allowed_chats (List of ``int``, *optional*):
List of chat_id which participant allowed to view the story.
denied_chats (List of ``int``, *optional*):
List of chat_id which participant denied to view the story.
allowed_users (List of ``int``, *optional*):
List of user_id whos allowed to view the story.
denied_users (List of ``int``, *optional*):
List of user_id whos denied to view the story.
pinned (``bool``, *optional*):
if True, the story will be pinned.
default to False.
protect_content (``bool``, *optional*):
Protects the contents of the sent story from forwarding and saving.
default to False.
parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
List of special entities that appear in the caption, which can be specified instead of *parse_mode*.
progress (``Callable``, *optional*):
Pass a callback function to view the file transmission progress.
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
detailed description) and will be called back each time a new file chunk has been successfully
transmitted.
progress_args (``tuple``, *optional*):
Extra custom arguments for the progress callback function.
You can pass anything you need to be available in the progress callback scope; for example, a Message
object or a Client instance in order to edit the message with the updated progress status.
Returns:
:obj:`~pyrogram.types.Story` a single story is returned.
Example:
.. code-block:: python
# Send new photo story
photo_id = "abcd12345"
await app.send_story(photo=photo_id, caption='Hello guys.')
Raises:
ValueError: In case of invalid arguments.
"""
# TODO: media_areas
if privacy:
privacy_rules = [types.StoriesPrivacyRules(type=privacy)]
else:
privacy_rules = [types.StoriesPrivacyRules(type=enums.StoriesPrivacyRules.PUBLIC)]
message, entities = (await utils.parse_text_entities(self, caption, parse_mode, caption_entities)).values()
try:
if isinstance(media, str):
if os.path.isfile(media):
thumb = await self.save_file(thumb)
file = await self.save_file(media, progress=progress, progress_args=progress_args)
mime_type = self.guess_mime_type(file.name)
if mime_type == "video/mp4":
media = raw.types.InputMediaUploadedDocument(
mime_type=mime_type,
file=file,
thumb=thumb,
attributes=[
raw.types.DocumentAttributeVideo(
duration=duration,
w=width,
h=height,
),
raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(media))
]
)
else:
media = raw.types.InputMediaUploadedPhoto(
file=file,
)
elif re.match("^https?://", media):
mime_type = self.guess_mime_type(media)
if mime_type == "video/mp4":
media = raw.types.InputMediaDocumentExternal(
url=media,
)
else:
media = raw.types.InputMediaPhotoExternal(
url=media,
)
else:
media = utils.get_input_media_from_file_id(media)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(media, progress=progress, progress_args=progress_args)
mime_type = self.guess_mime_type(file.name)
if mime_type == "video/mp4":
media = raw.types.InputMediaUploadedDocument(
mime_type=mime_type,
file=file,
thumb=thumb,
attributes=[
raw.types.DocumentAttributeVideo(
supports_streaming=supports_streaming or None,
duration=duration,
w=width,
h=height,
),
raw.types.DocumentAttributeFilename(file_name=file_name or media.name)
]
)
else:
media = raw.types.InputMediaUploadedPhoto(
file=file,
)
if allowed_chats:
chats = [await self.resolve_peer(chat_id) for chat_id in allowed_chats]
privacy_rules.append(raw.types.InputPrivacyValueAllowChatParticipants(chats=chats))
if denied_chats:
chats = [await self.resolve_peer(chat_id) for chat_id in denied_chats]
privacy_rules.append(raw.types.InputPrivacyValueDisallowChatParticipants(chats=chats))
if allowed_users:
users = [await self.resolve_peer(user_id) for user_id in allowed_users]
privacy_rules.append(raw.types.InputPrivacyValueAllowUsers(users=users))
if denied_users:
users = [await self.resolve_peer(user_id) for user_id in denied_users]
privacy_rules.append(raw.types.InputPrivacyValueDisallowUsers(users=users))
while True:
try:
r = await self.invoke(
raw.functions.stories.SendStory(
peer=await self.resolve_peer(chat_id),
media=media,
privacy_rules=privacy_rules,
random_id=self.rnd_id(),
pinned=pinned,
noforwards=protect_content,
caption=message,
entities=entities,
period=period,
)
)
except FilePartMissing as e:
await self.save_file(media, file_id=file.id, file_part=e.value)
else:
for i in r.updates:
if isinstance(i, raw.types.UpdateStory):
return await types.Story._parse(self, i.story, i.peer)
except StopTransmission:
return None

View File

@ -0,0 +1,68 @@
# 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 List, Union, Iterable
import pyrogram
from pyrogram import raw
class ToggleStoriesPinned:
async def toggle_stories_pinned(
self: "pyrogram.Client",
chat_id: Union[int, str],
stories_ids: Union[int, Iterable[int]],
pinned: bool,
) -> List[int]:
"""Toggle stories pinned.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
stories_ids (List of ``int`` ``32-bit``):
List of unique identifiers of the target stories.
pinned (``bool``):
If set to ``True``, the stories will be pinned.
Returns:
List of ``int``: List of pinned stories IDs
Example:
.. code-block:: python
# Pin a single story
await app.toggle_stories_pinned(chat_id, 123456789, True)
"""
is_iterable = not isinstance(stories_ids, int)
stories_ids = list(stories_ids) if is_iterable else [stories_ids]
r = await self.invoke(
raw.functions.stories.TogglePinned(
peer=await self.resolve_peer(chat_id),
id=stories_ids,
pinned=pinned
)
)
return types.List(r)

View File

@ -18,8 +18,9 @@
from .input_message_content import InputMessageContent
from .input_reply_to_message import InputReplyToMessage
from .input_reply_to_story import InputReplyToStory
from .input_text_message_content import InputTextMessageContent
__all__ = [
"InputMessageContent", "InputReplyToMessage", "InputTextMessageContent"
"InputMessageContent", "InputReplyToMessage", "InputReplyToStory", "InputTextMessageContent"
]

View File

@ -0,0 +1,48 @@
# 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 pyrogram import raw
from ..object import Object
class InputReplyToStory(Object):
"""Contains information about a target replied story.
Parameters:
user_id (:obj:`~pyrogram.raw.types.InputUser`):
An InputUser.
story_id (``int``):
Unique identifier for the target story.
"""
def __init__(
self, *,
user_id: "raw.types.InputUser" = None,
story_id: int = None
):
super().__init__()
self.user_id = user_id
self.story_id = story_id
def write(self):
return raw.types.InputReplyToStory(
user_id=self.user_id,
story_id=self.story_id
).write()

View File

@ -38,6 +38,11 @@ from .poll_option import PollOption
from .reaction import Reaction
from .sticker import Sticker
from .stripped_thumbnail import StrippedThumbnail
from .stories_privacy_rules import StoriesPrivacyRules
from .story import Story
from .story_deleted import StoryDeleted
from .story_skipped import StorySkipped
from .story_views import StoryViews
from .thumbnail import Thumbnail
from .venue import Venue
from .video import Video
@ -46,11 +51,13 @@ from .voice import Voice
from .web_app_data import WebAppData
from .web_page import WebPage
from .message_reactions import MessageReactions
from .message_story import MessageStory
__all__ = [
"Animation", "Audio", "Contact", "Document", "ForumTopic", "ForumTopicCreated",
"ForumTopicClosed", "ForumTopicReopened", "ForumTopicEdited", "GeneralTopicHidden",
"GeneralTopicUnhidden", "Game", "Location", "Message", "MessageEntity", "Photo", "Thumbnail",
"StrippedThumbnail", "Poll", "PollOption", "Sticker", "Venue", "Video", "VideoNote", "Voice",
"WebPage", "Dice", "Reaction", "WebAppData", "MessageReactions"
"StrippedThumbnail", "Story", "StoryDeleted", "StorySkipped", "StoryViews", "StoriesPrivacyRules", "Poll", "PollOption", "Sticker",
"Venue", "Video", "VideoNote", "Voice", "WebPage", "Dice", "Reaction", "WebAppData",
"MessageReactions", "MessageStory"
]

View File

@ -180,6 +180,9 @@ class Message(Object, Update):
game (:obj:`~pyrogram.types.Game`, *optional*):
Message is a game, information about the game.
story (:obj:`~pyrogram.types.MessageStory`):
Message is a story, information about the story.
video (:obj:`~pyrogram.types.Video`, *optional*):
Message is a video, information about the video.
@ -376,6 +379,7 @@ class Message(Object, Update):
sticker: "types.Sticker" = None,
animation: "types.Animation" = None,
game: "types.Game" = None,
story: "types.MessageStory" = None,
video: "types.Video" = None,
voice: "types.Voice" = None,
video_note: "types.VideoNote" = None,
@ -462,6 +466,7 @@ class Message(Object, Update):
self.sticker = sticker
self.animation = animation
self.game = game
self.story = story
self.video = video
self.voice = voice
self.video_note = video_note
@ -744,6 +749,7 @@ class Message(Object, Update):
contact = None
venue = None
game = None
story = None
audio = None
voice = None
animation = None
@ -776,6 +782,9 @@ class Message(Object, Update):
elif isinstance(media, raw.types.MessageMediaGame):
game = types.Game._parse(client, message)
media_type = enums.MessageMediaType.GAME
elif isinstance(media, raw.types.MessageMediaStory):
story = types.MessageStory._parse(media)
media_type = enums.MessageMediaType.STORY
elif isinstance(media, raw.types.MessageMediaDocument):
doc = media.document
@ -904,6 +913,7 @@ class Message(Object, Update):
voice=voice,
animation=animation,
game=game,
story=story,
video=video,
video_note=video_note,
sticker=sticker,

View File

@ -0,0 +1,56 @@
# 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 pyrogram import raw
from ..object import Object
class MessageStory(Object):
"""Contains information about a forwarded story.
Parameters:
chat_id (``int``):
Unique user identifier of story sender.
story_id (``int``):
Unique story identifier.
"""
def __init__(
self,
*,
chat_id: int,
story_id: int
):
super().__init__()
self.chat_id = chat_id
self.story_id = story_id
@staticmethod
def _parse(message_story: "raw.types.MessageMediaStory") -> "MessageStory":
if isinstance(message_story.peer, raw.types.PeerChannel):
chat_id = message_story.peer.channel_id
else:
chat_id = message_story.peer.user_id
return MessageStory(
chat_id=chat_id,
story_id=message_story.id
)

View File

@ -0,0 +1,47 @@
# 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 pyrogram import enums, raw
from ..object import Object
class StoriesPrivacyRules(Object):
"""A story privacy rules.
Parameters:
type (:obj:`~pyrogram.enums.StoriesPrivacyRules`):
Story privacy type.
"""
def __init__(
self, *,
type: "enums.StoriesPrivacyRules"
):
super().__init__()
self.type = type
def write(self):
if self.type == enums.StoriesPrivacyRules.PUBLIC:
return raw.types.InputPrivacyValueAllowAll().write()
if self.type == enums.StoriesPrivacyRules.CLOSE_FRIENDS:
return raw.types.InputPrivacyValueAllowCloseFriends().write()
if self.type == enums.StoriesPrivacyRules.CONTACTS:
return raw.types.InputPrivacyValueAllowContacts().write()
if self.type == enums.StoriesPrivacyRules.NO_CONTACTS:
return raw.types.InputPrivacyValueDisallowContacts().write()
if self.type == enums.StoriesPrivacyRules.PRIVATE:
return raw.types.InputPrivacyValueDisallowAll().write()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
# 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/>.
import pyrogram
from pyrogram import raw, types
from typing import Union
from ..object import Object
from ..update import Update
class StoryDeleted(Object, Update):
"""A deleted story.
Parameters:
id (``int``):
Unique story identifier.
from_user (:obj:`~pyrogram.types.User`, *optional*):
Sender of the story.
sender_chat (:obj:`~pyrogram.types.Chat`, *optional*):
Sender of the story. If the story is from channel.
"""
def __init__(
self,
*,
client: "pyrogram.Client" = None,
id: int,
from_user: Union["types.User", "types.Chat"] = None
):
super().__init__(client)
self.id = id
self.from_user = from_user
async def _parse(
client: "pyrogram.Client",
stories: raw.base.StoryItem,
peer: Union["raw.types.PeerChannel", "raw.types.PeerUser"]
) -> "StoryDeleted":
from_user = await client.get_users(peer.user_id) if isinstance(peer, raw.types.PeerUser) else await client.get_chat(peer.channel_id)
return StoryDeleted(
id=stories.id,
from_user=from_user,
client=client
)

View File

@ -0,0 +1,84 @@
# 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/>.
import pyrogram
from datetime import datetime
from pyrogram import raw, types, utils
from typing import Union
from ..object import Object
from ..update import Update
class StorySkipped(Object, Update):
"""A skipped story.
Parameters:
id (``int``):
Unique story identifier.
from_user (:obj:`~pyrogram.types.User`, *optional*):
Sender of the story.
sender_chat (:obj:`~pyrogram.types.Chat`, *optional*):
Sender of the story. If the story is from channel.
date (:py:obj:`~datetime.datetime`, *optional*):
Date the story was sent.
expire_date (:py:obj:`~datetime.datetime`, *optional*):
Date the story will be expired.
close_friends (``bool``, *optional*):
True, if the Story is shared with close_friends only.
"""
# TODO: Add Privacy
def __init__(
self,
*,
client: "pyrogram.Client" = None,
id: int,
from_user: Union["types.User", "types.Chat"] = None,
date: datetime,
expire_date: datetime,
close_friends: bool = None
):
super().__init__(client)
self.id = id
self.from_user = from_user
self.date = date
self.expire_date = expire_date
self.close_friends = close_friends
async def _parse(
client: "pyrogram.Client",
stories: raw.base.StoryItem,
peer: Union["raw.types.PeerChannel", "raw.types.PeerUser"]
) -> "StorySkipped":
from_user = await client.get_users(peer.user_id) if isinstance(peer, raw.types.PeerUser) else await client.get_chat(peer.channel_id)
return StorySkipped(
id=stories.id,
from_user=from_user,
date=utils.timestamp_to_datetime(stories.date),
expire_date=utils.timestamp_to_datetime(stories.expire_date),
close_friends=stories.close_friends,
client=client
)

View File

@ -0,0 +1,74 @@
# 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 pyrogram import raw, types
from typing import List
from ..object import Object
class StoryViews(Object):
"""Contains information about a story viewers.
Parameters:
views_count (``int`` ``32-bit``):
Views count.
has_viewers (``bool``, *optional*):
Has viewers.
forwards_count (``int`` ``32-bit``, *optional*):
Forwards count.
reactions (List of :obj:`~pyrogram.types.Reaction`, *optional*):
Reactions list.
reactions_count (``int`` ``32-bit``, *optional*):
Reactions count.
recent_viewers (List of ``int`` ``64-bit``, *optional*):
Viewers list.
"""
def __init__(
self, *,
views_count: int,
has_viewers: bool = None,
forwards_count: int = None,
reactions: List["types.Reaction"] = None,
reactions_count: int = None,
recent_viewers: List[int] = None
):
super().__init__()
self.views_count = views_count
self.has_viewers = has_viewers
self.forwards_count = forwards_count
self.reactions = reactions
self.reactions_count = reactions_count
self.recent_viewers = recent_viewers
@staticmethod
def _parse(client, storyviews: "raw.types.StoryViews") -> "StoryViews":
return StoryViews(
views_count=getattr(storyviews, "views_count", None),
has_viewers=getattr(storyviews, "has_viewers", None),
forwards_count=getattr(storyviews, "forwards_count", None),
reactions=[
types.Reaction._parse_count(client, reaction) for reaction in storyviews.reactions
] or None,
recent_viewers=getattr(storyviews, "recent_viewers", None)
)

View File

@ -248,16 +248,21 @@ def get_peer_type(peer_id: int) -> str:
raise ValueError(f"Peer id invalid: {peer_id}")
def get_reply_to(
reply_to_message_id: Optional[int],
message_thread_id: Optional[int],
) -> Optional[raw.types.InputReplyToMessage]:
if not any((reply_to_message_id, message_thread_id)):
return None
reply_to_message_id: Optional[int] = None,
message_thread_id: Optional[int] = None,
user_id: Optional[raw.types.InputUser] = None,
reply_to_story_id: Optional[int] = None
) -> Optional[Union[raw.types.InputReplyToMessage, raw.types.InputReplyToStory]]:
if all((user_id, reply_to_story_id)):
return raw.types.InputReplyToStory(user_id=user_id, story_id=reply_to_story_id) # type: ignore[arg-type]
return raw.types.InputReplyToMessage(
reply_to_msg_id=reply_to_message_id or message_thread_id, # type: ignore[arg-type]
top_msg_id=message_thread_id if reply_to_message_id else None,
)
if any((reply_to_message_id, message_thread_id)):
return raw.types.InputReplyToMessage(
reply_to_msg_id=reply_to_message_id or message_thread_id, # type: ignore[arg-type]
top_msg_id=message_thread_id if reply_to_message_id else None,
)
return None
def get_channel_id(peer_id: int) -> int:
return MAX_CHANNEL_ID - peer_id

View File

@ -0,0 +1,125 @@
# 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 io import BytesIO
from pyrogram.raw.core.primitives import Int, Long, Int128, Int256, Bool, Bytes, String, Double, Vector
from pyrogram.raw.core import TLObject
from pyrogram import raw
from typing import List, Optional, Any
# # # # # # # # # # # # # # # # # # # # # # # #
# !!! WARNING !!! #
# This is a generated file! #
# All changes made in this file will be lost! #
# # # # # # # # # # # # # # # # # # # # # # # #
class UpdateBotPrecheckoutQuery(TLObject): # type: ignore
"""Telegram API type.
Constructor of :obj:`~pyrogram.raw.base.Update`.
Details:
- Layer: ``165``
- ID: ``8CAA9A96``
Parameters:
query_id (``int`` ``64-bit``):
N/A
user_id (``int`` ``64-bit``):
N/A
payload (``bytes``):
N/A
currency (``str``):
N/A
total_amount (``int`` ``64-bit``):
N/A
info (:obj:`PaymentRequestedInfo <pyrogram.raw.base.PaymentRequestedInfo>`, *optional*):
N/A
shipping_option_id (``str``, *optional*):
N/A
"""
__slots__: List[str] = ["query_id", "user_id", "payload", "currency", "total_amount", "info", "shipping_option_id"]
ID = 0x8caa9a96
QUALNAME = "types.UpdateBotPrecheckoutQuery"
def __init__(self, *, query_id: int, user_id: int, payload: bytes, currency: str, total_amount: int, info: "raw.base.PaymentRequestedInfo" = None, shipping_option_id: Optional[str] = None) -> None:
self.query_id = query_id # long
self.user_id = user_id # long
self.payload = payload # bytes
self.currency = currency # string
self.total_amount = total_amount # long
self.info = info # flags.0?PaymentRequestedInfo
self.shipping_option_id = shipping_option_id # flags.1?string
@staticmethod
def read(b: BytesIO, *args: Any) -> "UpdateBotPrecheckoutQuery":
flags = Int.read(b)
query_id = Long.read(b)
user_id = Long.read(b)
payload = Bytes.read(b)
info = TLObject.read(b) if flags & (1 << 0) else None
shipping_option_id = String.read(b) if flags & (1 << 1) else None
currency = String.read(b)
total_amount = Long.read(b)
return UpdateBotPrecheckoutQuery(query_id=query_id, user_id=user_id, payload=payload, currency=currency, total_amount=total_amount, info=info, shipping_option_id=shipping_option_id)
def write(self, *args) -> bytes:
b = BytesIO()
b.write(Int(self.ID, False))
flags = 0
flags |= (1 << 0) if self.info is not None else 0
flags |= (1 << 1) if self.shipping_option_id is not None else 0
b.write(Int(flags))
b.write(Long(self.query_id))
b.write(Long(self.user_id))
b.write(Bytes(self.payload))
if self.info is not None:
b.write(self.info.write())
if self.shipping_option_id is not None:
b.write(String(self.shipping_option_id))
b.write(String(self.currency))
b.write(Long(self.total_amount))
return b.getvalue()