Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add add_contacts, delete_contacts, get_contacts
  • Loading branch information
1pyxa1 committed Feb 20, 2018
commit 7d727381532223dfe42c48c5ac08f1e6bd6b48a8
102 changes: 101 additions & 1 deletion pyrogram/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,17 @@
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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately the typing module is only available for Python 3.5+. We should remove this in order to support 3.4


log = logging.getLogger(__name__)

Expand Down Expand Up @@ -2306,3 +2309,100 @@ def download_media(self, message: types.Message, file_name: str = None):
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] != '+':
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"+" + number.strip("+") instead looks cleaner.

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:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop can be replaced by a call to fetch_peers which takes care of this

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,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to keep just one argument (the list), like the raw function does. To add/delete a single contact you simply pass a list with a single element, e.g. [123456789]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, it's up to you of course

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also about consistency, other methods like forward_messages, and delete_messages work like this

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()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to check whether the Contact we want to remove exists in the user's contacts list

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if you don't have a conversation with a contact you want to remove, you need to get access_hash

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a call to resolve_peer returns nothing we simply ignore that

Copy link
Copy Markdown
Member

@delivrance delivrance Feb 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, in order to make it working for contacts, the lib must also fetch contacts when it starts and add users in the internal dictionaries, just like get_dialogs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, if you don't have a conversation with a contact you cannot remove it? or i didn't get it

Copy link
Copy Markdown
Member

@delivrance delivrance Feb 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, add_contacts will call fetch_peers to add the new contacts in the internal dictionaries, this is possible because https://docs.pyrogram.ml/types/contacts/ImportedContacts also contains the users list

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but if you restart the Client, self.get_dialogs() won't add new contacts to peers_by_id .._username. i double checked. could you please also test it. maybe my mistake.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i mean in that case if you haven't start a dialog with new contact

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, of course it won't add new contacts, because the code was missing, I've added it just now. Check new commits on this PR please

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i've understood your idea. thanks!


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))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another call to fetch_peers can be made here before returning.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another call to fetch_peers can be made here before returning.