Unable to verify phone number is in file - python

I'm developing an text message marketing service. In order to subscribe to my service, the user must text the keyword memphis. I've already written the code to add the users number to my subscriber's list, but if someone's number is already on the list, how can I include a process to check the already existing list and reply back with a message informing the user that they are already subscribed?
I have tried using a for loop to iterate over every number in the csv file:
def sms_subscription():
contact_num = request.values.get('From')
response = request.values.get('Body')
resp = MessagingResponse()
#NEW SUBSCRIBERS
if response.lower() == 'memphis':
with open('Subscriber_List.csv', 'r+') as subscriber_list:
subscriber_list_writer = csv.writer(subscriber_list)
for contact in subscriber_list:
if contact == contact_num:
resp.message("Your already subscribed")
return str(resp)
else:
subscriber_list_writer.writerow([contact_num])
resp.message("Thanks for subscribing to our local coupon book. As we get new deals, we'll notify via SMS. To opt-out reply 'STOP'")
return str(resp)
else:
resp.message("Be sure to check spelling and for spaces and try again.")
return str(resp
I've tested this with my personal cell phone. Instead of replying back to me that my number is already subscribed, I continue to get the "Thanks for subscribing to our local coupon book.
As we get new deals, we'll notify the user via SMS. To opt-out, the user would reply 'STOP'.

I think I see the problem.
Your code:
def sms_subscription():
contact_num = request.values.get('From')
response = request.values.get('Body')
resp = MessagingResponse()
#NEW SUBSCRIBERS
if response.lower() == 'memphis':
with open('Subscriber_List.csv', 'r+') as subscriber_list:
subscriber_list_writer = csv.writer(subscriber_list)
for contact in subscriber_list:
if contact == contact_num:
resp.message("Your already subscribed")
return str(resp)
else:
subscriber_list_writer.writerow([contact_num])
resp.message("Thanks for subscribing to our local coupon book. As we get new deals, we'll notify via SMS. To opt-out reply 'STOP'")
return str(resp)
else:
resp.message("Be sure to check spelling and for spaces and try again.")
return str(resp
First off, you should change subscriber_list to subscriber_list.readlines() to get a list in which each line is an element.
In your for loop you check if contact equals contact_num, but contact contains a newline (\n) (in my case when I tested it, but it may contain whitespaces or other chars), and thus is not equal to contact_num. To fix this, you can add these lines (there are one-liners to do this, with regex for example, but I'm using this example for readability and simplicity) above if contact == contact_num:
contact = contact.replace('\n','')
contact = contact.replace(' ','')
What these do is replace newlines and whitespaces with nothing, essentially removing them.
Furthermore, in your for loop, you are checking if contact_num is in the file, but if it is not the first element, then it will run this:
else:
subscriber_list_writer.writerow([contact_num])
resp.message("Thanks for subscribing to our local coupon book. As we get new deals, we'll notify via SMS. To opt-out reply 'STOP'")
return str(resp)
What you need is to check all elements in the file, and then, if the number was not found, write it to the file. When you return a value, it exits the function, so if the first element in your file is not the desired phone number, then it will run your code under else and exit the function.
To fix this, just move
else:
subscriber_list_writer.writerow([contact_num])
resp.message("Thanks for subscribing to our local coupon book. As we get new deals, we'll notify via SMS. To opt-out reply 'STOP'")
return str(resp)
outside of the for loop, and remove the else-- it is not needed. The loop will now check to see if contact_num is in the file, and if it is, it will return
"You're already subscribed",
if not, it will add the num to the file and return
"Thanks for subscribing to our local coupon book. As we get new deals, we'll notify via SMS. To opt-out reply 'STOP'"
I am assuming that MessagingResponse() is a class, like so:
class MessagingResponse:
def __init__(self,message):
self.message = message
If so, resp.message("Your already subscribed") will throw an error; the correct syntax is resp.message = "Your already subscribed".
Final code (with a few modifications):
EDIT:
As #jpmc26 said, using the csv reader/writer is a better option. There were also some bugs in the previous code. Edited code:
def sms_subscription():
contact_num = request.values.get('From')
response = request.values.get('Body')
resp = MessagingResponse("") #you might want to remove the quotes if this throws an error
#NEW SUBSCRIBERS
if response.lower() == 'memphis':
with open('Subscriber_List.csv', 'r+') as subscriber_list:
for contact in csv.reader(subscriber_list):
if contact_num in contact:
resp.message = "You're already subscribed"
return resp
csv.writer(subscriber_list).writerow([contact_num])
resp.message = ("Thanks for subscribing to our local coupon book. As we get new deals, we'll notify via SMS. To opt-out reply 'STOP'")
return resp
else:
resp.message = "Be sure to check spelling and for spaces and try again."
return resp

Related

Get local variable after function call in python

I have a function in python that change my account password. That is something like follows :
def f(account):
new_password = # Some random string generation
# Do something and send password change request to remote
account.password = new_password
account.save()
In the second line of above function I send a post request to change my password and then do some processing and finally save my new password. In the processing phase some error has occurred, but unfortunately my request has been sent to server. I have called the function in python shell and now my password has changed but I don't have it. Is it possible to get new_password variable from my function in python shell?
First of all, that is not valid Python code. Functions are not defined with function, but with def. (It seems you updated your question after reading this).
If indeed the function is called with an account object, then the caller will have access to it after the call. So account.password should have the password, unless account.save() wiped it out.
For instance, this could work:
def f(account):
new_password = # Some random string generation
# Do something and send password change request to remote
account.password = new_password
account.save()
account = Account() # do here whatever you do to get an account object
try: # Trap errors
f(account)
except:
print("Something went wrong...")
finally: # Whether an exception occurred or not, print the password
print("The password is:", account.password)
Again, this can only provide the password if account.save() did not destroy the value assigned to account.password.
If you can change the f function to your needs, then include the error handling inside that function and have it return the password:
def f(account):
new_password = # Some random string generation
# Do something and send password change request to remote
account.password = new_password
try: # Trap errors
account.save()
except:
print("Something went wrong...")
return new_password
account = Account() # do here whatever you do to get an account object
new_password = f(account) # now you will have the password returned
print("The password is:", new_password)
If however you already called the function and the program ended, then it is of course too late now. You must take the necessary precautions before running the code, and only run it when you are sure you can recover the password whatever happens.

How to get the next telegram messages from specific users

I'm implementing a telegram bot that will serve users. Initially, it used to get any new message sequentially, even in the middle of an ongoing session with another user. Because of that, anytime 2 or more users tried to use the bot, it used to get all jumbled up. To solve this I implemented a queue system that put users on hold until the ongoing conversation was finished. But this queue system is turning out to be a big hassle. I think my problems would be solved with just a method to get the new messages from a specific chat_id or user. This is the code that I'm using to get any new messages:
def get_next_message_result(self, update_id: int, chat_id: str):
"""
get the next message the of a given chat.
In case of the next message being from another user, put it on the queue, and wait again for
expected one.
"""
update_id += 1
link_requisicao = f'{self.url_base}getUpdates?timeout={message_timeout}&offset={update_id}'
result = json.loads(requests.get(link_requisicao).content)["result"]
if len(result) == 0:
return result, update_id # timeout
if "text" not in result[0]["message"]:
self.responder(speeches.no_text_speech, message_chat_id)
return [], update_id # message without text
message_chat_id = result[0]["message"]["chat"]["id"]
while message_chat_id != chat_id:
self.responder(speeches.wait_speech, message_chat_id)
if message_chat_id not in self.current_user_queue:
self.current_user_queue.append(message_chat_id)
print("Queuing user with the following chat_id:", message_chat_id)
update_id += 1
link_requisicao = f'{self.url_base}getUpdates?timeout={message_timeout}&offset={update_id}'
result = json.loads(requests.get(link_requisicao).content)["result"]
if len(result) == 0:
return result, update_id # timeout
if "text" not in result[0]["message"]:
self.responder(speeches.no_text_speech, message_chat_id)
return [], update_id # message without text
message_chat_id = result[0]["message"]["chat"]["id"]
return result, update_id
On another note: I use the queue so that the moment the current conversation ends, it calls the next user in line. Should I just drop the queue feature and tell the concurrent users to wait a few minutes? While ignoring any messages not from the current chat_id?

How to create MUC in gtalk using python xmpppy

Can anybody help me to fix this code, I really need it, but have no idea what to do next. I need to create a groupchat and send messega to invited persons, now it is example2#gmail.com, but it does not...
Is there mistake?
#!/usr/bin/python
import sys,os,xmpp,time
jid = 'example1#gmail.com'
psw = 'psw'
jid=xmpp.protocol.JID(jid)
cl=xmpp.Client(jid.getDomain(),debug=[])
cl.connect()
cl.auth(jid.getNode(),psw)
node = jid.getNode()
domain = 'talk.google.com'
room = node + '#' + domain
nroom = room + '/' + 'Maria'
mes = xmpp.Presence(to=nroom)
cl.sendInitPresence()
cl.send(mes)
NS_MUCUSER = 'http://jabber.org/protocol/muc#user'
invite = xmpp.simplexml.Node('invite')
invite.setAttr('to', 'example2#gmail.com')
invite.setTagData('reason', 'I really need it!')
mess = xmpp.Message(to=room)
mess.setTag('x', namespace=NS_MUCUSER).addChild(node=invite)
cl.send(mess)
msg = xmpp.protocol.Message(body="Hello there!")
msg.setTo(room)
msg.setType('groupchat')
cl.send(msg)
time.sleep(1) # some older servers will not send the message if you disconnect immediately after sending
cl.disconnect()
print "Done"
According to the specs - http://xmpp.org/extensions/xep-0045.html#createroom - sending a request to join a room that doesn't exist should create that room (or MUC)
The workflow for creating and configuring such rooms is as follows:
The user sends presence to <room#service/nick> and signal his or her support
for the Multi-User Chat protocol by including extended presence information
in an empty <x/> child element qualified by the 'http://jabber.org/protocol/muc'
namespace (note the lack of an '#owner' or '#user' fragment).
If this user is allowed to create a room and the room does not yet exist, the
service MUST create the room according to some default configuration, assign the
requesting user as the initial room owner, and add the owner to the room but not
allow anyone else to enter the room (effectively "locking" the room). The initial
presence stanza received by the owner from the room MUST include extended
presence information indicating the user's status as an owner and acknowledging
that the room has been created (via status code 201) and is awaiting
configuration.
So something like this is supposed to work according to the documentation.
jid=xmpp.protocol.JID('example#gmail.com')
cl=xmpp.Client(jid.getDomain(),debug=[])
jid = xmpp.protocol.JID('example#gmail.com')
client = xmpp.Client(jid.getDomain(), debug=[])
client.connect()
client.auth(jid.getNode(), 'my secret password')
client.send(xmpp.Presence(to='room#talk.google.com/ANick')
I find my mistake. Problem is that I didn't wait enough to get answer from the server and I invited people before server was able to create a chat room. Now I wait until I get answer from server and then send invite message.

Python, IMAP and GMail. Mark messages as SEEN

I have a python script that has to fetch unseen messages, process it, and mark as seen (or read)
I do this after login in:
typ, data = self.server.imap_server.search(None, '(UNSEEN)')
for num in data[0].split():
print "Mensage " + str(num) + " mark"
self.server.imap_server.store(num, '+FLAGS', '(SEEN)')
The first problem is that, the search returns ALL messages, and not only the UNSEEN.
The second problem is that messages are not marked as SEEN.
Can anybody give me a hand with this?
Thanks!
import imaplib
obj = imaplib.IMAP4_SSL('imap.gmail.com', '993')
obj.login('user', 'password')
obj.select('Inbox') <--- it will select inbox
typ ,data = obj.search(None,'UnSeen')
obj.store(data[0].replace(' ',','),'+FLAGS','\Seen')
I think the flag names need to start with a backslash, eg: \SEEN
I am not so familiar with the imaplib but I implement this well with the imapclient module
import imapclient,pyzmail,html2text
from backports import ssl
context=ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
iobj=imapclient.IMAPClient('outlook.office365.com', ssl=True, ssl_context=context)
iobj.login(uname,pwd)# provide your username and password
iobj.select_folder('INBOX',readonly=True)# Selecting Inbox.
unread=iobj.search('UNSEEN')# Selecting Unread messages, you can add more search criteria here to suit your purpose.'FROM', 'SINCE' etc.
print('There are: ',len(unread),' UNREAD emails')
for i in unread:
mail=iobj.fetch(i,['BODY[]'])#I'm fetching the body of the email here.
mcontent=pyzmail.PyzMessage.factory(mail[i][b'BODY[]'])#This returns the email content in HTML format
subject=mcontent.get_subject()# You might not need this
receiver_name,receiver_email=mcontent.get_address('from')
mail_body=html2text.html2text(mcontent.html_part.get_payload().decode(mcontent.html_part.charset))# This returns the email content as text that you can easily relate with.
Let's say I want to just go through the unread emails, reply the sender and mark the email as read. I'd call the smtp function from here to compose and send a reply.
import smtplib
smtpobj=smtplib.SMTP('smtp.office365.com',587)
smtpobj.starttls()
smtpobj.login(uname,pwd)# Your username and password goes here.
sub='Subject: '+str(subject)+'\n\n'# Subject of your reply
msg='Thanks for your email! You're qualified for the next round' #Some random reply :(
fullmsg=sub+new_result
smtpobj.sendmail(uname,test,fullmsg)# This sends the email.
iobj.set_flags(i,['\\Seen','\\Answered'])# This marks the email as read and adds the answered flag
iobj.append('Sent Items', fullmsg)# This puts a copy of your reply in your Sent Items.
iobj.logout()
smtpobj.logout()
I hope this helps

python-xmpp and looping through list of recipients to receive and IM message

I can't figure out the problem and want some input as to whether my Python code is incorrect, or if this is an issue or design limitation of Python XMPP library. I'm new to Python by the way.
Here's snippets of code in question below. What I'd like to do is read in a text file of IM recipients, one recipient per line, in XMPP/Jabber ID format. This is read into a Python list variable.
I then instantiate an XMPP client session and loop through the list of recipients and send a message to each recipient. Then sleep some time and repeat test. This is for load testing the IM client of recipients as well as IM server. There is code to alternately handle case of taking only one recipient from command line input instead of from file.
What ends up happening is that Python does iterate/loop through the list but only last recipient in list receives message. Switch order of recipients to verify. Kind of looks like Python XMPP library is not sending it out right, or I'm missing a step with the library calls, because the debug print statements during runtime indicate the looping works correctly.
recipient = ""
delay = 60
useFile = False
recList = []
...
elif (sys.argv[i] == '-t'):
recipient = sys.argv[i+1]
useFile = False
elif (sys.argv[i] == '-tf'):
fil = open(sys.argv[i+1], 'r')
recList = fil.readlines()
fil.close()
useFile = True
...
# disable debug msgs
cnx = xmpp.Client(svr,debug=[])
cnx.connect(server=(svr,5223))
cnx.auth(user,pwd,'imbot')
cnx.sendInitPresence()
while (True):
if useFile:
for listUser in recList:
cnx.send(xmpp.Message(listUser,msg+str(msgCounter)))
print "sending to "+listUser+" msg = "+msg+str(msgCounter)
else:
cnx.send(xmpp.Message(recipient,msg+str(msgCounter)))
msgCounter += 1
time.sleep(delay)
Never mind, found the problem. One has to watch out for the newline characters at the end of a line for the elements in a list returned by file.readlines(), so I had to strip it out with .rstrip('\n') on the element when sending out message.

Categories

Resources