Python: Is there a way to use a set amount of inputs? - python-3.x

I have this simple python webhook sender for Discord with 3 inputs for the URLs.
I want to figure out how to make on option to use 1, 2 or all 3 of the inputs. Is that possible?
I'm not the most experienced person so please answer in some detail.
from discord_webhook import DiscordWebhook
print('paste webhook 1')
url1 = input()
print('paste webhook 2')
url2 = input()
print('paste webhook 3')
url3 = input()
print('what do you want them to say?')
content = input()
print('sending...')
while True:
webhook_urls = [url1, url2, url3]
webhook = DiscordWebhook(url=webhook_urls, content=content)
response = webhook.execute()

I'm assuming you would initially ask them how many webhooks they want to input
from discord_webhook import DiscordWebhook
def ask_for_count():
webhooks_num = input('How many webhooks would you like to use? (1, 2 or 3) \n')
# Firstly, you don't need a seperate print statement to ask for input
# it can be in the input function and if you need the answer in a new line,
# use the escape character /n which creates a new line after execution.
return webhooks_num
def get_webhooks():
if count == '1':
url1 = input('paste webhook 1 \n')
webhook_urls.append(url1)
return # The return ends function as soon as the urls are added to the list.
elif count == '2':
url1 = input('paste webhook 1 \n')
url2 = input('paste webhook 2 \n')
webhook_urls.append(url1)
webhook_urls.append(url2)
return
elif count == '3':
url1 = input('paste webhook 1 \n')
url2 = input('paste webhook 2 \n')
url3 = input('paste webhook 3 \n')
webhook_urls.append(url1)
webhook_urls.append(url2)
webhook_urls.append(url3)
return
else:
print('Please enter a valid choice.')
def get_content():
answer = input('what do you want them to say? \n')
print('sending...')
return answer
webhook_urls = []
# List is intentionally outside of the function,
# so that you don't create an empty list everytime the function is called.
# Now you call the functions defined above to execute in order.
count = ask_for_count()
get_webhooks()
content = get_content()
while True:
webhook = DiscordWebhook(url=webhook_urls, content=content)
response = webhook.execute()
So, basically, as soon as the program runs, the user is asked for the number of webhooks needed and then based on the input (out of 3), they get asked for the webhooks which are then added to the webhook_urls list initiated earlier.
After that, the user is asked for the content and the while loop initiates, executing the code normally, using the function outputs and the list initiated earlier; webhook_urls.
Hope I helped.

Related

how to use tweepy to tweet a variable

I'm using jupyter notebook to make a code that reads a trump tweets database and trains to make its own tweets based on the ones on the db. I want to use tweepy to tweet the output however I can't seem to find a way to tweet it.
I tried adding the status update command at the end of the code
def generate_w_seed2(sentence,diversity):
sentence = sentence[0:maxlen]
generated = ''
generated += sentence
sys.stdout.write(generated)
for i in range(120):
x_pred = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x_pred[0, t, char_indices[char]] = 1.
preds = modelo.predict(x_pred, verbose=0)[0]
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
generated += next_char
sentence = sentence[1:] + next_char
sys.stdout.write(next_char)
sys.stdout.flush()
print()
return
for s in random.sample(list(text),1):
for diversity in [0.5]:
generate_w_seed2(s,diversity)
print()
api.update_status(generate_w_seed2(s,diversity))
But I get the following error:
TweepError: [{'code': 170, 'message': 'Missing required parameter: status.'}]
I have also tried placing the variable in a function (named estado) and while it didn't read the variable it tweeted the following:
<function estado at 0x00000000E59DC6A8>

Refactor out long if-else block using a mapping of two columns from a pandas DataFrame

I am building a chatbot using Selenium and it has two short answers by now. When user sends '/help' the bot sends 'You asked for help', when user sends '/more', bot sends 'You asked more'...
def conversation():
if last_msg() == '/help':
msg = 'You asked help'
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys(msg)
elif last_msg() =='/more':
msg = 'You asked more'
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys(msg)
else:
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys('Sorry, input not listed')
time.sleep(1)
driver.find_element_by_class_name("_3M-N-").click()
How can i escalate this using pandas? Assuming i have an csv with 2 columns, one named 'msg' and the other 'reply'. I would like to add many rows to this csv, without needing to change the code.
msg reply
0 /help you_asked_for_help
1 /more you_asked_for_more
df_with_reply = pd.read_csv(r'C:\Users...')
How can i make this:
if last_msg() == '/help':
msg = 'You asked help'
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys(msg)
elif last_msg() =='/more':
msg = 'You asked more'
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys(msg)
Turn into this:
if last_msg() == IS IN df COLUMN 'msg'
RETURN ACCORDING TEXT FROM df COLUMN 'reply' as X
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys(X)
else:
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys('Sorry, input not listed')
Setup a default dictionary mapping messages to replies.
from collections import defaultdict
d = defaultdict(lambda: 'Sorry, input not listed')
d.update(df.set_index('msg')['reply'].to_dict())
Now d can be accessed inside your function:
def conversation():
input_field = driver.find_element_by_class_name("_3u328")
input_field.send_keys(d[last_msg()])
time.sleep(1)
driver.find_element_by_class_name("_3M-N-").click()

