From 7d727381532223dfe42c48c5ac08f1e6bd6b48a8 Mon Sep 17 00:00:00 2001 From: RussFP <1pyxa1@gmail.com> Date: Tue, 20 Feb 2018 14:20:34 +0300 Subject: [PATCH 1/7] add add_contacts, delete_contacts, get_contacts --- pyrogram/client/client.py | 102 +++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 4329672a..98cff8bb 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -45,14 +45,17 @@ from pyrogram.api.errors import ( from pyrogram.api.types import ( User, Chat, Channel, PeerUser, PeerChannel, + InputUser, InputPeerEmpty, InputPeerSelf, - InputPeerUser, InputPeerChat, InputPeerChannel + InputPeerUser, InputPeerChat, InputPeerChannel, + InputPhoneContact ) from pyrogram.crypto import AES from pyrogram.session import Auth, Session from pyrogram.session.internals import MsgId from .input_media import InputMedia from .style import Markdown, HTML +from typing import List, Union log = logging.getLogger(__name__) @@ -2306,3 +2309,100 @@ class Client: self.download_queue.put((media, file_name, done)) done.wait() + + def add_contacts(self, + phone: Union[int, str] = None, + first_name: str = None, + last_name: str = None, + input_phone_contact_list: List[InputPhoneContact] = None): + if (phone is None or first_name is None) and \ + input_phone_contact_list is None: + log.warning("(phone and first_name) or input_phone_contact_list " + "must be not None") + return None + + if phone is not None and first_name is not None: + if str(phone)[0] != '+': + phone = '+' + str(phone) + input_phone_contact_list = [] + input_phone_contact = InputPhoneContact(client_id=0, + phone=phone, + first_name=first_name, + last_name=last_name or '') + input_phone_contact_list.append(input_phone_contact) + + # make sure that we send only InputPhoneContact + inner_input_phone_contact_list = [] + for contact in input_phone_contact_list: + if isinstance(contact, InputPhoneContact): + inner_input_phone_contact_list.append(contact) + + imported_contacts = self.send( + functions.contacts.ImportContacts(inner_input_phone_contact_list)) + + for user in imported_contacts.users: + if isinstance(user, User): + if user.id in self.peers_by_id: + continue + + if user.access_hash is None: + continue + + input_peer = InputPeerUser( + user_id=user.id, + access_hash=user.access_hash + ) + + self.peers_by_id[user.id] = input_peer + + if user.username is not None: + self.peers_by_username[user.username] = input_peer + + return imported_contacts + + def delete_contacts(self, _id: int = None, + ids_list: Union[ + List[int], List[InputUser]] = None): + if _id is None and ids_list is None: + log.warning('id or ids_list must be not None') + return False + + contacts = self.get_contacts() + + if _id is not None: + if not isinstance(_id, int): + log.warning('id is not int') + return False + + input_user = None + for user in contacts.users: + if isinstance(user, User): + if _id == user.id: + input_user = InputUser(user_id=user.id, + access_hash=user.access_hash) + break + + ids_list = [input_user] + + inner_ids_list = [] + for _id in ids_list: + if isinstance(_id, InputUser): + inner_ids_list.append(_id) + + if isinstance(_id, int): + input_user = None + for user in contacts.users: + if isinstance(user, User): + if _id == user.id: + input_user = InputUser( + user_id=user.id, + access_hash=user.access_hash) + break + inner_ids_list.append(input_user) + + res = self.send(functions.contacts.DeleteContacts(inner_ids_list)) + return res + + def get_contacts(self, _hash: int = 0): + return self.send(functions.contacts.GetContacts(_hash)) + From 2ab8fbe04776e50b05e66f4d1d3ff7f96e81e4eb Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:01:28 +0100 Subject: [PATCH 2/7] Add InputPhoneContact type --- pyrogram/__init__.py | 1 + pyrogram/client/input_phone_contact.py | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 pyrogram/client/input_phone_contact.py diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 6dfc2b39..db7a3a84 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -30,4 +30,5 @@ from .client import ChatAction from .client import Client from .client import ParseMode from .client.input_media import InputMedia +from .client.input_phone_contact import InputPhoneContact from .client import Emoji diff --git a/pyrogram/client/input_phone_contact.py b/pyrogram/client/input_phone_contact.py new file mode 100644 index 00000000..d67092ff --- /dev/null +++ b/pyrogram/client/input_phone_contact.py @@ -0,0 +1,11 @@ +from pyrogram.api.types import InputPhoneContact as RawInputPhoneContact + + +class InputPhoneContact: + def __new__(cls, phone: str, first_name: str, last_name: str = ""): + return RawInputPhoneContact( + client_id=0, + phone="+" + phone.strip("+"), + first_name=first_name, + last_name=last_name + ) From 3ff3f5d9f4e84be1d8100423643457f5eda71622 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:03:35 +0100 Subject: [PATCH 3/7] Rewrite add_contacts and delete_contacts --- pyrogram/client/client.py | 112 ++++++++------------------------------ 1 file changed, 22 insertions(+), 90 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 98cff8bb..472af427 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -45,17 +45,14 @@ from pyrogram.api.errors import ( from pyrogram.api.types import ( User, Chat, Channel, PeerUser, PeerChannel, - InputUser, InputPeerEmpty, InputPeerSelf, - InputPeerUser, InputPeerChat, InputPeerChannel, - InputPhoneContact + InputPeerUser, InputPeerChat, InputPeerChannel ) from pyrogram.crypto import AES from pyrogram.session import Auth, Session from pyrogram.session.internals import MsgId from .input_media import InputMedia from .style import Markdown, HTML -from typing import List, Union log = logging.getLogger(__name__) @@ -2310,99 +2307,34 @@ class Client: done.wait() - def add_contacts(self, - phone: Union[int, str] = None, - first_name: str = None, - last_name: str = None, - input_phone_contact_list: List[InputPhoneContact] = None): - if (phone is None or first_name is None) and \ - input_phone_contact_list is None: - log.warning("(phone and first_name) or input_phone_contact_list " - "must be not None") - return None - - if phone is not None and first_name is not None: - if str(phone)[0] != '+': - phone = '+' + str(phone) - input_phone_contact_list = [] - input_phone_contact = InputPhoneContact(client_id=0, - phone=phone, - first_name=first_name, - last_name=last_name or '') - input_phone_contact_list.append(input_phone_contact) - - # make sure that we send only InputPhoneContact - inner_input_phone_contact_list = [] - for contact in input_phone_contact_list: - if isinstance(contact, InputPhoneContact): - inner_input_phone_contact_list.append(contact) - + def add_contacts(self, contacts: list): imported_contacts = self.send( - functions.contacts.ImportContacts(inner_input_phone_contact_list)) + functions.contacts.ImportContacts( + contacts=contacts + ) + ) - for user in imported_contacts.users: - if isinstance(user, User): - if user.id in self.peers_by_id: - continue - - if user.access_hash is None: - continue - - input_peer = InputPeerUser( - user_id=user.id, - access_hash=user.access_hash - ) - - self.peers_by_id[user.id] = input_peer - - if user.username is not None: - self.peers_by_username[user.username] = input_peer + self.fetch_peers(imported_contacts.users) return imported_contacts - def delete_contacts(self, _id: int = None, - ids_list: Union[ - List[int], List[InputUser]] = None): - if _id is None and ids_list is None: - log.warning('id or ids_list must be not None') - return False + def delete_contacts(self, ids: list): + contacts = [] - contacts = self.get_contacts() + for i in ids: + try: + input_user = self.resolve_peer(i) + except PeerIdInvalid: + continue + else: + if isinstance(input_user, types.InputPeerUser): + contacts.append(input_user) - if _id is not None: - if not isinstance(_id, int): - log.warning('id is not int') - return False - - input_user = None - for user in contacts.users: - if isinstance(user, User): - if _id == user.id: - input_user = InputUser(user_id=user.id, - access_hash=user.access_hash) - break - - ids_list = [input_user] - - inner_ids_list = [] - for _id in ids_list: - if isinstance(_id, InputUser): - inner_ids_list.append(_id) - - if isinstance(_id, int): - input_user = None - for user in contacts.users: - if isinstance(user, User): - if _id == user.id: - input_user = InputUser( - user_id=user.id, - access_hash=user.access_hash) - break - inner_ids_list.append(input_user) - - res = self.send(functions.contacts.DeleteContacts(inner_ids_list)) - return res + return self.send( + functions.contacts.DeleteContacts( + id=contacts + ) + ) def get_contacts(self, _hash: int = 0): return self.send(functions.contacts.GetContacts(_hash)) - From c99bc9118badcf00559f12c0cdf588ef7fc3e8b0 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:05:17 +0100 Subject: [PATCH 4/7] Fetch users when getting contacts --- pyrogram/client/client.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 472af427..7611abcd 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -2337,4 +2337,7 @@ class Client: ) def get_contacts(self, _hash: int = 0): - return self.send(functions.contacts.GetContacts(_hash)) + contacts = self.send(functions.contacts.GetContacts(_hash)) + self.fetch_peers(contacts.users) + + return contacts From c33719be9e546329c18eeba32c76894f86e0275e Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:06:12 +0100 Subject: [PATCH 5/7] Call get_contacts when starting the client --- pyrogram/client/client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 7611abcd..34fa401b 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -183,6 +183,7 @@ class Client: self.rnd_id = MsgId self.get_dialogs() + self.get_contacts() for i in range(self.UPDATES_WORKERS): Thread(target=self.updates_worker, name="UpdatesWorker#{}".format(i + 1)).start() From c5281eb963d0bbc9f3627dbcfa0e8a3ef5a8754b Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:28:01 +0100 Subject: [PATCH 6/7] Add ability to send messages to contacts by using their phone numbers --- pyrogram/client/client.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 34fa401b..8f149c94 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -135,6 +135,7 @@ class Client: self.peers_by_id = {} self.peers_by_username = {} + self.peers_by_phone = {} self.channels_pts = {} @@ -225,6 +226,7 @@ class Client: continue username = entity.username + phone = entity.phone input_peer = InputPeerUser( user_id=user_id, @@ -236,6 +238,9 @@ class Client: if username is not None: self.peers_by_username[username] = input_peer + if phone is not None: + self.peers_by_phone[phone] = input_peer + if isinstance(entity, Chat): chat_id = entity.id @@ -795,6 +800,12 @@ class Client: if peer_id in ("self", "me"): return InputPeerSelf() + if peer_id.startswith("+"): + try: + return self.peers_by_phone[peer_id] + except KeyError: + raise PeerIdInvalid + peer_id = peer_id.lower().strip("@") try: From 5a44b93574a47af7ba227141af5495e98aaf1202 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:48:10 +0100 Subject: [PATCH 7/7] Accept phone numbers with and without a leading "+" --- pyrogram/client/client.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 8f149c94..2548998c 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -800,19 +800,21 @@ class Client: if peer_id in ("self", "me"): return InputPeerSelf() - if peer_id.startswith("+"): + peer_id = peer_id.lower().strip("@+") + + try: + int(peer_id) + except ValueError: + try: + return self.peers_by_username[peer_id] + except KeyError: + return self.resolve_username(peer_id) + else: try: return self.peers_by_phone[peer_id] except KeyError: raise PeerIdInvalid - peer_id = peer_id.lower().strip("@") - - try: - return self.peers_by_username[peer_id] - except KeyError: - return self.resolve_username(peer_id) - if type(peer_id) is not int: if isinstance(peer_id, types.PeerUser): peer_id = peer_id.user_id