Update to telethon 1.8. Fixes #334
This commit is contained in:
@@ -309,7 +309,7 @@ class AbstractUser(ABC):
|
||||
if await puppet.update_displayname(self, update):
|
||||
puppet.save()
|
||||
elif isinstance(update, UpdateUserPhoto):
|
||||
if await puppet.update_avatar(self, update.photo.photo_big):
|
||||
if await puppet.update_avatar(self, update.photo):
|
||||
puppet.save()
|
||||
else:
|
||||
self.log.warning("Unexpected other user info update: %s", update)
|
||||
|
||||
+58
-28
@@ -47,13 +47,13 @@ from telethon.errors import (ChatAdminRequiredError, ChatNotModifiedError, Photo
|
||||
PhotoInvalidDimensionsError, PhotoSaveFileInvalidError)
|
||||
from telethon.tl.patched import Message, MessageService
|
||||
from telethon.tl.types import (
|
||||
Channel, ChatAdminRights, ChatBannedRights, ChannelFull, ChannelParticipantAdmin,
|
||||
Channel, ChatAdminRights, ChatBannedRights, ChannelFull, ChannelParticipantAdmin, Document,
|
||||
ChannelParticipantCreator, ChannelParticipantsRecent, ChannelParticipantsSearch, Chat,
|
||||
ChatFull, ChatInviteEmpty, ChatParticipantAdmin, ChatParticipantCreator, ChatPhoto, Poll,
|
||||
DocumentAttributeFilename, DocumentAttributeImageSize, DocumentAttributeSticker,
|
||||
DocumentAttributeVideo, FileLocation, GeoPoint, InputChannel, InputChatUploadedPhoto,
|
||||
DocumentAttributeFilename, DocumentAttributeImageSize, DocumentAttributeSticker, PhotoEmpty,
|
||||
DocumentAttributeVideo, GeoPoint, InputChannel, InputChatUploadedPhoto, InputPhotoFileLocation,
|
||||
InputPeerChannel, InputPeerChat, InputPeerUser, InputUser, InputUserSelf, MessageMediaPoll,
|
||||
MessageActionChannelCreate, MessageActionChatAddUser, MessageActionChatCreate,
|
||||
MessageActionChannelCreate, MessageActionChatAddUser, MessageActionChatCreate, ChatPhotoEmpty,
|
||||
MessageActionChatDeletePhoto, MessageActionChatDeleteUser, MessageActionChatEditPhoto,
|
||||
MessageActionChatEditTitle, MessageActionChatJoinedByLink, MessageActionChatMigrateTo,
|
||||
MessageActionPinMessage, MessageActionGameScore, MessageMediaContact, MessageMediaDocument,
|
||||
@@ -63,7 +63,7 @@ from telethon.tl.types import (
|
||||
TypeDocumentAttribute, TypeInputPeer, TypeMessageAction, TypeMessageEntity, TypePeer,
|
||||
TypePhotoSize, TypeUpdates, TypeUser, PhotoSize, TypeUserFull, UpdateChatUserTyping,
|
||||
UpdateNewChannelMessage, UpdateNewMessage, UpdateUserTyping, User, UserFull, MessageEntityPre,
|
||||
InputMediaUploadedDocument)
|
||||
InputMediaUploadedDocument, InputPeerPhotoFileLocation)
|
||||
from mautrix_appservice import MatrixRequestError, IntentError, AppService, IntentAPI
|
||||
|
||||
from .types import MatrixEventID, MatrixRoomID, MatrixUserID, TelegramID
|
||||
@@ -575,7 +575,7 @@ class Portal:
|
||||
changed = await self.update_title(entity.title) or changed
|
||||
|
||||
if isinstance(entity.photo, ChatPhoto):
|
||||
changed = await self.update_avatar(user, entity.photo.photo_big) or changed
|
||||
changed = await self.update_avatar(user, entity.photo) or changed
|
||||
|
||||
if changed:
|
||||
self.save()
|
||||
@@ -616,12 +616,21 @@ class Portal:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _get_largest_photo_size(photo: Union[Photo, List[TypePhotoSize]]
|
||||
) -> Optional[TypePhotoSize]:
|
||||
def _get_largest_photo_size(photo: Union[Photo, Document]
|
||||
) -> Tuple[Optional[InputPhotoFileLocation],
|
||||
Optional[TypePhotoSize]]:
|
||||
if not photo:
|
||||
return None
|
||||
return max(photo.sizes if isinstance(photo, Photo) else photo, key=(lambda photo2: (
|
||||
len(photo2.bytes) if not isinstance(photo2, PhotoSize) else photo2.size)))
|
||||
return None, None
|
||||
largest = max(photo.sizes if isinstance(photo, Photo) else photo.thumbs,
|
||||
key=(lambda photo2: (len(photo2.bytes)
|
||||
if not isinstance(photo2, PhotoSize)
|
||||
else photo2.size)))
|
||||
return InputPhotoFileLocation(
|
||||
id=photo.id,
|
||||
access_hash=photo.access_hash,
|
||||
file_reference=photo.file_reference,
|
||||
thumb_size=largest.type,
|
||||
), largest
|
||||
|
||||
async def remove_avatar(self, _: 'AbstractUser', save: bool = False) -> None:
|
||||
await self.main_intent.set_room_avatar(self.mxid, None)
|
||||
@@ -629,11 +638,33 @@ class Portal:
|
||||
if save:
|
||||
self.save()
|
||||
|
||||
async def update_avatar(self, user: 'AbstractUser', photo: FileLocation,
|
||||
async def update_avatar(self, user: 'AbstractUser',
|
||||
photo: Union[ChatPhoto, ChatPhotoEmpty, Photo, PhotoEmpty],
|
||||
save: bool = False) -> bool:
|
||||
photo_id = f"{photo.volume_id}-{photo.local_id}"
|
||||
if isinstance(photo, ChatPhoto):
|
||||
loc = InputPeerPhotoFileLocation(
|
||||
peer=await self.get_input_entity(user),
|
||||
local_id=photo.photo_big.local_id,
|
||||
volume_id=photo.photo_big.volume_id,
|
||||
big=True
|
||||
)
|
||||
photo_id = f"{loc.volume_id}-{loc.local_id}"
|
||||
elif isinstance(photo, Photo):
|
||||
loc, largest = self._get_largest_photo_size(photo)
|
||||
photo_id = f"{largest.location.volume_id}-{largest.location.local_id}"
|
||||
elif isinstance(photo, (ChatPhotoEmpty, PhotoEmpty)):
|
||||
photo_id = ""
|
||||
loc = None
|
||||
else:
|
||||
raise ValueError(f"Unknown photo type {type(photo)}")
|
||||
if self.photo_id != photo_id:
|
||||
file = await util.transfer_file_to_matrix(user.client, self.main_intent, photo)
|
||||
if not photo_id:
|
||||
await self.main_intent.set_room_avatar(self.mxid, "")
|
||||
self.photo_id = ""
|
||||
if save:
|
||||
self.save()
|
||||
return True
|
||||
file = await util.transfer_file_to_matrix(user.client, self.main_intent, loc)
|
||||
if file:
|
||||
await self.main_intent.set_room_avatar(self.mxid, file.mxc)
|
||||
self.photo_id = photo_id
|
||||
@@ -1212,8 +1243,8 @@ class Portal:
|
||||
and isinstance(update.message, MessageService)
|
||||
and isinstance(update.message.action, MessageActionChatEditPhoto))
|
||||
if is_photo_update:
|
||||
loc = self._get_largest_photo_size(update.message.action.photo).location
|
||||
self.photo_id = f"{loc.volume_id}-{loc.local_id}"
|
||||
loc, size = self._get_largest_photo_size(update.message.action.photo)
|
||||
self.photo_id = f"{size.location.volume_id}-{size.location.local_id}"
|
||||
self.save()
|
||||
break
|
||||
|
||||
@@ -1368,8 +1399,8 @@ class Portal:
|
||||
|
||||
async def handle_telegram_photo(self, source: 'AbstractUser', intent: IntentAPI, evt: Message,
|
||||
relates_to: Dict = None) -> Optional[Dict]:
|
||||
largest_size = self._get_largest_photo_size(evt.media.photo)
|
||||
file = await util.transfer_file_to_matrix(source.client, intent, largest_size.location)
|
||||
loc, largest_size = self._get_largest_photo_size(evt.media.photo)
|
||||
file = await util.transfer_file_to_matrix(source.client, intent, loc)
|
||||
if not file:
|
||||
return None
|
||||
if self.get_config("inline_images") and (evt.message
|
||||
@@ -1429,7 +1460,7 @@ class Portal:
|
||||
|
||||
@staticmethod
|
||||
def _parse_telegram_document_meta(evt: Message, file: DBTelegramFile, attrs: Dict,
|
||||
thumb: TypePhotoSize) -> Tuple[Dict, str]:
|
||||
thumb_size: TypePhotoSize) -> Tuple[Dict, str]:
|
||||
document = evt.media.document
|
||||
name = evt.message or attrs["name"]
|
||||
if attrs["is_sticker"]:
|
||||
@@ -1461,8 +1492,8 @@ class Portal:
|
||||
info["thumbnail_url"] = file.thumbnail.mxc
|
||||
info["thumbnail_info"] = {
|
||||
"mimetype": file.thumbnail.mime_type,
|
||||
"h": file.thumbnail.height or thumb.h,
|
||||
"w": file.thumbnail.width or thumb.w,
|
||||
"h": file.thumbnail.height or thumb_size.h,
|
||||
"w": file.thumbnail.width or thumb_size.w,
|
||||
"size": file.thumbnail.size,
|
||||
}
|
||||
|
||||
@@ -1473,16 +1504,16 @@ class Portal:
|
||||
document = evt.media.document
|
||||
attrs = self._parse_telegram_document_attributes(document.attributes)
|
||||
|
||||
thumb = self._get_largest_photo_size(document.thumbs)
|
||||
if thumb and not isinstance(thumb, (PhotoSize, PhotoCachedSize)):
|
||||
self.log.debug(f"Unsupported thumbnail type {type(thumb)}")
|
||||
thumb_loc, thumb_size = self._get_largest_photo_size(document)
|
||||
if thumb_size and not isinstance(thumb_size, (PhotoSize, PhotoCachedSize)):
|
||||
self.log.debug(f"Unsupported thumbnail type {type(thumb_size)}")
|
||||
thumb = None
|
||||
file = await util.transfer_file_to_matrix(source.client, intent, document, thumb,
|
||||
file = await util.transfer_file_to_matrix(source.client, intent, document, thumb_loc,
|
||||
is_sticker=attrs["is_sticker"])
|
||||
if not file:
|
||||
return None
|
||||
|
||||
info, name = self._parse_telegram_document_meta(evt, file, attrs, thumb)
|
||||
info, name = self._parse_telegram_document_meta(evt, file, attrs, thumb_size)
|
||||
|
||||
await intent.set_typing(self.mxid, is_typing=False)
|
||||
|
||||
@@ -1819,8 +1850,7 @@ class Portal:
|
||||
if isinstance(action, MessageActionChatEditTitle):
|
||||
await self.update_title(action.title, save=True)
|
||||
elif isinstance(action, MessageActionChatEditPhoto):
|
||||
largest_size = self._get_largest_photo_size(action.photo)
|
||||
await self.update_avatar(source, largest_size.location, save=True)
|
||||
await self.update_avatar(source, action.photo, save=True)
|
||||
elif isinstance(action, MessageActionChatDeletePhoto):
|
||||
await self.remove_avatar(source, save=True)
|
||||
elif isinstance(action, MessageActionChatAddUser):
|
||||
|
||||
@@ -22,7 +22,8 @@ import asyncio
|
||||
import logging
|
||||
import re
|
||||
|
||||
from telethon.tl.types import UserProfilePhoto, User, FileLocation, UpdateUserName, PeerUser
|
||||
from telethon.tl.types import (UserProfilePhoto, User, UpdateUserName, PeerUser, TypeInputPeer,
|
||||
InputPeerPhotoFileLocation, UserProfilePhotoEmpty)
|
||||
from mautrix_appservice import AppService, IntentAPI, IntentError, MatrixRequestError
|
||||
|
||||
from .types import MatrixUserID, TelegramID
|
||||
@@ -113,6 +114,9 @@ class Puppet:
|
||||
match = regex.match(self.displayname)
|
||||
return match.group(1) or self.displayname
|
||||
|
||||
def get_input_entity(self, user: 'AbstractUser') -> Awaitable[TypeInputPeer]:
|
||||
return user.client.get_input_entity(PeerUser(user_id=self.tgid))
|
||||
|
||||
# region Custom puppet management
|
||||
def _fresh_intent(self) -> IntentAPI:
|
||||
return (self.az.intent.user(self.custom_mxid, self.access_token)
|
||||
@@ -348,7 +352,7 @@ class Puppet:
|
||||
|
||||
changed = await self.update_displayname(source, info) or changed
|
||||
if isinstance(info.photo, UserProfilePhoto):
|
||||
changed = await self.update_avatar(source, info.photo.photo_big) or changed
|
||||
changed = await self.update_avatar(source, info.photo) or changed
|
||||
|
||||
self.is_bot = info.bot
|
||||
|
||||
@@ -384,13 +388,32 @@ class Puppet:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def update_avatar(self, source: 'AbstractUser', photo: FileLocation) -> bool:
|
||||
async def update_avatar(self, source: 'AbstractUser',
|
||||
photo: Union[UserProfilePhoto, UserProfilePhotoEmpty]) -> bool:
|
||||
if self.disable_updates:
|
||||
return False
|
||||
photo_id = f"{photo.volume_id}-{photo.local_id}"
|
||||
|
||||
if isinstance(photo, UserProfilePhotoEmpty):
|
||||
photo_id = ""
|
||||
else:
|
||||
photo_id = str(photo.photo_id)
|
||||
if self.photo_id != photo_id:
|
||||
file = await util.transfer_file_to_matrix(source.client, self.default_mxid_intent,
|
||||
photo)
|
||||
if not photo_id:
|
||||
self.photo_id = ""
|
||||
try:
|
||||
await self.default_mxid_intent.set_avatar("")
|
||||
except MatrixRequestError:
|
||||
self.log.exception("Failed to set avatar")
|
||||
self.photo_id = ""
|
||||
return True
|
||||
|
||||
loc = InputPeerPhotoFileLocation(
|
||||
peer=await self.get_input_entity(source),
|
||||
local_id=photo.photo_big.local_id,
|
||||
volume_id=photo.photo_big.volume_id,
|
||||
big=True
|
||||
)
|
||||
file = await util.transfer_file_to_matrix(source.client, self.default_mxid_intent, loc)
|
||||
if file:
|
||||
self.photo_id = photo_id
|
||||
try:
|
||||
|
||||
@@ -23,8 +23,9 @@ import asyncio
|
||||
import magic
|
||||
from sqlalchemy.exc import IntegrityError, InvalidRequestError
|
||||
|
||||
from telethon.tl.types import (Document, FileLocation, InputFileLocation, InputDocumentFileLocation,
|
||||
TypePhotoSize, PhotoSize, PhotoCachedSize)
|
||||
from telethon.tl.types import (Document, InputFileLocation, InputDocumentFileLocation,
|
||||
TypePhotoSize, PhotoSize, PhotoCachedSize, InputPhotoFileLocation,
|
||||
InputPeerPhotoFileLocation)
|
||||
from telethon.errors import (AuthBytesInvalidError, AuthKeyInvalidError, LocationInvalidError,
|
||||
SecurityError)
|
||||
from mautrix_appservice import IntentAPI
|
||||
@@ -47,7 +48,8 @@ except ImportError:
|
||||
|
||||
log = logging.getLogger("mau.util") # type: logging.Logger
|
||||
|
||||
TypeLocation = Union[Document, InputDocumentFileLocation, FileLocation, InputFileLocation]
|
||||
TypeLocation = Union[Document, InputDocumentFileLocation, InputPeerPhotoFileLocation,
|
||||
InputFileLocation, InputPhotoFileLocation]
|
||||
|
||||
|
||||
def convert_image(file: bytes, source_mime: str = "image/webp", target_type: str = "png",
|
||||
@@ -99,9 +101,9 @@ def _read_video_thumbnail(data: bytes, video_ext: str = "mp4", frame_ext: str =
|
||||
|
||||
|
||||
def _location_to_id(location: TypeLocation) -> str:
|
||||
if isinstance(location, (Document, InputDocumentFileLocation)):
|
||||
if isinstance(location, (Document, InputDocumentFileLocation, InputPhotoFileLocation)):
|
||||
return f"{location.id}-{location.access_hash}"
|
||||
elif isinstance(location, (FileLocation, InputFileLocation)):
|
||||
elif isinstance(location, (InputFileLocation, InputPeerPhotoFileLocation)):
|
||||
return f"{location.volume_id}-{location.local_id}"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user