Skip to content
Open
Changes from all commits
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
93 changes: 93 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import datetime
from hashlib import md5
from os import getenv
from time import time_ns

from requests import get
Comment on lines +4 to +6
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why the gap here? It would be good to keep all imports together unless there is some specific reason not to

from dotenv import load_dotenv

load_dotenv()

PUBLIC_API_KEY = getenv("MARVEL_PUBLIC_API_KEY")
PRIVATE_API_KEY = getenv("MARVEL_PRIVATE_API_KEY")
Comment on lines +11 to +12
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice use of keeping your environment variables secure! Good DevOps practice!


SEARCH_URL = "https://gateway.marvel.com:443/v1/public/characters"
DETAILS_URL = "https://gateway.marvel.com:443/v1/public/characters/{id}"
Comment on lines +14 to +15
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a way you could have just added the {id} onto the first url rather than having to create two urls?


PAGE_SIZE = 20

while True:
timestamp = str(time_ns())
key_hash = md5(f"{timestamp}{PRIVATE_API_KEY}{PUBLIC_API_KEY}".encode("utf-8")).hexdigest()
default_params = {
'apikey': PUBLIC_API_KEY,
'ts': timestamp,
'hash': key_hash,
}

name = input("What Marvel character? ")

keep_searching = True
ID = None
offset = 0

while keep_searching:
Comment on lines +19 to +34
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A nested while statement could be suggested to not be best practice as it can get messy (see comment below on nested if/else statements)


print("Trying to find that character . . .")

search_params = {
**default_params,
'nameStartsWith': name,
'limit': PAGE_SIZE,
'offset': offset
}

res = get(SEARCH_URL, search_params).json()

# refer to https://developer.marvel.com/docs#!/public/getCreatorCollection_get_0 for data shape

data = res['data']
total = data['total']
offset = data['offset']

characters = data['results']
Comment on lines +49 to +53
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Have you thought about using .get() instead of []. This would just ensure that an error wouldn't be thrown if that specific section wasn't there.


if total == 0:
print("Couldn't find any characters by this name...")
keep_searching = False
elif total == 1:
ID = characters[0]['id']
keep_searching = False
else:
IDs = []
i = 0
print(f"Please select a character)")
for character in characters:
i += 1
print(f"- {i}: {character['name']}")
IDs.append(character['id'])

choice = input(f"Which ID? (1-{len(characters)}), or 'n' for next page ")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is pretty cool functionality! Awesome job!


if choice == "n":
if offset + PAGE_SIZE >= total:
print("There are no more pages...")
keep_searching = False
else:
offset += PAGE_SIZE
else:
index = int(choice) - 1
ID = IDs[index]
keep_searching = False
found_a_character = True
Comment on lines +55 to +82
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

At this point there is many nested if/else if statements, on top of the nested while statements, this makes following the logic difficult, especially to understand which branch you end up in. If there are nested if/else statements, then sometimes it is best to put everything into a function and use return statements.


if ID: # if any previous branch resulted in a result
print("Retrieving details . . .")

res = get(DETAILS_URL.format(id=ID), params=default_params).json()

character = res['data']['results'][0] # should only be one returned

print(f"Name: {character['name']}")
print(f"Bio: {character['description']}")
Comment on lines +91 to +92
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice functionality to print both the name and the description!