From 897a35be5d98dc853bdf548eeb1fbb29f9e3872a Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Nov 2023 14:42:06 +0200 Subject: [PATCH] Add commands to add and delete contacts. Fixes #885 --- mautrix_telegram/commands/handler.py | 2 + mautrix_telegram/commands/telegram/misc.py | 76 +++++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/mautrix_telegram/commands/handler.py b/mautrix_telegram/commands/handler.py index 1e47a96d..545ecbea 100644 --- a/mautrix_telegram/commands/handler.py +++ b/mautrix_telegram/commands/handler.py @@ -159,6 +159,7 @@ def command_handler( needs_admin: bool = False, management_only: bool = False, name: str | None = None, + aliases: list[str] | None = None, help_text: str = "", help_args: str = "", help_section: HelpSection = None, @@ -167,6 +168,7 @@ def command_handler( _func, _handler_class=CommandHandler, name=name, + aliases=aliases, help_text=help_text, help_args=help_args, help_section=help_section, diff --git a/mautrix_telegram/commands/telegram/misc.py b/mautrix_telegram/commands/telegram/misc.py index 274a21cf..37f2cbf9 100644 --- a/mautrix_telegram/commands/telegram/misc.py +++ b/mautrix_telegram/commands/telegram/misc.py @@ -18,8 +18,8 @@ from __future__ import annotations from typing import cast import base64 import codecs -import math import re +import shlex from aiohttp import ClientSession, InvalidURL from telethon.errors import ( @@ -29,10 +29,10 @@ from telethon.errors import ( InviteHashInvalidError, InviteRequestSentError, OptionsTooMuchError, - TakeoutInitDelayError, UserAlreadyParticipantError, ) from telethon.tl.functions.channels import JoinChannelRequest +from telethon.tl.functions.contacts import DeleteByPhonesRequest, ImportContactsRequest from telethon.tl.functions.messages import ( CheckChatInviteRequest, GetBotCallbackAnswerRequest, @@ -42,12 +42,14 @@ from telethon.tl.functions.messages import ( from telethon.tl.patched import Message from telethon.tl.types import ( InputMediaDice, + InputPhoneContact, MessageMediaGame, MessageMediaPoll, TypeInputPeer, TypeUpdates, User as TLUser, ) +from telethon.tl.types.contacts import ImportedContacts from telethon.tl.types.messages import BotCallbackAnswer from mautrix.types import EventID, Format @@ -161,6 +163,76 @@ async def pm(evt: CommandEvent) -> EventID: return await evt.reply(f"Created private chat room with {displayname}") +async def _handle_contact(source: AbstractUser, user: TLUser) -> str: + puppet: pu.Puppet = await pu.Puppet.get_by_tgid(user.id) + await puppet.update_info(source, user) + + params = [] + if user.username: + params.append(f"[@{user.username}](https://t.me/{user.username})") + if user.phone: + params.append(f"+{user.phone}") + params.append(f"ID `{user.id}`") + params_str = " / ".join(params) + return f"[{puppet.displayname}](https://matrix.to/#/{puppet.mxid}): {params_str}" + + +@command_handler( + help_section=SECTION_CREATING_PORTALS, + help_args="<_phone_> <_first name_> <_last name_>", + help_text="Add a phone number to your contacts on Telegram", +) +async def add_contact(evt: CommandEvent) -> EventID: + if len(evt.args) < 3: + return await evt.reply( + "**Usage:** `$cmdprefix+sp add-contact `" + ) + try: + names = shlex.split(" ".join(evt.args[1:])) + except ValueError as e: + return await evt.reply( + f"Failed to parse names (use shell quoting for names with spaces): {e}" + ) + if len(names) != 2: + return await evt.reply( + "Wrong number of names, must have first and last name " + "(use shell quoting for names with spaces)" + ) + res: ImportedContacts = await evt.sender.client( + ImportContactsRequest( + contacts=[ + InputPhoneContact( + client_id=1, phone=evt.args[0], first_name=names[0], last_name=names[1] + ) + ] + ) + ) + if res.retry_contacts: + return await evt.reply("Failed to import contacts") + elif not res.users: + return await evt.reply("Contact imported, but user not found on Telegram") + imported_str = "\n".join( + [f"* {await _handle_contact(evt.sender, user)}" for user in res.users] + ) + return await evt.reply(f"Imported contacts:\n\n{imported_str}") + + +@command_handler( + help_section=SECTION_CREATING_PORTALS, + help_args="<_phones..._>", + help_text="Remove phone numbers from your contacts on Telegram.", + aliases=["remove-contact", "delete-contacts", "remove-contacts"], +) +async def delete_contact(evt: CommandEvent) -> EventID: + if len(evt.args) == 0: + return await evt.reply("**Usage:** `$cmdprefix+sp delete-contact `") + ok = await evt.sender.client(DeleteByPhonesRequest(phones=evt.args)) + if ok: + return await evt.reply("Contacts deleted") + else: + return await evt.reply("Contacts not deleted?") + + async def _join( evt: CommandEvent, identifier: str, link_type: str ) -> tuple[TypeUpdates | None, EventID | None]: