diff --git a/Dockerfile b/Dockerfile index dfb1228a..1431b498 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ RUN apk add --no-cache \ ffmpeg \ ca-certificates \ su-exec \ - && pip3 install -r requirements.txt -r optional-requirements.txt + && pip3 install .[all] VOLUME /data diff --git a/mautrix_telegram/abstract_user.py b/mautrix_telegram/abstract_user.py index 1585b0c2..258dc19b 100644 --- a/mautrix_telegram/abstract_user.py +++ b/mautrix_telegram/abstract_user.py @@ -24,12 +24,11 @@ from sqlalchemy import orm from telethon.tl.patched import MessageService, Message from telethon.tl.types import ( Channel, ChannelForbidden, Chat, ChatForbidden, MessageActionChannelMigrateFrom, PeerUser, - TypeUpdate, UpdateChannelPinnedMessage, UpdateChatPinnedMessage, UpdateChatAdmins, - UpdateChatParticipantAdmin, UpdateChatParticipants, UpdateChatUserTyping, - UpdateDeleteChannelMessages, UpdateDeleteMessages, UpdateEditChannelMessage, UpdateEditMessage, - UpdateNewChannelMessage, UpdateNewMessage, UpdateReadHistoryOutbox, UpdateShortChatMessage, - UpdateShortMessage, UpdateUserName, UpdateUserPhoto, UpdateUserStatus, UpdateUserTyping, User, - UserStatusOffline, UserStatusOnline) + TypeUpdate, UpdateChannelPinnedMessage, UpdateChatPinnedMessage, UpdateChatParticipantAdmin, + UpdateChatParticipants, UpdateChatUserTyping, UpdateDeleteChannelMessages, UpdateDeleteMessages, + UpdateEditChannelMessage, UpdateEditMessage, UpdateNewChannelMessage, UpdateNewMessage, + UpdateReadHistoryOutbox, UpdateShortChatMessage, UpdateShortMessage, UpdateUserName, + UpdateUserPhoto, UpdateUserStatus, UpdateUserTyping, User, UserStatusOffline, UserStatusOnline) from mautrix_appservice import MatrixRequestError, AppService from alchemysession import AlchemySessionContainer @@ -202,7 +201,7 @@ class AbstractUser(ABC): await self.update_typing(update) elif isinstance(update, UpdateUserStatus): await self.update_status(update) - elif isinstance(update, (UpdateChatAdmins, UpdateChatParticipantAdmin)): + elif isinstance(update, UpdateChatParticipantAdmin): await self.update_admin(update) elif isinstance(update, UpdateChatParticipants): await self.update_participants(update) @@ -247,19 +246,13 @@ class AbstractUser(ABC): puppet = pu.Puppet.get(TelegramID(update.peer.user_id)) await puppet.intent.mark_read(portal.mxid, message.mxid) - async def update_admin(self, - update: Union[UpdateChatAdmins, UpdateChatParticipantAdmin]) -> None: + async def update_admin(self, update: UpdateChatParticipantAdmin) -> None: # TODO duplication not checked portal = po.Portal.get_by_tgid(TelegramID(update.chat_id), peer_type="chat") if not portal or not portal.mxid: return - if isinstance(update, UpdateChatAdmins): - await portal.set_telegram_admins_enabled(update.enabled) - elif isinstance(update, UpdateChatParticipantAdmin): - await portal.set_telegram_admin(TelegramID(update.user_id)) - else: - self.log.warning("Unexpected admin status update: %s", update) + await portal.set_telegram_admin(TelegramID(update.user_id)) async def update_typing(self, update: Union[UpdateUserTyping, UpdateChatUserTyping]) -> None: if isinstance(update, UpdateUserTyping): diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 83fb6137..c2bf813f 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -37,17 +37,17 @@ from sqlalchemy.exc import IntegrityError from telethon.tl.functions.messages import ( AddChatUserRequest, CreateChatRequest, DeleteChatUserRequest, EditChatAdminRequest, EditChatPhotoRequest, EditChatTitleRequest, ExportChatInviteRequest, GetFullChatRequest, - UpdatePinnedMessageRequest, MigrateChatRequest, SetTypingRequest) + UpdatePinnedMessageRequest, MigrateChatRequest, SetTypingRequest, EditChatAboutRequest) from telethon.tl.functions.channels import ( - CreateChannelRequest, EditAboutRequest, EditAdminRequest, EditBannedRequest, EditPhotoRequest, - EditTitleRequest, ExportInviteRequest, GetParticipantsRequest, InviteToChannelRequest, + CreateChannelRequest, EditAdminRequest, EditBannedRequest, EditPhotoRequest, + EditTitleRequest, GetParticipantsRequest, InviteToChannelRequest, JoinChannelRequest, LeaveChannelRequest, UpdateUsernameRequest) from telethon.tl.functions.messages import ReadHistoryRequest as ReadMessageHistoryRequest from telethon.tl.functions.channels import ReadHistoryRequest as ReadChannelHistoryRequest from telethon.errors import ChatAdminRequiredError, ChatNotModifiedError from telethon.tl.patched import Message, MessageService from telethon.tl.types import ( - Channel, ChannelAdminRights, ChannelBannedRights, ChannelFull, ChannelParticipantAdmin, + Channel, ChatAdminRights, ChatBannedRights, ChannelFull, ChannelParticipantAdmin, ChannelParticipantCreator, ChannelParticipantsRecent, ChannelParticipantsSearch, Chat, ChatFull, ChatInviteEmpty, ChatParticipantAdmin, ChatParticipantCreator, ChatPhoto, DocumentAttributeFilename, DocumentAttributeImageSize, DocumentAttributeSticker, @@ -60,7 +60,7 @@ from telethon.tl.types import ( MessageMediaGeo, MessageMediaPhoto, MessageMediaUnsupported, MessageMediaGame, PeerChannel, PeerChat, PeerUser, Photo, PhotoCachedSize, SendMessageCancelAction, SendMessageTypingAction, TypeChannelParticipant, TypeChat, TypeChatParticipant, TypeDocumentAttribute, TypeInputPeer, - TypeMessageAction, TypeMessageEntity, TypePeer, TypePhotoSize, TypeUpdates, TypeUser, + TypeMessageAction, TypeMessageEntity, TypePeer, TypePhotoSize, TypeUpdates, TypeUser, PhotoSize, TypeUserFull, UpdateChatUserTyping, UpdateNewChannelMessage, UpdateNewMessage, UpdateUserTyping, User, UserFull, MessageEntityPre) from mautrix_appservice import MatrixRequestError, IntentError, AppService, IntentAPI @@ -595,7 +595,7 @@ class Portal: @staticmethod def _get_largest_photo_size(photo: Photo) -> TypePhotoSize: return max(photo.sizes, key=(lambda photo2: ( - len(photo2.bytes) if isinstance(photo2, PhotoCachedSize) else photo2.size))) + len(photo2.bytes) if not isinstance(photo2, PhotoSize) else photo2.size))) async def remove_avatar(self, _: 'AbstractUser', save: bool = False) -> None: await self.main_intent.set_room_avatar(self.mxid, None) @@ -663,19 +663,11 @@ class Portal: async def get_invite_link(self, user: 'u.User') -> str: if self.peer_type == "user": raise ValueError("You can't invite users to private chats.") - elif self.peer_type == "chat": - link = await user.client(ExportChatInviteRequest(chat_id=self.tgid)) - elif self.peer_type == "channel": - if self.username: - return f"https://t.me/{self.username}" - link = await user.client( - ExportInviteRequest(channel=await self.get_input_entity(user))) - else: - raise ValueError(f"Invalid peer type '{self.peer_type}' for invite link.") - + if self.username: + return f"https://t.me/{self.username}" + link = await user.client(ExportChatInviteRequest(peer=await self.get_input_entity(user))) if isinstance(link, ChatInviteEmpty): raise ValueError("Failed to get invite link.") - return link.link async def get_authenticated_matrix_users(self) -> List['u.User']: @@ -825,7 +817,7 @@ class Portal: await source.client(DeleteChatUserRequest(chat_id=self.tgid, user_id=user.tgid)) elif self.peer_type == "channel": channel = await self.get_input_entity(source) - rights = ChannelBannedRights(datetime.fromtimestamp(0), True) + rights = ChatBannedRights(datetime.fromtimestamp(0), True) await source.client(EditBannedRequest(channel=channel, user_id=user.tgid, banned_rights=rights)) @@ -1079,11 +1071,10 @@ class Portal: elif self.peer_type == "channel": moderator = level >= 50 admin = level >= 75 - rights = ChannelAdminRights(change_info=moderator, post_messages=moderator, - edit_messages=moderator, delete_messages=moderator, - ban_users=moderator, invite_users=moderator, - invite_link=moderator, pin_messages=moderator, - add_admins=admin) + rights = ChatAdminRights(change_info=moderator, post_messages=moderator, + edit_messages=moderator, delete_messages=moderator, + ban_users=moderator, invite_users=moderator, + pin_messages=moderator, add_admins=admin) await sender.client( EditAdminRequest(channel=await self.get_input_entity(sender), user_id=user_id, admin_rights=rights)) @@ -1107,15 +1098,15 @@ class Portal: await self._update_telegram_power_level(sender, user_id, level) async def handle_matrix_about(self, sender: 'u.User', about: str) -> None: - if self.peer_type not in {"channel"}: + if self.peer_type not in ("chat", "channel"): return - channel = await self.get_input_entity(sender) - await sender.client(EditAboutRequest(channel=channel, about=about)) + peer = await self.get_input_entity(sender) + await sender.client(EditChatAboutRequest(peer=peer, about=about)) self.about = about self.save() async def handle_matrix_title(self, sender: 'u.User', title: str) -> None: - if self.peer_type not in {"chat", "channel"}: + if self.peer_type not in ("chat", "channel"): return if self.peer_type == "chat": @@ -1128,7 +1119,7 @@ class Portal: self.save() async def handle_matrix_avatar(self, sender: 'u.User', url: str) -> None: - if self.peer_type not in {"chat", "channel"}: + if self.peer_type not in ("chat", "channel"): # Invalid peer type return diff --git a/optional-requirements.txt b/optional-requirements.txt index a4400877..573c87c1 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -2,3 +2,5 @@ lxml cryptg Pillow moviepy +# TODO remove when moviepy is fixed +imageio==2.4.1 diff --git a/requirements.txt b/requirements.txt index 721e74d4..e9e5ccc2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,5 +6,5 @@ SQLAlchemy alembic commonmark future-fstrings -telethon>=1.5,<1.5.4 +telethon telethon-session-sqlalchemy diff --git a/setup.py b/setup.py index b6a1f000..d500945f 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ extras = { "better_formatter": ["lxml>=4.1.1,<5"], "fast_crypto": ["cryptg>=0.1,<0.2"], "webp_convert": ["Pillow>=5.0.0,<6"], - "hq_thumbnails": ["moviepy>=0.2,<0.3"], + "hq_thumbnails": ["moviepy>=0.2,<0.3", "imageio==2.4.1"], } extras["all"] = list(set(deps[0] for deps in extras.values())) @@ -34,8 +34,8 @@ setuptools.setup( "ruamel.yaml>=0.15.35,<0.16", "future-fstrings>=0.4.2", "python-magic>=0.4.15,<0.5", - "telethon>=1.5,<1.5.4", - "telethon-session-sqlalchemy>=0.2.3,<0.3", + "telethon>=1.5.5,<1.6", + "telethon-session-sqlalchemy>=0.2.6,<0.3", ], extras_require=extras,