Python 3: Multiple mails being sent using a 'for loop' instead of single mail

I have the below script which is perfectly working, but when I read the status of the Cisco devices using a for loop and send mail using the user defined function send_mail(), I am receiving two mails instead of one mail, any suggestions to get a single mail, will be greatly appreciated:
username = 'cisco'
password = 'cisco'
hosts = ['10.0.10.100','10.0.10.101']
platform = 'cisco_ios'
def send_mail():
fromaddr = "#gmail.com"
toaddr = "#hotmail.com"
msg = MIMEMultipart()
msg['From'] = '#gmail.com'
msg['To'] = '#hotmail.com'
msg['Subject'] = "This is Health check"
msg.attach(MIMEText(status, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
for host in hosts:
#print(host)
connect = ConnectHandler(device_type=platform, ip=host, username=username, password=password)
output = connect.send_command('terminal length 0', expect_string=r'#')
output = connect.send_command('enable',expect_string=r'#')
host_name = connect.send_command('show run | in hostname',expect_string=r'#')
interface_status = connect.send_command(f'show ip int brief',expect_string=r'#')
#print(interface_status)
old_stdout = sys.stdout
interface_result = StringIO()
sys.stdout = interface_result
sys.stdout = old_stdout
data = pd.read_fwf(StringIO(interface_status), widths=[27, 16, 3, 7, 23, 8])
status = " "
for index, row in data.iterrows():
if row[4] == 'administratively down' or row[4] == 'down':
log = (f"\nInterface {row[0]} is down in {host_name}\n")
status += log
bgp_status = connect.send_command('show ip bgp summary | be N',expect_string=r'#')
old_stdout = sys.stdout
bgp_result = StringIO()
sys.stdout = bgp_result
sys.stdout = old_stdout
bgp_data = pd.read_fwf(StringIO(bgp_status), delim_whitespace=True, header=None)
for index, row in bgp_data.iterrows():
if row[9] == 'Down' or row[9] == 'Idle' or row[9] == 'Active':
bgp = (f"\nNeighbor {row[0]} is down in {host_name}\n")
status += bgp
send_mail()
I think I understand what your issue is. In short, you are calling send_mail() within each for loop, whereas you actually want to collect statuses for each host, and then send a final status report as one email. This is a short example to illustrate how you might do this - obviously you will have to adapt your code accordingly.
A couple of points:
Rather than having send_mail rely on a global status variable, pass in a status argument. This helps decouple functions from each other.
You might want to collect statuses for each host in a list, and then combine them in a logical manner when sending your status email.
String concatenation is slow. Better to build a list of strings, and join them using the string join function.
Here is some example code:
hosts = ['10.0.10.100','10.0.10.101']
def send_mail(status=''):
'''A placeholder function for testing'''
print("Sending email:\n{status}".format(status=status))
return
status_for_hosts = []
for host in hosts:
status_list = []
# An example of how you might collect statuses for a host
status_list.append("Host {host_ip} is up".format(host_ip=host))
# Use join() instead of string concatenation
full_status = ''.join(status_list)
status_for_hosts.append(full_status)
send_mail(status='\n'.join(status_for_hosts))

tweepy It won't follow some of the tweets

seems like for some of the tweets with the keyword 'follow'
it will follow and for some of them it wont...
other than that it works fine(I didn't notice something else)
can someone pinpoint where is the problem?
class Listener():
def search(self, twts):
global numoftwts
for i in twts:
names = ['follow', 'following']
txt = i.text.lower()
if not any(k in txt for k in keywords) or any(k in txt for k in bannedwords):
continue
if not self.is_user_bot_hunter(str(i.author.screen_name)):
if not i.retweeted:
try:
print("Trying to retweet status_id:{}".format(i.id))
res = api.retweet(i.id)
if res.retweeted:
api.create_favorite(i.id)
print('retweeted', numoftwts, 'times', '-',
str(datetime.datetime.fromtimestamp(time.time()).strftime('%d-%m-%Y %H:%M:%S')))
print(i.text)
print('\n')
else:
print("retweet failed")
if any(c in txt for c in names):
# print("Trying to follow something")
# if hasattr(i, 'retweeted_status'):
# print("trying to fetch user_id")
user_id = i.retweeted_status.user.id_str
res = api.create_friendship(user_id)
res = api.get_user(user_id)
if res.following:
print("Successfully followed :{}".format(user_id))
print('\n')
except Exception as e:
print("Exception:".format(str(e)))
continue
sleep(600)
def run(self):
for eachkey in keywords:
tweets = api.search(q=eachkey, result_type='mixed', lang='en')
self.search(tweets)
if __name__ == '__main__':
while True:
r = Listener()
r.run()
where did I go wrong?
AttributeError: 'Status' object has no attribute 'retweeted_status'
> c:\users\x\desktop\twitterbot\twtbotcopy.py(64)search()
-> user_id = i.retweeted_status.user.id_str
(Pdb) n
> c:\users\x\desktop\twitterbot\twtbotcopy.py(70)search()
-> except Exception as e:
(Pdb) n
If your getting any error where you are unable to get tweets from a particular user then use:
try:
specific_tweets = tweepy.Cursor(api.search, tweet_mode='extended', q= <some query>, lang='en').items(500)
except tweepy.error.TweepError:
pass
And if you want to access the retweeted attribute of a tweet then do this:
if hasattr(tweet, 'retweeted_status'):
extracted_author = tweet.retweeted_status.user.screen_name
else: extracted_author = tweet.user.screen_name
basically check whether hasattr(tweet, 'retweeted_status') of a tweet is true or not. It checks whether the tweet has the attribute named "retweeted_status"
AttributeError: 'Status' object has no attribute 'retweeted_status'
-> user_id = i.retweeted_status.user.id_str
It means that you want to get the user ID of a retweet, for a tweet that is not a retweet.
I you want to know if a tweet is a RT, the test is :
if hasattr(tweet, 'retweeted_status'):
# this tweet is a RT

urllib error: Too many requests

The below python program asks the user for two reddit usernames and compares their score.
import json
from urllib import request
def obtainKarma(users_data):
users_info = []
for user_data in users_data:
data = json.load(user_data)
posts = data["data"]["children"]
num_posts = len(posts)
scores = []
comments = []
for post_id in range(num_posts):
score = posts[post_id]["data"]["score"]
comment = posts[post_id]["num_comments"]
scores.append(score)
comments.append(comment)
users_info.append((scores,comments))
user_id = 0
for user_info in users_info:
user_id+=1
print("User"+str(user_id))
for user_attr in user_info:
print(user_attr)
def getUserInfo():
count = 2
users_data = []
while count:
count = count + 1
username = input("Please enter username:\n")
url = "https://reddit.com/user/"+username+".json"
try:
user_data = request.urlopen(url)
except:
print("No such user.\nRetry Please.\n")
count = count + 1
raise
users_data.append(user_data)
obtainKarma(users_data)
if __name__ == '__main__':
getUserInfo()
However, when I run the program and enter a username, I get an error:
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 429: Too Many Requests
I tried looking for similar issues but none of them satisfied to solve this specific issue. Looking at the error, it would make sense to say that the URL includes an amount of data that exceeds a specific limit? But that still sounds absurd because it is not that much of a data.
Thanks.
The problem seems to be resolved when you supply a User-Agent with your request.
import json
from urllib import request
def obtainKarma(users_data):
users_info = []
for user_data in users_data:
data = json.loads(user_data) # I've changed 'json.load' to 'json.loads' because you want to parse a string, not a file
posts = data["data"]["children"]
num_posts = len(posts)
scores = []
comments = []
for post_id in range(num_posts):
score = posts[post_id]["data"]["score"]
comment = posts[post_id]["data"]["num_comments"] # I think you forgot '["data"]' here, so I added it
scores.append(score)
comments.append(comment)
users_info.append((scores,comments))
user_id = 0
for user_info in users_info:
user_id+=1
print("User"+str(user_id))
for user_attr in user_info:
print(user_attr)
def getUserInfo():
count = 2
users_data = []
while count:
count = count + 1
username = input("Please enter username:\n")
url = "https://reddit.com/user/"+username+".json"
user_data = None
try:
req = request.Request(url)
req.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)')
resp = request.urlopen(req)
user_data = resp.read().decode("utf-8")
except Exception as e:
print(e)
print("No such user.\nRetry Please.\n")
count = count + 1
raise # why raise? --> Program will end if user is not found
if user_data:
print(user_data)
users_data.append(user_data)
obtainKarma(users_data)
if __name__ == '__main__':
getUserInfo()
There were still other issues with your code:
You should not write json.load(user_data), because you are parsing a string. So I changed it to use json.loads(user_data).
The Python documentation for json.loads states:
Deserialize s (a str instance containing a JSON document) to a Python object using this conversion table.
And in the code comment = posts[post_id]["num_comments"], I think you forgot to index on 'data', so I changed it to comment = posts[post_id]["data"]["num_comments"]
And why are you raising the exception in the except-block? This will end the program, however it seems that you expect it not to, from looking at the following code:
print("No such user.\nRetry Please.\n")

Resources