I've recently started learning Python API's and I've run into a problem while trying to access the HaveIBeenPwned API. I can get it to print the JSON data so I think it's a formatting problem? All other solutions seem to force me to rewrite my entire code only to find it doesn't work anyway or is incompatible.
#This program aims to provide 4 search functions by which users can test if their data is at risk.
import urllib.request as url
import json
import ast
def UsernameSearch():
print("Username search selected!")
def PasswordSearch():
print("Password search selected!")
def EmailSearch():
Username = input("Please enter the Email that's going to be searched \n: ")
def DataGetCurrent(Username):
SearchURL = "https://haveibeenpwned.com/api/v2/breachedaccount/{}".format(Username)
request = url.urlopen(url.Request(SearchURL, headers={'User-Agent' : "Mozilla/5.0"}))
data = request.read()
data = data.decode("utf-8")
json_data = json.loads(data)
return json_data[0]
Data = DataGetCurrent(Username)
a = ("Your Email address has been involved in [number] breaches: \nBreach \nTitle: {}\nWebsite: {}\nDate: {}\nInformation: {}\nLeaked Data: {}".format(Data['Title'],Data['Domain'],Data['BreachDate'],Data['Description'],Data['DataClasses']))
print(a)
def SiteSearch():
print("Website search selected!")
def loop():
try:
answer = input("There are currently 5 options: \n(1)Username search \n(2)Password search \n(3)Email search \n(4)Website search \n(5)Exit \n \n:")
if answer.upper() == "1":
UsernameSearch()
elif answer.upper() == "2":
PasswordSearch()
elif answer.upper() == "3":
EmailSearch()
elif answer.upper() == "4":
SiteSearch()
else:
print("\nThis is invalid, sorry. Please try again!\n")
loop()
except KeyboardInterrupt:
print("\nYou don't need to exit the program this way, there's an exit option; just type \"exit\"!\n")
loop()
loop()
The error it throws is:
TypeError: string indices must be integers
Edit:
Updated now and it does call some information however it only calls the first dictionary entry whereas I need it to call as many as there are (and preferably have a count variable sometimes).
I'm also having trouble selecting the "DataClasses" entry and printing the individual entities within.
All help is appreciated, thanks.
To convert a json string to dictionary, use json module (standard library):
import json
data_str = '{"index" : 5}'
json_dict = json.loads(data_str)
In your example:
import json
# ...
def DataGetCurrent(Username):
SearchURL = "https://haveibeenpwned.com/api/v2/breachedaccount/{}".format(Username)
request = url.urlopen(url.Request(SearchURL, headers={'User-Agent' : "Mozilla/5.0"}))
data = request.read()
data = data.decode("utf-8")
return json.loads(data)
EDIT
Apparently HaveIBeenPwned returns a list of dictionaries. Therefore, to get the results, you need to get the dictionary in the 0th index of the list:
def DataGetCurrent(Username):
SearchURL = "https://haveibeenpwned.com/api/v2/breachedaccount/{}".format(Username)
request = url.urlopen(url.Request(SearchURL, headers={'User-Agent' : "Mozilla/5.0"}))
data = request.read()
data = data.decode("utf-8")
json_list = json.loads(data)
return json_list[0]
EDIT 2
0th element of the list is only one of the results. To process all the results, the list itself should be returned and used accordingly.
Related
I have some code already but I got feedback on how to pass the rest of the criteria but I have no idea how to do it.
Assignment brief:
You are working in a Newspaper office that handles the reports from their journalists. You have been asked to design a program that will be used to help them send confidential reports in that others cannot read as email is not secure, we need to generate an encryption key that they can encode their scoops and documents when sent by email.
The program will need to generate the key. Encode the message, export the key, import a key from another person and decode a message. It will be a simple substitution cipher. The key needs to be made up out of all Alphanumeric Characters and some Special Characters. It will be a single key per session so you will need to save the key if you close the program otherwise you won’t be able to decode those messages used to encode them.
All projects start with planning it is the most important part that can make or break a project so ensure this is carried out correctly
Pass, Merit and Distinction Requirements
What the feedback says to do:
You were asked to import a key and export a key your program doesn't allow this so you would need to resubmit to get Pass4 and Pass6
Code I have done so far below
def run():
x=input("code or decode? ")
if x == "code":
a=list("")
import string
alpha = str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
message=input("What is your message to encode? ")
x=len(message)
y=0
z=0
for counter in range(x):
y=y+1
letter = alpha.find(message[z:y])
z=z+1
letter=letter+13
if letter > 24:
letter=letter-24
letter=alpha[letter:letter+1]
if counter != x-1:
print(letter,end="")
else:
print(letter)
x=input("type yes to go again? ")
if x == "yes":
run()
else:
input()
else:
a=list("")
import string
alpha = str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
message=input("What is your message to decode? ")
x=len(message)
y=0
z=0
for counter in range(x):
y=y+1
letter = alpha.find(message[z:y])
z=z+1
letter=letter-13
if letter < 0:
letter=24+letter
letter=alpha[letter:letter+1]
if counter != x-1:
print(letter,end="")
else:
print(letter)
x=input("again? ")
if x == "yes":
run()
else:
input()
run()
I did some research and come up with this.
You can use it as it is or edit it to meet your needs. Hope it helps.
Update.1: The longer the message, the bigger the encryption key will be. One solution for this is to use zlib.compress method in order to shrink the key, and then decompress it when needed.
Update.2: Added the export/import functionality of the encryption key using a Json file (you can of course choose other way of storing data) along with a title assigned to it, so you have the choice to either enter the title or enter the encryption key of the message for decryption. The title is just optional and for simplicity purposes, you can get rid of it if you want to. You'll also notice the code contains lots of if/else statements, that's just so you know where you currently are and what choices you have.
A GUI based would be better.
import string
import json
import os
# A list containing all characters
alpha = string.ascii_letters
def code(title, message, key = 6):
temp_dict = {}
cipher=[]
for i in range(len(alpha)):
temp_dict[alpha [i]] = alpha [(i+key)%len(alpha )]
# Generating the encryption key
for char in message:
if char in alpha :
temp = temp_dict[char]
cipher.append(temp)
else:
temp =char
cipher.append(temp)
# This code is needed to decode the expected message so make sure to save it by any method you want,
# otherwhise it'll generate a random text.
cipher= "".join(cipher)
main_data = {title : cipher}
file_name = "encryption_key.json"
if os.path.exists(file_name):
with open(file_name, "r+") as file:
data = json.load(file)
data[0].update(main_data)
file.seek(0)
json.dump(data, file)
else:
with open(file_name, "w") as file:
json.dump([main_data], file)
print("Encryption code :",cipher)
def decode(cipher, key = 6):
temp_dict = {}
for i in range(len(alpha)):
temp_dict[alpha [i]] = alpha [(i-key)%(len(alpha ))]
# Decoding the message
decoded_text = []
for char in cipher:
if char in alpha :
temp = temp_dict[char]
decoded_text.append(temp)
else:
temp = char
decoded_text.append(temp)
decoded_text = "".join(decoded_text)
return decoded_text
while True:
# There is an optional parameter (key) within the function which you can change according to your preference.
# The default value is 5 and it needs to be the same in both encode and decodefunctions.
x=input('[E]ncode or [D]ecode? answer with "e/d:" ')
if x.lower() == "e":
title = input("Enter the title of the message: ")
message = input("What is your message to encode? ")
code(title, message)
break
elif x.lower() == "d":
file_name = "encryption_key.json"
if os.path.exists(file_name):
with open(file_name, "r+") as file:
data = json.load(file)[0]
else:
print("There is no related file for decryption.")
continue
choice = input('Enter the [T]itle or the [K]ey of the message for decryption. [A]ll to decrypt everything on the file. answer with "t/k/a:" ')
if choice.lower() == 't':
title = input("Enter the title: ")
if title in data.keys():
encryption_key = data[title]
print(decode(encryption_key))
break
else:
print("There is no such title.")
elif choice.lower() == "k":
encryption_key = input("Enter the encryption code related to the message? ")
if encryption_key in data.values():
print(decode(encryption_key))
break
else:
print("There is no such encryption key.")
elif choice.lower() == "a":
decrypt_dict = {}
for k, v in data.items():
decrypt_dict[k] = decode(v)
print(decrypt_dict)
break
else:
print("There is no related file for decryption.")
else:
print("Enter a valid answer.")
This is my code below where i created two datas with first pin for example 1111 and another 2222 , where if i use the first pin from the database(ie 1111) it fetches the data from mongodb and returns login successful but if i take another pin(ie 2222) it says invalid pin. May i know what is wrong with the code?
import pymongo
import sys
cluster = pymongo.MongoClient("mongodb://localhost:27017/")
db = cluster['test']
collection = db['test']
login_data = int(input("Enter the pin:"))
result = collection.find({})
for item in result:
if login_data == item['pin']:
print("Login successfully")
break
else:
login_data != item['pin']
print("Invalid pin")
sys.exit(0)
Your loop never has chance to iterate more than once because you either break or sys.exit. Your operation can be simplified by using a filter criteria and a find_one(), no need for a for loop, e.g.
result = collection.find_one({'pin': login_data})
if result is None:
print("Invalid pin")
sys.exit(0)
print("Login successfully")
I'm writing a script in Python that prompts you to ask a question, and analyzes the AskReddit subreddit to and gives you a response. My code is:
import requests
import json
import random
#The main function that will grab a reply
def grab_reply(question):
#Navigate to the Search Reddit Url
r = requests.get('https://www.reddit.com/r/AskReddit/search.json?q=' + question + '&sort=relevance&t=all', headers = {'User-agent': 'Chrome'})
answers = json.loads(r.text) #Load the JSON file
Children = answers["data"]["children"]
ans_list= []
for post in Children:
if post["data"]["num_comments"] >= 5: #Greater then 5 or equal comments
ans_list.append (post["data"]["url"])
#If no results are found return "I have no idea"
if len(ans_list) == 0:
return "I have no idea"
#Pick A Random Post
comment_url=ans_list[random.randint(0,len(ans_list)-1)] + '.json?sort=top' #Grab Random Comment Url and Append .json to end
#Navigate to the Comments
r = requests.get(comment_url, headers = {'User-agent': 'Chrome'})
reply= json.loads(r.text)
Children = reply[1]['data']['children']
reply_list= []
for post in Children:
reply_list.append(post["data"]["body"]) #Add Comments to the List
if len(reply_list) == 0:
return "I have no clue"
#Return a Random Comment
return reply_list[random.randint(0,len(reply_list)-1)]
#Main Loop, Always ask for a question
while 1:
input("Ask me anything: ")
q=q.replace(" ", "+") #Replace Spaces with + for URL encoding
print(grab_reply(q)) #Grab and Print the Reply
After running the script in my terminal, I get this response:
NameError: name 'q' is not defined
I have managed to get most of the errors out of my script, but this one is driving me crazy. Help me out, stack overflow.
probably this will help
while True:
q = input("Ask me anything: ")
input("Ask me anything: ")
should be:
q = input("Ask me anything: ")
Since, you are not assigning the result of the input to any variable. q is undefined.
q is not defined yet. You should defined q before use it.
I'm creating a dictionary of two lists created by importing a csv file. Each of the two lists contain multiple lists of dictionaries with 8 key:value pairs per item. Each dictionary contains information about one particular item. One of the lists is information about multiple books; the other is information about multiple movies.
I need to query through the list of books by allowing a user to enter a query string which will be used to search against multiple fields in the list of books. The search needs to perform partial string matching and be case insensitive. All details for all matching books should be displayed without repeating any entries.
How do I search through a list and print the entire dictionary if it matches the query string?
# Note to self: book_collection is a list
# ORDER OF INFO in book_collection: title, author, publisher, pages, year, copies, available, ID
def query_book_collection(book_collection):
# check to see if the string is in the dictionary--partial string matching and case insensitive
query_string = input("Enter a query string to use for the search: ")
if query_string.lower() in book_collection:
print(book_collection)
else:
print("Sorry, that search returned no results.")
With the way I have it coded now, I expected it to match only full, direct matches (not partial string matches) and then print the full book_collection; however, it only ever prints "Sorry, that search returned no results."
EDIT: I have updated query_string.lower to query_string.lower().
The dictionary of books has 22 lists, and each list is a dictionary, I believe. One list (from the debugger) looks like this, for example:
: {'Title': 'My Best Book Ever', 'Author': 'Joseph Caldwell', 'Publisher': 'FPG Publishing', 'Pages': '317', 'Year': '2014', 'Copies': 3, 'Available': 3, 'ID': 17001}
The goal is to be able to search for any phrase, and if that phrase appears in the dictionary above, the entire dictionary will be printed.
Here is more of the code to give a bigger context, for those asking. The code I shared originally is just below the long print menu:
# each subset of the collection.
def load_collections():
# Load the two collections.
book_collection, max_book_id = load_collection("books.csv")
movie_collection, max_movie_id = load_collection("movies.csv")
# Check for error.
if book_collection is None or movie_collection is None:
return None, None
# Return the composite dictionary.
return {"books": book_collection, "movies": movie_collection}, max(max_book_id, max_movie_id)
# Loads a single collection and returns the data as a list. Upon error, None is returned.
def load_collection(file_name):
max_id = -1
try:
# Create an empty collection.
collection = []
# Open the file and read the field names
collection_file = open(file_name, "r")
field_names = collection_file.readline().rstrip().split(",")
# Read the remaining lines, splitting on commas, and creating dictionaries (one for each item)
for item in collection_file:
field_values = item.rstrip().split(",")
collection_item = {}
for index in range(len(field_values)):
if (field_names[index] == "Available") or (field_names[index] == "Copies") or (field_names[index] == "ID"):
collection_item[field_names[index]] = int(field_values[index])
else:
collection_item[field_names[index]] = field_values[index]
# Add the full item to the collection.
collection.append(collection_item)
# Update the max ID value
max_id = max(max_id, collection_item["ID"])
# Close the file now that we are done reading all of the lines.
collection_file.close()
# Catch IO Errors, with the File Not Found error the primary possible problem to detect.
except FileNotFoundError:
print("File not found when attempting to read", file_name)
return None
except IOError:
print("Error in data file when reading", file_name)
return None
# Return the collection.
return collection, max_id
# Display the menu of commands and get user's selection. Returns a string with the user's requested command.
# No validation is performed.
def prompt_user_with_menu():
print("\n\n********** Welcome to the Collection Manager. **********")
print("COMMAND FUNCTION")
print(" ci Check in an item")
print(" co Check out an item")
print(" ab Add a new book")
print(" am Add a new movie")
print(" db Display books")
print(" dm Display movies")
print(" qb Query for books")
print(" qm Query for movies")
print(" x Exit")
return input("Please enter a command to proceed: ")
# Create the query function. Prompts user to enter query string for a book and
# displays ALL results--partial string matching and case insensitive. Note to self: book_collection is a list
# ORDER OF INFO in book_collection: title, author, publisher, pages, year, copies, available, ID
def query_book_collection(book_collection):
# check to see if the string is in the dictionary--partial string matching and case insensitive
query_string = input("Enter a query string to use for the search: ")
if query_string.lower() in book_collection:
print(book_collection)
else:
print("Sorry, that search returned no results.")
def query_movie_collection():
pass
def check_out():
pass
def check_in():
pass
def get_item_ID():
pass
def display_collection():
pass
def add_book():
pass
def add_movie():
pass
# This is the main program function. It runs the main loop which prompts the user and performs the requested actions.
def main():
# Load the collections, and check for an error.
library_collections, max_existing_id = load_collections()
if library_collections is None:
print("The collections could not be loaded. Exiting.")
return
print("The collections have loaded successfully.")
# Display the error and get the operation code entered by the user. We perform this continuously until the
# user enters "x" to exit the program. Calls the appropriate function that corresponds to the requested operation.
operation = prompt_user_with_menu()
while operation != "x":
if operation == "ci":
check_in(library_collections)
elif operation == "co":
check_out(library_collections)
elif operation == "ab":
max_existing_id = add_book(library_collections["books"], max_existing_id)
elif operation == "am":
max_existing_id = add_movie(library_collections["movies"], max_existing_id)
elif operation == "db":
display_collection(library_collections["books"])
elif operation == "dm":
display_collection(library_collections["movies"])
elif operation == "qb":
query_book_collection(library_collections["books"])
elif operation == "qm":
query_movie_collection(library_collections["movies"])
else:
print("Unknown command. Please try again.")
operation = prompt_user_with_menu()
# Start the program.
main()
To match sub-strings you need to check each value of each book separately. This can be done with a loop and list comprehension:
found = False
for book in book_collection:
if any([query_string.lower() in str(val).lower() for val in book.values()]):
print(book_collection)
found == True
if not found:
print("Sorry, that search returned no results.")
The str(val) is required as some data in book_collection is not a string.
You could join all values in collection together before use in opearator:
def query_book_collection(book_collection):
query_string = input("Enter a query string to use for the search: ")
collection_string = ",".join(map(str, book_collection.values())).lower()
if query_string.lower() in collection_string:
print(book_collection)
else:
print("Sorry, that search returned no results.")
but the more efficient way should be adding a new property which concat all the values for querying into book_collection when you load your collection in your load_collection function. like(using python buildin csv module to read csv file):
def load_collection(file_name):
try:
with open(file_name, "r") as f:
reader = csv.DictReader(f)
collection = []
max_id = -1
for item in reader:
# add a field for querying
item["_fulltext"] = ",".join(item.values())
# casting type
item["Available"] = int(item["Available"])
item["Copies"] = int(item["Copies"])
item["ID"] = int(item["ID"])
collection.append(item)
max_id = max(max_id, item["ID"])
return collection, max_id
except FileNotFoundError:
print("File not found when attempting to read", file_name)
return None, None
except IOError:
print("Error in data file when reading", file_name)
return None, None
then, you query function would be like:
def query_book_collection(book_collection):
query_string = input("Enter a query string to use for the search: ")
if query_string.lower() in book_collection["_fulltext"]:
print(book_collection)
else:
print("Sorry, that search returned no results.")
I've been trying to create a really simple login screen on python for fun. Somewhere else in the program I have it save the entered username and password as a str (in dict format) on an external file. I can get it to check if the key-username- is correct but i cant find a way to make it check if the password entered is the password linked with the key -the value- I might of worded this weirdly but does any one have any idea how?
def login():
clear()
gap()
loginu = input("ENTER YOUR USERNAME:")
gap()
file = open("usernamesf.txt","r")
usernra = file.read()
usernr = usernra.replace("'","")
usernw = '"{' + usernr + '}"'
print (usernw)
usernwl = ast.literal_eval(usernw)
print (usernwl)
if loginu in usernwl:
gap()
loginp = input("ENTER YOUR PASSWORD:")
loginpc = usernw[loginu]
if loginp in loginpc:
print ("yay")
else:
gap()
print ("NO USERNAME FOUND...")
time.sleep(0.5)
gap()
signu = input("Would you like to sign up?")
if signu in ['yes','y','Y','Yes',' yes',' Yes',' y',' Y']:
sign()
else:
menu()
I would first recommend that you use the json library to parse your file - it is able to convert python dictionaries to string and vice versa, which is really useful.
To convert dict to str:
json.dumps(dictionary)
To convert str to dict: json.loads(string)
With this, to read the dictionary from the file, it is simply:
import json
with open("usernamesf.txt") as f:
user_dictionary = json.loads(f.read())
if loginu in user_dictionary:
password = input("ENTER YOUR PASSWORD")
if user_dictionary[username] == password:
# success
Notice how i used the with statement here for the file - this ensures that the file is properly closed by python after you are done with it - that is, after you exit the with block. You can read more about this in the official python documentation on file I/O here: https://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects