2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-29 13:27:47 +00:00

Refactor Message and MessageEntity

This commit is contained in:
Dan 2018-12-15 21:40:44 +01:00
parent 334fb8d0ba
commit 5ecbfbf25f
2 changed files with 310 additions and 25 deletions

View File

@ -16,13 +16,17 @@
# 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.api import types
import pyrogram
from pyrogram.api import types, functions
from pyrogram.api.core import Object
from pyrogram.api.errors import MessageIdsEmpty
from ..bots import InlineKeyboardMarkup, ReplyKeyboardMarkup
from pyrogram.api.errors import MessageIdsEmpty, StickersetInvalid
from .contact import Contact
from .location import Location
from .message_entity import MessageEntity
from ..messages_and_media.photo import Photo
from ..user_and_chats.chat import Chat
from ..user_and_chats.user import User
from ...ext.utils import Str
class Message(Object):
@ -222,18 +226,19 @@ class Message(Object):
# TODO: Add game missing field. Also invoice, successful_payment, connected_website
ID = 0xb0700003
def __init__(self, message_id: int, date: int = None, chat=None, from_user=None, forward_from=None,
forward_from_chat=None, forward_from_message_id: int = None, forward_signature: str = None,
forward_date: int = None, reply_to_message=None, mentioned=None, empty=None, service=None, media=None,
edit_date: int = None, media_group_id: str = None, author_signature: str = None, text: str = None,
entities: list = None, caption_entities: list = None, audio=None, document=None, photo=None,
sticker=None, animation=None, video=None, voice=None, video_note=None, caption: str = None,
contact=None, location=None, venue=None, web_page=None, new_chat_members: list = None,
left_chat_member=None, new_chat_title: str = None, new_chat_photo=None, delete_chat_photo: bool = None,
group_chat_created: bool = None, supergroup_chat_created: bool = None,
channel_chat_created: bool = None, migrate_to_chat_id: int = None, migrate_from_chat_id: int = None,
pinned_message=None, views: int = None, via_bot=None, outgoing: bool = None, matches: list = None,
command: list = None, reply_markup=None,
def __init__(self, message_id: int, *,
date: int = None, chat=None, from_user=None, forward_from=None, forward_from_chat=None,
forward_from_message_id: int = None, forward_signature: str = None, forward_date: int = None,
reply_to_message=None, mentioned=None, empty=None, service=None, media=None, edit_date: int = None,
media_group_id: str = None, author_signature: str = None, text: str = None, entities: list = None,
caption_entities: list = None, audio=None, document=None, photo=None, sticker=None, animation=None,
video=None, voice=None, video_note=None, caption: str = None, contact=None, location=None, venue=None,
web_page=None, new_chat_members: list = None, left_chat_member=None, new_chat_title: str = None,
new_chat_photo=None, delete_chat_photo: bool = None, group_chat_created: bool = None,
supergroup_chat_created: bool = None, channel_chat_created: bool = None,
migrate_to_chat_id: int = None, migrate_from_chat_id: int = None, pinned_message=None,
views: int = None, via_bot=None, outgoing: bool = None, matches: list = None, command: list = None,
reply_markup=None,
client=None, raw=None):
self.message_id = message_id
self.date = date
@ -286,6 +291,255 @@ class Message(Object):
self.command = command
self.reply_markup = reply_markup
self._client = client
self._raw = raw
@staticmethod
def parse(client, message: types.Message or types.MessageService or types.MessageEmpty, users: dict, chats: dict,
replies: int = 1):
if isinstance(message, types.MessageEmpty):
return Message(
message_id=message.id,
client=client,
raw=message
)
if isinstance(message, types.MessageService):
action = message.action
new_chat_members = None
left_chat_member = None
new_chat_title = None
delete_chat_photo = None
migrate_to_chat_id = None
migrate_from_chat_id = None
group_chat_created = None
channel_chat_created = None
new_chat_photo = None
if isinstance(action, types.MessageActionChatAddUser):
new_chat_members = [User.parse(client, users[i]) for i in action.users]
elif isinstance(action, types.MessageActionChatJoinedByLink):
new_chat_members = [User.parse(client, users[message.from_id])]
elif isinstance(action, types.MessageActionChatDeleteUser):
left_chat_member = User.parse(client, users[action.user_id])
elif isinstance(action, types.MessageActionChatEditTitle):
new_chat_title = action.title
elif isinstance(action, types.MessageActionChatDeletePhoto):
delete_chat_photo = True
elif isinstance(action, types.MessageActionChatMigrateTo):
migrate_to_chat_id = action.channel_id
elif isinstance(action, types.MessageActionChannelMigrateFrom):
migrate_from_chat_id = action.chat_id
elif isinstance(action, types.MessageActionChatCreate):
group_chat_created = True
elif isinstance(action, types.MessageActionChannelCreate):
channel_chat_created = True
elif isinstance(action, types.MessageActionChatEditPhoto):
new_chat_photo = Photo.parse(client, action.photo)
parsed_message = Message(
message_id=message.id,
date=message.date,
chat=Chat.parse(client, message, users, chats),
from_user=User.parse(client, users.get(message.from_id, None)),
service=True,
new_chat_members=new_chat_members,
left_chat_member=left_chat_member,
new_chat_title=new_chat_title,
new_chat_photo=new_chat_photo,
delete_chat_photo=delete_chat_photo,
migrate_to_chat_id=int("-100" + str(migrate_to_chat_id)) if migrate_to_chat_id else None,
migrate_from_chat_id=-migrate_from_chat_id if migrate_from_chat_id else None,
group_chat_created=group_chat_created,
channel_chat_created=channel_chat_created,
client=client,
raw=message
# TODO: supergroup_chat_created
)
if isinstance(action, types.MessageActionPinMessage):
try:
parsed_message.pinned_message = client.get_messages(
parsed_message.chat.id,
reply_to_message_ids=message.id,
replies=0
)
except MessageIdsEmpty:
pass
return parsed_message
if isinstance(message, types.Message):
entities = [MessageEntity.parse(client, entity, users) for entity in message.entities]
entities = list(filter(lambda x: x is not None, entities))
forward_from = None
forward_from_chat = None
forward_from_message_id = None
forward_signature = None
forward_date = None
forward_header = message.fwd_from
if forward_header:
forward_date = forward_header.date
if forward_header.from_id:
forward_from = User.parse(client, users[forward_header.from_id])
else:
forward_from_chat = Chat.parse_channel_chat(client, chats[forward_header.channel_id])
forward_from_message_id = forward_header.channel_post
forward_signature = forward_header.post_author
photo = None
location = None
contact = None
venue = None
audio = None
voice = None
animation = None
video = None
video_note = None
sticker = None
document = None
web_page = None
media = message.media
if media:
if isinstance(media, types.MessageMediaPhoto):
photo = Photo.parse(client, media.photo)
elif isinstance(media, types.MessageMediaGeo):
location = Location.parse(client, media.geo)
elif isinstance(media, types.MessageMediaContact):
contact = Contact.parse(client, media)
elif isinstance(media, types.MessageMediaVenue):
venue = pyrogram.Venue.parse(client, media)
elif isinstance(media, types.MessageMediaDocument):
doc = media.document
if isinstance(doc, types.Document):
attributes = {type(i): i for i in doc.attributes}
file_name = getattr(
attributes.get(
types.DocumentAttributeFilename, None
), "file_name", None
)
if types.DocumentAttributeAudio in attributes:
audio_attributes = attributes[types.DocumentAttributeAudio]
if audio_attributes.voice:
voice = pyrogram.Voice.parse(client, doc, audio_attributes)
else:
audio = pyrogram.Audio.parse(client, doc, audio_attributes, file_name)
elif types.DocumentAttributeAnimated in attributes:
video_attributes = attributes.get(types.DocumentAttributeVideo, None)
animation = pyrogram.Animation.parse(client, doc, video_attributes, file_name)
elif types.DocumentAttributeVideo in attributes:
video_attributes = attributes[types.DocumentAttributeVideo]
if video_attributes.round_message:
video_note = pyrogram.VideoNote.parse(client, doc, video_attributes)
else:
video = pyrogram.Video.parse(client, doc, video_attributes, file_name)
elif types.DocumentAttributeSticker in attributes:
image_size_attributes = attributes.get(types.DocumentAttributeImageSize, None)
sticker_attribute = attributes[types.DocumentAttributeSticker]
if isinstance(sticker_attribute.stickerset, types.InputStickerSetID):
try:
set_name = client.send(
functions.messages.GetStickerSet(sticker_attribute.stickerset)
).set.short_name
except StickersetInvalid:
set_name = None
else:
set_name = None
sticker = pyrogram.Sticker.parse(client, doc, image_size_attributes,
set_name, sticker_attribute, file_name)
else:
document = pyrogram.Document.parse(client, doc, file_name)
elif isinstance(media, types.MessageMediaWebPage):
web_page = True
else:
media = None
reply_markup = message.reply_markup
if reply_markup:
if isinstance(reply_markup, types.ReplyKeyboardForceReply):
reply_markup = pyrogram.ForceReply.read(reply_markup)
elif isinstance(reply_markup, types.ReplyKeyboardMarkup):
reply_markup = pyrogram.ReplyKeyboardMarkup.read(reply_markup)
elif isinstance(reply_markup, types.ReplyInlineMarkup):
reply_markup = pyrogram.InlineKeyboardMarkup.read(reply_markup)
elif isinstance(reply_markup, types.ReplyKeyboardHide):
reply_markup = pyrogram.ReplyKeyboardRemove.read(reply_markup)
else:
reply_markup = None
parsed_message = Message(
message_id=message.id,
date=message.date,
chat=Chat.parse(client, message, users, chats),
from_user=User.parse(client, users.get(message.from_id, None)),
text=Str(message.message) or None if media is None else None,
caption=Str(message.message) or None if media is not None else None,
entities=entities or None if media is None else None,
caption_entities=entities or None if media is not None else None,
author_signature=message.post_author,
forward_from=forward_from,
forward_from_chat=forward_from_chat,
forward_from_message_id=forward_from_message_id,
forward_signature=forward_signature,
forward_date=forward_date,
mentioned=message.mentioned,
media=bool(media) or None,
edit_date=message.edit_date,
media_group_id=message.grouped_id,
photo=photo,
location=location,
contact=contact,
venue=venue,
audio=audio,
voice=voice,
animation=animation,
video=video,
video_note=video_note,
sticker=sticker,
document=document,
web_page=web_page,
views=message.views,
via_bot=User.parse(client, users.get(message.via_bot_id, None)),
outgoing=message.out,
reply_markup=reply_markup,
client=client,
raw=message
)
if parsed_message.text:
parsed_message.text.init(parsed_message._client, parsed_message.entities or [])
if parsed_message.caption:
parsed_message.caption.init(parsed_message._client, parsed_message.caption_entities or [])
if message.reply_to_msg_id and replies:
try:
parsed_message.reply_to_message = client.get_messages(
parsed_message.chat.id,
reply_to_message_ids=message.id,
replies=replies - 1
)
except MessageIdsEmpty:
pass
return parsed_message
def reply(self,
text: str,
quote: bool = None,
@ -549,9 +803,9 @@ class Message(Object):
``ValueError``: If the provided index or position is out of range or the button label was not found
``TimeoutError``: If, after clicking an inline button, the bot fails to answer within 10 seconds
"""
if isinstance(self.reply_markup, ReplyKeyboardMarkup):
if isinstance(self.reply_markup, pyrogram.ReplyKeyboardMarkup):
return self.reply(x)
elif isinstance(self.reply_markup, InlineKeyboardMarkup):
elif isinstance(self.reply_markup, pyrogram.InlineKeyboardMarkup):
if isinstance(x, int) and y is None:
try:
button = [

View File

@ -16,7 +16,9 @@
# 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.api import types
from pyrogram.api.core import Object
from ..user_and_chats.user import User
class MessageEntity(Object):
@ -45,16 +47,45 @@ class MessageEntity(Object):
ID = 0xb0700004
def __init__(
self,
type: str,
offset: int,
length: int,
url: str = None,
user=None
):
ENTITIES = {
types.MessageEntityMention.ID: "mention",
types.MessageEntityHashtag.ID: "hashtag",
types.MessageEntityCashtag.ID: "cashtag",
types.MessageEntityBotCommand.ID: "bot_command",
types.MessageEntityUrl.ID: "url",
types.MessageEntityEmail.ID: "email",
types.MessageEntityBold.ID: "bold",
types.MessageEntityItalic.ID: "italic",
types.MessageEntityCode.ID: "code",
types.MessageEntityPre.ID: "pre",
types.MessageEntityTextUrl.ID: "text_link",
types.MessageEntityMentionName.ID: "text_mention",
types.MessageEntityPhone.ID: "phone_number"
}
def __init__(self, type: str, offset: int, length: int, *,
url: str = None, user=None,
client=None, raw=None):
self.type = type
self.offset = offset
self.length = length
self.url = url
self.user = user
self._client = client
self._raw = raw
@staticmethod
def parse(client, entity, users: dict) -> "MessageEntity" or None:
type = MessageEntity.ENTITIES.get(entity.ID, None)
if type is None:
return None
return MessageEntity(
type=type,
offset=entity.offset,
length=entity.length,
url=getattr(entity, "url", None),
user=User.parse(client, users.get(getattr(entity, "user_id", None), None))
)