Add command to kick relaybot users from Telegram

This commit is contained in:
Tulir Asokan
2022-08-14 14:19:36 +03:00
parent 2cf9205cda
commit 15e5cc8da1
2 changed files with 25 additions and 9 deletions
+1
View File
@@ -11,6 +11,7 @@ Minimum Conduit version remains at 0.4.0.
* Added option to include captions in the same message as the media to * Added option to include captions in the same message as the media to
implement [MSC2530]. Sending captions the same way is also supported and implement [MSC2530]. Sending captions the same way is also supported and
enabled by default. enabled by default.
* Added commands to kick or ban relaybot users from Telegram.
* Added support for Telegram's disappearing messages. * Added support for Telegram's disappearing messages.
* Added support for bridging forwarded messages as forwards on Telegram. * Added support for bridging forwarded messages as forwards on Telegram.
* Forwarding is not allowed in relay mode as the bot wouldn't be able to * Forwarding is not allowed in relay mode as the bot wouldn't be able to
+24 -9
View File
@@ -49,7 +49,7 @@ from telethon.tl.types import (
from telethon.utils import add_surrogate, del_surrogate from telethon.utils import add_surrogate, del_surrogate
from mautrix.errors import MBadState, MForbidden from mautrix.errors import MBadState, MForbidden
from mautrix.types import UserID from mautrix.types import RoomID, UserID
from . import portal as po, puppet as pu, user as u from . import portal as po, puppet as pu, user as u
from .abstract_user import AbstractUser from .abstract_user import AbstractUser
@@ -57,6 +57,7 @@ from .db import BotChat, Message as DBMessage
from .types import TelegramID from .types import TelegramID
ReplyFunc = Callable[[str], Awaitable[Message]] ReplyFunc = Callable[[str], Awaitable[Message]]
BanFunc = Callable[[RoomID, UserID, str], Awaitable[None]]
TelegramAdminPermission = Literal[ TelegramAdminPermission = Literal[
"change_info", "change_info",
"post_messages", "post_messages",
@@ -89,6 +90,7 @@ class Bot(AbstractUser):
"portal": None, "portal": None,
"invite": "invite_users", "invite": "invite_users",
"mxban": "ban_users", "mxban": "ban_users",
"mxkick": "ban_users",
} }
def __init__(self, token: str) -> None: def __init__(self, token: str) -> None:
@@ -295,7 +297,12 @@ class Bot(AbstractUser):
return await reply(f"Invited `{user.mxid}` to the portal.") return await reply(f"Invited `{user.mxid}` to the portal.")
async def handle_command_ban( async def handle_command_ban(
self, message: Message, portal: po.Portal, reply: ReplyFunc, reason: str self,
message: Message,
portal: po.Portal,
reply: ReplyFunc,
reason: str,
action: Literal["kick", "ban"] = "ban",
) -> Message: ) -> Message:
if not message.reply_to: if not message.reply_to:
return await reply("You must reply to a relaybot message when using that command") return await reply("You must reply to a relaybot message when using that command")
@@ -305,23 +312,29 @@ class Bot(AbstractUser):
if not msg or msg.sender != self.tgid or not msg.sender_mxid: if not msg or msg.sender != self.tgid or not msg.sender_mxid:
return await reply("Target message is not a relayed message") return await reply("Target message is not a relayed message")
puppet = await pu.Puppet.get_by_peer(message.from_id) puppet = await pu.Puppet.get_by_peer(message.from_id)
actioned = "Banned" if action == "ban" else "Kicked"
try: try:
await puppet.intent_for(portal).ban_user(portal.mxid, msg.sender_mxid, reason) intent = puppet.intent_for(portal)
func: BanFunc = intent.ban_user if action == "ban" else intent.kick_user
await func(portal.mxid, msg.sender_mxid, reason)
except MForbidden as e: except MForbidden as e:
self.log.warning( self.log.warning(
f"Failed to ban {msg.sender_mxid} from {portal.mxid} as {puppet.mxid}: {e}, " f"Failed to {action} {msg.sender_mxid} from {portal.mxid} as {puppet.mxid}: {e}, "
f"falling back to bridge bot" f"falling back to bridge bot"
) )
reason_prefix = f"Banned by {puppet.displayname or puppet.tgid}" reason_prefix = f"{actioned} by {puppet.displayname or puppet.tgid}"
reason = f"{reason_prefix}: {reason}" if reason else reason_prefix reason = f"{reason_prefix}: {reason}" if reason else reason_prefix
try: try:
await self.az.intent.ban_user(portal.mxid, msg.sender_mxid, reason) func: BanFunc = (
self.az.intent.ban_user if action == "ban" else self.az.intent.kick_user
)
await func(portal.mxid, msg.sender_mxid, reason)
except MForbidden as e: except MForbidden as e:
self.log.warning( self.log.warning(
f"Failed to ban {msg.sender_mxid} from {portal.mxid} as bridge bot: {e}" f"Failed to {action} {msg.sender_mxid} from {portal.mxid} as bridge bot: {e}"
) )
return await reply(f"Failed to ban `{msg.sender_mxid}`") return await reply(f"Failed to {action} `{msg.sender_mxid}`")
return await reply(f"Successfully banned `{msg.sender_mxid}`") return await reply(f"Successfully {actioned.lower()} `{msg.sender_mxid}`")
@staticmethod @staticmethod
def handle_command_id(message: Message, reply: ReplyFunc) -> Awaitable[Message]: def handle_command_id(message: Message, reply: ReplyFunc) -> Awaitable[Message]:
@@ -378,6 +391,8 @@ class Bot(AbstractUser):
await self.handle_command_invite(portal, reply, mxid_input=UserID(args)) await self.handle_command_invite(portal, reply, mxid_input=UserID(args))
elif command == "mxban": elif command == "mxban":
await self.handle_command_ban(message, portal, reply, reason=args) await self.handle_command_ban(message, portal, reply, reason=args)
elif command == "mxkick":
await self.handle_command_ban(message, portal, reply, reason=args, action="kick")
async def handle_service_message(self, message: MessageService) -> None: async def handle_service_message(self, message: MessageService) -> None:
to_peer = message.to_id to_peer = message.to_id