I keep on getting 'PeerIdInvalidError' when using Telethon - python

I am making a program that adds users to a group using phone number:
contact = InputPhoneContact(client_id=0, phone=phone, first_name=phone, last_name='add')
result = session(ImportContactsRequest([contact]))
user_input = InputPeerUser(result.users[0].id, result.users[0].access_hash)
session(functions.messages.AddChatUserRequest(user_id=user_input, fwd_limit=0, chat_id=import_chat.chats[0].id))
I keep on getting PeerIdInvalidError when running AddChatUserRequest
Edit: This algorithm works but it shows this error when adding some accounts. The error is caused by AddChatUserRequest

It might be the case that the user has disabled or rejecting the feature to be added to groups by other users. If you have multiple accounts or know some of them, you could test this case.

Related

Python Django - delaying ValidationError until for loop completes

I'm working on an app that simulates a social media site. I currently have a form where users can enter in their friends' emails so they can be invited to join the app.
Let's say we have a user who enters in three email addresses to the email form which are then saved as a list of strings:
emails_to_invite = ["jen#website.com", "mike#website.com", "joe#website.com"]
In the database, we already have a list of users who have already been invited to the site:
current_users = ["jen#website.com", "mike#website.com", "dan#website.com", "kim#website.com"]
So we have two users who have already been invited: jen#website.com and mike#website.com.
I'm trying to write some code that returns a ValidationError and can list both matched users in the message. Here's what I have so far:
for email in emails_to_invite:
if email in current_users:
raise forms.ValidationError(f"{email} is already in the database.")
Here's how I want this error to display:
jen#website.com is already in the database.
mike#website.com is already in the database.
But right now, the error only displays the first email:
jen#website.com is already in the database.
I also need mike#website.com to display too. It appears that the for loop stops once it recognizes one match, but I need it to keep going until it recognizes all matches. Can anyone offer some suggestions?
If you don't want an Exception in a code-block to halt your execution (and hide further exceptions, as you've found), put the susceptible code in a a try/except block to handle the error as you see fit.
To later raise the exception, consider using something like:
raised_exceptions = []
<loop that might raise exceptions>
try:
<loop that might raise exceptions>
except Exception as e:
raised_exceptions.append(e)
<do something with the exceptions you saved>
That being said, IMO you shouldn't be using exceptions in this way - consider returning a series of lists, one per possible outcome, instead: email sent and already invited (and/or joined user)

Python imaplib can't select() custom gmail labels

I have a bot I'm writing using imaplib in python to fetch emails from gmail and output some useful data from them. I've hit a snag on selecting the inbox, though; the existing sorting system uses custom labels to separate emails from different customers. I've partially replicated this system in my test email, but imaplib.select() throws a "imaplib.IMAP4.error: SELECT command error: BAD [b'Could not parse command']" with custom labels. Screenshot attatched My bot has no problem with the default gmail folders, fetching INBOX or [Gmail]/Spam. In that case, it hits an error later in the code that deals with completely different problem I have yet to fix. The point, though, is that imaplib.select() is succsessful with default inboxes and just not custom labels.
The way my code works is it works through all the available inboxes, compares it to a user-inputted name, and if they match, saves the name and sets a boolean to true to signal that it found a match. It then checks, if there was a match (the user-inputted inbox exists) it goes ahead, otherwise it throws an error message and resets. It then attempts to select the inbox the user entered.
I've verified that the variable the program's saving the inbox name to matches what's listed as the name in the imap.list() command. I have no idea what the issue is.
I could bypass the process by iterating through all mail to find the email's I'm looking for, but it's far more efficient to use the existing sorting system due to the sheer number of emails on the account I'll be using.
Any help is appreciated!
EDIT: Code attached after request. Thank you to the person who told me to do so.
'''
Fetches emails from the specified inbox and outputs them to a popup
'''
def fetchEmails(self):
#create an imap object. Must be local otherwise we can only establish a single connection
#imap states are kinda bad
imap = imaplib.IMAP4_SSL(host="imap.gmail.com", port="993")
#Login and fetch a list of available inboxes
imap.login(username.get(), password.get())
type, inboxList = imap.list()
#Set a reference boolean and iterate through the list
inboxNameExists = False
for i in inboxList:
#Finds the name of the inbox
name = self.inboxNameParser(i.decode())
#If the given inbox name is encountered, set its existence to true and break
if name.casefold().__eq__(inboxName.get().casefold()):
inboxNameExists = True
break
#If the inbox name does not exist, break and give error message
if inboxNameExists != True:
self.logout(imap)
tk.messagebox.showerror("Disconnected!", "That Inbox does not exist.")
return
'''
If/else to correctly feed the imap.select() method the inbox name
Apparently inboxes containing spaces require quoations before and after
Selects the inbox and pushes it to a variable
two actually but the first is unnecessary(?)
imap is weird
'''
if(name.count(" ") > 0):
status, messages = imap.select("\"" + name + "\"")
else:
status, messages = imap.select(name);
#Int containing total number of emails in inbox
messages = int(messages[0])
#If there are no messages disconnect and show an infobox
if messages == 0:
self.logout(imap)
tk.messagebox.showinfo("Disconnected!", "The inbox is empty.")
self.mailboxLoop(imap, messages)
Figured the issue out after a few hours banging through it with a friend. As it turns out the problem was that imap.select() wants quotations around the mailbox name if it contains spaces. So imap.select("INBOX") is fine, but with spaces you'd need imap.select("\"" + "Label Name" + "\"")
You can see this reflected in the code I posted with the last if/else statement.
Python imaplib requires mailbox names with spaces to be surrounded by apostrophes. So imap.select("INBOX") is fine, but with spaces you'd need imap.select("\"" + "Label Name" + "\"").

