Merge branch 'telethon-1.18'
This commit is contained in:
@@ -25,8 +25,8 @@ from telethon.network import (ConnectionTcpMTProxyRandomizedIntermediate, Connec
|
|||||||
Connection)
|
Connection)
|
||||||
from telethon.tl.patched import MessageService, Message
|
from telethon.tl.patched import MessageService, Message
|
||||||
from telethon.tl.types import (
|
from telethon.tl.types import (
|
||||||
Channel, Chat, MessageActionChannelMigrateFrom, PeerUser, TypeUpdate, UpdateChatPinnedMessage,
|
Channel, Chat, MessageActionChannelMigrateFrom, PeerUser, TypeUpdate, UpdatePinnedMessages,
|
||||||
UpdateChannelPinnedMessage, UpdateChatParticipantAdmin, UpdateChatParticipants, PeerChat,
|
UpdatePinnedChannelMessages, UpdateChatParticipantAdmin, UpdateChatParticipants, PeerChat,
|
||||||
UpdateChatUserTyping, UpdateDeleteChannelMessages, UpdateNewMessage, UpdateDeleteMessages,
|
UpdateChatUserTyping, UpdateDeleteChannelMessages, UpdateNewMessage, UpdateDeleteMessages,
|
||||||
UpdateEditChannelMessage, UpdateEditMessage, UpdateNewChannelMessage, UpdateReadHistoryOutbox,
|
UpdateEditChannelMessage, UpdateEditMessage, UpdateNewChannelMessage, UpdateReadHistoryOutbox,
|
||||||
UpdateShortChatMessage, UpdateShortMessage, UpdateUserName, UpdateUserPhoto, UpdateUserStatus,
|
UpdateShortChatMessage, UpdateShortMessage, UpdateUserName, UpdateUserPhoto, UpdateUserStatus,
|
||||||
@@ -252,7 +252,7 @@ class AbstractUser(ABC):
|
|||||||
await self.update_admin(update)
|
await self.update_admin(update)
|
||||||
elif isinstance(update, UpdateChatParticipants):
|
elif isinstance(update, UpdateChatParticipants):
|
||||||
await self.update_participants(update)
|
await self.update_participants(update)
|
||||||
elif isinstance(update, (UpdateChannelPinnedMessage, UpdateChatPinnedMessage)):
|
elif isinstance(update, (UpdatePinnedMessages, UpdatePinnedChannelMessages)):
|
||||||
await self.update_pinned_messages(update)
|
await self.update_pinned_messages(update)
|
||||||
elif isinstance(update, (UpdateUserName, UpdateUserPhoto)):
|
elif isinstance(update, (UpdateUserName, UpdateUserPhoto)):
|
||||||
await self.update_others_info(update)
|
await self.update_others_info(update)
|
||||||
@@ -263,14 +263,15 @@ class AbstractUser(ABC):
|
|||||||
else:
|
else:
|
||||||
self.log.trace("Unhandled update: %s", update)
|
self.log.trace("Unhandled update: %s", update)
|
||||||
|
|
||||||
async def update_pinned_messages(self, update: Union[UpdateChannelPinnedMessage,
|
async def update_pinned_messages(self, update: Union[UpdatePinnedMessages,
|
||||||
UpdateChatPinnedMessage]) -> None:
|
UpdatePinnedChannelMessages]) -> None:
|
||||||
if isinstance(update, UpdateChatPinnedMessage):
|
if isinstance(update, UpdatePinnedMessages):
|
||||||
portal = po.Portal.get_by_tgid(TelegramID(update.chat_id))
|
portal = po.Portal.get_by_entity(update.peer, receiver_id=self.tgid)
|
||||||
else:
|
else:
|
||||||
portal = po.Portal.get_by_tgid(TelegramID(update.channel_id))
|
portal = po.Portal.get_by_tgid(TelegramID(update.channel_id))
|
||||||
if portal and portal.mxid:
|
if portal and portal.mxid:
|
||||||
await portal.receive_telegram_pin_id(update.id, self.tgid)
|
await portal.receive_telegram_pin_ids(update.messages, self.tgid,
|
||||||
|
remove=not update.pinned)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def update_participants(update: UpdateChatParticipants) -> None:
|
async def update_participants(update: UpdateChatParticipants) -> None:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
from typing import Optional, Iterator
|
from typing import Optional, Iterator, List
|
||||||
|
|
||||||
from sqlalchemy import Column, UniqueConstraint, Integer, String, and_, func, desc, select
|
from sqlalchemy import Column, UniqueConstraint, Integer, String, and_, func, desc, select
|
||||||
|
|
||||||
@@ -51,6 +51,12 @@ class Message(Base):
|
|||||||
return cls._select_one_or_none(cls.c.tgid == tgid, cls.c.tg_space == tg_space,
|
return cls._select_one_or_none(cls.c.tgid == tgid, cls.c.tg_space == tg_space,
|
||||||
cls.c.edit_index == edit_index)
|
cls.c.edit_index == edit_index)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_first_by_tgids(cls, tgids: List[TelegramID], tg_space: TelegramID
|
||||||
|
) -> Iterator['Message']:
|
||||||
|
return cls._select_all(cls.c.tgid.in_(tgids), cls.c.tg_space == tg_space,
|
||||||
|
cls.c.edit_index == 0)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def count_spaces_by_mxid(cls, mxid: EventID, mx_room: RoomID) -> int:
|
def count_spaces_by_mxid(cls, mxid: EventID, mx_room: RoomID) -> int:
|
||||||
rows = cls.db.execute(select([func.count(cls.c.tg_space)])
|
rows = cls.db.execute(select([func.count(cls.c.tg_space)])
|
||||||
@@ -77,6 +83,12 @@ class Message(Base):
|
|||||||
return cls._select_one_or_none(cls.c.mxid == mxid, cls.c.mx_room == mx_room,
|
return cls._select_one_or_none(cls.c.mxid == mxid, cls.c.mx_room == mx_room,
|
||||||
cls.c.tg_space == tg_space)
|
cls.c.tg_space == tg_space)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_by_mxids(cls, mxids: List[EventID], mx_room: RoomID, tg_space: TelegramID
|
||||||
|
) -> Iterator['Message']:
|
||||||
|
return cls._select_all(cls.c.mxid.in_(mxids), cls.c.mx_room == mx_room,
|
||||||
|
cls.c.tg_space == tg_space)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_by_tgid(cls, s_tgid: TelegramID, s_tg_space: TelegramID, s_edit_index: int,
|
def update_by_tgid(cls, s_tgid: TelegramID, s_tg_space: TelegramID, s_edit_index: int,
|
||||||
**values) -> None:
|
**values) -> None:
|
||||||
|
|||||||
@@ -281,13 +281,12 @@ class MatrixHandler(BaseMatrixHandler):
|
|||||||
portal = po.Portal.get_by_mxid(room_id)
|
portal = po.Portal.get_by_mxid(room_id)
|
||||||
sender = await u.User.get_by_mxid(sender_mxid).ensure_started()
|
sender = await u.User.get_by_mxid(sender_mxid).ensure_started()
|
||||||
if await sender.has_full_access(allow_bot=True) and portal:
|
if await sender.has_full_access(allow_bot=True) and portal:
|
||||||
events = new_events - old_events
|
if not new_events:
|
||||||
if len(events) > 0:
|
await portal.handle_matrix_unpin_all(sender)
|
||||||
# New event pinned, set that as pinned in Telegram.
|
else:
|
||||||
await portal.handle_matrix_pin(sender, EventID(events.pop()), event_id)
|
changes = {event_id: event_id in new_events
|
||||||
elif len(new_events) == 0:
|
for event_id in new_events ^ old_events}
|
||||||
# All pinned events removed, remove pinned event in Telegram.
|
await portal.handle_matrix_pin(sender, changes, event_id)
|
||||||
await portal.handle_matrix_pin(sender, None, event_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def handle_room_upgrade(room_id: RoomID, sender: UserID, new_room_id: RoomID,
|
async def handle_room_upgrade(room_id: RoomID, sender: UserID, new_room_id: RoomID,
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class BasePortal(MautrixBasePortal, ABC):
|
|||||||
|
|
||||||
dedup: PortalDedup
|
dedup: PortalDedup
|
||||||
send_lock: PortalSendLock
|
send_lock: PortalSendLock
|
||||||
|
_pin_lock: asyncio.Lock
|
||||||
|
|
||||||
_db_instance: DBPortal
|
_db_instance: DBPortal
|
||||||
_main_intent: Optional[IntentAPI]
|
_main_intent: Optional[IntentAPI]
|
||||||
@@ -138,6 +139,7 @@ class BasePortal(MautrixBasePortal, ABC):
|
|||||||
|
|
||||||
self.dedup = PortalDedup(self)
|
self.dedup = PortalDedup(self)
|
||||||
self.send_lock = PortalSendLock()
|
self.send_lock = PortalSendLock()
|
||||||
|
self._pin_lock = asyncio.Lock()
|
||||||
|
|
||||||
if tgid:
|
if tgid:
|
||||||
self.by_tgid[self.tgid_full] = self
|
self.by_tgid[self.tgid_full] = self
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ import magic
|
|||||||
|
|
||||||
from telethon.tl.functions.messages import (EditChatPhotoRequest, EditChatTitleRequest,
|
from telethon.tl.functions.messages import (EditChatPhotoRequest, EditChatTitleRequest,
|
||||||
UpdatePinnedMessageRequest, SetTypingRequest,
|
UpdatePinnedMessageRequest, SetTypingRequest,
|
||||||
EditChatAboutRequest)
|
EditChatAboutRequest, UnpinAllMessagesRequest)
|
||||||
from telethon.tl.functions.channels import EditPhotoRequest, EditTitleRequest, JoinChannelRequest
|
from telethon.tl.functions.channels import EditPhotoRequest, EditTitleRequest, JoinChannelRequest
|
||||||
from telethon.errors import (ChatNotModifiedError, PhotoExtInvalidError,
|
from telethon.errors import (ChatNotModifiedError, PhotoExtInvalidError, MessageIdInvalidError,
|
||||||
PhotoInvalidDimensionsError, PhotoSaveFileInvalidError,
|
PhotoInvalidDimensionsError, PhotoSaveFileInvalidError, RPCError)
|
||||||
RPCError)
|
|
||||||
from telethon.tl.patched import Message, MessageService
|
from telethon.tl.patched import Message, MessageService
|
||||||
from telethon.tl.types import (DocumentAttributeFilename, DocumentAttributeImageSize, GeoPoint,
|
from telethon.tl.types import (DocumentAttributeFilename, DocumentAttributeImageSize, GeoPoint,
|
||||||
InputChatUploadedPhoto, MessageActionChatEditPhoto, MessageMediaGeo,
|
InputChatUploadedPhoto, MessageActionChatEditPhoto, MessageMediaGeo,
|
||||||
@@ -412,23 +411,23 @@ class PortalMatrix(BasePortal, ABC):
|
|||||||
else:
|
else:
|
||||||
self.log.trace("Unhandled Matrix event: %s", content)
|
self.log.trace("Unhandled Matrix event: %s", content)
|
||||||
|
|
||||||
async def handle_matrix_pin(self, sender: 'u.User', pinned_message: Optional[EventID],
|
async def handle_matrix_unpin_all(self, sender: 'u.User', pin_event_id: EventID) -> None:
|
||||||
|
await sender.client(UnpinAllMessagesRequest(peer=self.peer))
|
||||||
|
await self._send_delivery_receipt(pin_event_id)
|
||||||
|
|
||||||
|
async def handle_matrix_pin(self, sender: 'u.User', changes: Dict[EventID, bool],
|
||||||
pin_event_id: EventID) -> None:
|
pin_event_id: EventID) -> None:
|
||||||
if self.peer_type != "chat" and self.peer_type != "channel":
|
tg_space = self.tgid if self.peer_type == "channel" else sender.tgid
|
||||||
return
|
ids = {msg.mxid: msg.tgid
|
||||||
try:
|
for msg in DBMessage.get_by_mxids(list(changes.keys()),
|
||||||
if not pinned_message:
|
mx_room=self.mxid, tg_space=tg_space)}
|
||||||
await sender.client(UpdatePinnedMessageRequest(peer=self.peer, id=0))
|
for event_id, pinned in changes.items():
|
||||||
else:
|
try:
|
||||||
tg_space = self.tgid if self.peer_type == "channel" else sender.tgid
|
await sender.client(UpdatePinnedMessageRequest(peer=self.peer, id=ids[event_id],
|
||||||
message = DBMessage.get_by_mxid(pinned_message, self.mxid, tg_space)
|
unpin=not pinned))
|
||||||
if message is None:
|
except (ChatNotModifiedError, MessageIdInvalidError, KeyError):
|
||||||
self.log.warning(f"Could not find pinned {pinned_message} in {self.mxid}")
|
pass
|
||||||
return
|
await self._send_delivery_receipt(pin_event_id)
|
||||||
await sender.client(UpdatePinnedMessageRequest(peer=self.peer, id=message.tgid))
|
|
||||||
await self._send_delivery_receipt(pin_event_id)
|
|
||||||
except ChatNotModifiedError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def handle_matrix_deletion(self, deleter: 'u.User', event_id: EventID,
|
async def handle_matrix_deletion(self, deleter: 'u.User', event_id: EventID,
|
||||||
redaction_event_id: EventID) -> None:
|
redaction_event_id: EventID) -> None:
|
||||||
|
|||||||
@@ -694,13 +694,20 @@ class PortalTelegram(BasePortal, ABC):
|
|||||||
levels.users[puppet.mxid] = 50
|
levels.users[puppet.mxid] = 50
|
||||||
await self.main_intent.set_power_levels(self.mxid, levels)
|
await self.main_intent.set_power_levels(self.mxid, levels)
|
||||||
|
|
||||||
async def receive_telegram_pin_id(self, msg_id: TelegramID, receiver: TelegramID) -> None:
|
async def receive_telegram_pin_ids(self, msg_ids: List[TelegramID], receiver: TelegramID,
|
||||||
tg_space = receiver if self.peer_type != "channel" else self.tgid
|
remove: bool) -> None:
|
||||||
message = DBMessage.get_one_by_tgid(msg_id, tg_space) if msg_id != 0 else None
|
async with self._pin_lock:
|
||||||
if message:
|
tg_space = receiver if self.peer_type != "channel" else self.tgid
|
||||||
await self.main_intent.set_pinned_messages(self.mxid, [message.mxid])
|
previously_pinned = await self.main_intent.get_pinned_messages(self.mxid)
|
||||||
else:
|
currently_pinned_dict = {event_id: True for event_id in previously_pinned}
|
||||||
await self.main_intent.set_pinned_messages(self.mxid, [])
|
for message in DBMessage.get_first_by_tgids(msg_ids, tg_space):
|
||||||
|
if remove:
|
||||||
|
currently_pinned_dict.pop(message.mxid, None)
|
||||||
|
else:
|
||||||
|
currently_pinned_dict[message.mxid] = True
|
||||||
|
currently_pinned = list(currently_pinned_dict.keys())
|
||||||
|
if currently_pinned != previously_pinned:
|
||||||
|
await self.main_intent.set_pinned_messages(self.mxid, currently_pinned)
|
||||||
|
|
||||||
async def set_telegram_admins_enabled(self, enabled: bool) -> None:
|
async def set_telegram_admins_enabled(self, enabled: bool) -> None:
|
||||||
level = 50 if enabled else 10
|
level = 50 if enabled else 10
|
||||||
|
|||||||
Reference in New Issue
Block a user