Gmail API: Python Email Dict appears to be Missing Keys

I'm experiencing a strange issue that seems to be inconsistent with google's gmail API:
If you look here, you can see that gmail's representation of an email has keys "snippet" and "id", among others. Here's some code that I use to generate the complete list of all my emails:
response = service.users().messages().list(userId='me').execute()
messageList = []
messageList.extend(response['messages'])
while 'nextPageToken' in response:
pagetoken = response['nextPageToken']
response = service.users().messages().list(userId='me', pageToken=pagetoken).execute()
messageList.extend(response['messages'])
for message in messageList:
if 'snippet' in message:
print(message['snippet'])
else:
print("FALSE")
The code works!... Except for the fact that I get output "FALSE" for every single one of the emails. 'snippet' doesn't exist! However, if I run the same code with "id" instead of snippet, I get a whole bunch of ids!
I decided to just print out the 'message' objects/dicts themselves, and each one only had an "id" and a "threadId", even though the API claims there should be more in the object... What gives?
Thanks for your help!
As #jedwards said in his comment, just because a message 'can' contain all of the fields specified in documentation, doesn't mean it will. 'list' provides the bare minimum amount of information for each message, because it provides a lot of messages and wants to be as lazy as possible. For individual messages that I want to know more about, I'd then use 'messages.get' with the id that I got from 'list'.
Running get for each email in your inbox seems very expensive, but to my knowledge there's no way to run a batch 'get' command.

Facebook SDK for Python - getting all page likes of a Facebook profile

Using an access token from the Facebook Graph API Explorer (https://developers.facebook.com/tools/explorer), with access scope which includes user likes, I am using the following code to try to get all the likes of a user profile:
myfbgraph = facebook.GraphAPI(token)
mylikes = myfbgraph.get_connections(id="me", connection_name="likes")['data']
for like in mylikes:
print like['name'], like['category']
...
However this is always giving me only 25 likes, whereas I know that the profile I'm using has 42 likes. Is there some innate limit operating here, or what's the problem in getting ALL the page likes of a user profile?
Per the Graph documention:
When you make an API request to a node or edge, you will usually not
receive all of the results of that request in a single response. This
is because some responses could contain thousands and thousands of
objects, and so most responses are paginated by default.
https://developers.facebook.com/docs/graph-api/using-graph-api/v2.2#paging
Well, this appears to work (a method, which accepts a user's facebook graph):
def get_myfacebook_likes(myfacebook_graph):
myfacebook_likes = []
myfacebook_likes_info = myfacebook_graph.get_connections("me", "likes")
while myfacebook_likes_info['data']:
for like in myfacebook_likes_info['data']:
myfacebook_likes.append(like)
if 'next' in myfacebook_likes_info['paging'].keys():
myfacebook_likes_info = requests.get(myfacebook_likes_info['paging']['next']).json()
else:
break
return myfacebook_likes
The above answers will work, but pretty slowly for anything with many likes. If you just want the count for number of likes, you can get it much more efficiently with total_likes:
myfacebook_likes_info = graph.get_connections(post['id'], 'likes?summary=1')
print myfacebook_likes_info["summary"]["total_count"]

Number of entities returned from a GQL Query

I'm new to Python and currently working on my first Google App Engine application. In my program I have an 'Inbox' database model which contains string proporties like to_user, from_user, title, content, etc. When a user logs in to my app I want to be able to count the number of messages that were sent to him/her, this way I can display it as "New Messages(x)". I feel like I currently am using a work around because I can't find a better way.
user = users.get_current_user()
inbox = Inbox.gql('WHERE to_user = :to_user', to_user=user.nickname())
count = 0
for note in inbox:
count = count+1
I tried using len(inbox) but that gave me an error. Thanks for your time.
In your specific case, where the number of New Messages will probably be small, I would not bother to create a counter upfront as suggested here.
I would go with a simpler solution using count() function:
user = users.get_current_user()
inbox = Inbox.gql('WHERE to_user = :to_user', to_user=user.nickname())
count = inbox.count()

Categories

Resources