Skip to content

Commit

Permalink
Merge pull request #1 from nekooooooooo/steam-url
Browse files Browse the repository at this point in the history
Steam url
  • Loading branch information
nekooooooooo committed Mar 25, 2023
2 parents aaa48c0 + 6144527 commit f88eae8
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 82 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
tempCodeRunnerFile.python
testcode.py
.vscode
*.json
*.json
__pycache__
109 changes: 28 additions & 81 deletions steam_wishlist.py
Original file line number Diff line number Diff line change
@@ -1,83 +1,12 @@
import time
import json
import random
import os
from utils.item_filters import has_price, within_budget, under_max_price, has_discount, get_price, is_game
from utils.combinations import random_combination
from utils.input import get_input
from utils.wishlist_data import get_wishlist_from_steam, get_wishlist_from_file

CURRENCY = "PHP"

def random_combination(games, budget, min_spend=0):
"""
Generate a random combination of games that can be bought within the budget and with a minimum spend of min_spend.
:param games: list of tuples, where each tuple represents a game title, its price, and discount
:param budget: float, maximum amount that can be spent
:param min_spend: float, minimum amount that must be spent
:return: tuple, where the first element is a list of tuples representing the selected games and their prices, and
the second element is the total price of the combination
"""

# Loop until a valid combination is generated
while True:
# Select a random number of games from the list
combo = random.sample(games, random.randint(1, len(games)))

# Calculate the total price of the combination
total_price = sum(item['price'] for item in combo)

# Check if the total price is within the budget and meets the minimum spend requirement
if min_spend <= total_price <= budget:
break

return combo, total_price

def has_price(item):
return item['price']

def within_budget(item, budget):
return item['price'] < budget * 100

def under_max_price(item, max_price):
return item['price'] < max_price * 100

def has_discount(item):
return item['discount']

def get_price(item):
return item['price'] / 100.0

def is_game(item):
return item['type'] == "Game"

def get_input(prompt, type_=None, min_=None, max_=None):
"""
A function that prompts the user for an input and validates it based on the specified type, minimum and maximum values.
If the input is invalid, it will raise a ValueError with an appropriate error message.
Args:
- prompt: A string that serves as the prompt for the user input.
- type_: A type that the user input will be casted into.
- min_: A number that specifies the minimum allowable value for the user input.
- max_: A number that specifies the maximum allowable value for the user input.
Returns:
- value: The validated user input.
"""
while True:
try:
value = type_(input(prompt))
if min_ is not None and value < min_:
raise ValueError(f"{prompt} cannot be less than {min_}")
if max_ is not None and value > max_:
raise ValueError(f"{prompt} cannot be greater than {max_}")
return value
except ValueError as e:
print(f"Invalid input: {e}\n")
"""
A while loop that continues to prompt the user for an input until a valid input is given.
A try-except block that attempts to cast the user input into the specified type, and validates the input
based on the minimum and maximum allowable values. If the input is invalid, it raises a ValueError with
an appropriate error message. If the input is valid, it returns the validated user input.
"""

def print_combination(combo, total_price):
# Display the games in each combination with their prices and discounts
print("-" * 97)
Expand All @@ -92,11 +21,29 @@ def print_combination(combo, total_price):
print(f"{'Total price:':<77} {CURRENCY}{total_price:>10,.2f}\n")

def main():
# Load wishlist data from JSON file
print("Getting wishlist.json")
with open("wishlist.json", encoding="utf-8") as f:
print("wishlist.json loaded")
data = json.load(f)

print("Please choose an option:")
print("[1] Use File")
print("[2] Use Steam ID/Steam URL")
option = input("Enter your choice (1 or 2): ")
while True:
if option == "1":
# Load wishlist from file
data = get_wishlist_from_file("wishlist.json")
break
elif option == "2":
# Load wishlist data from steam
while True:
input_id = input("Enter steam id: ")
data = get_wishlist_from_steam(input_id)
if data['data']:
break
else:
print(f"Sorry, the specified ID could not be found: {input_id}")
break
else:
print("Invalid option. Please enter 1 or 2.")


print(f"Currency: {CURRENCY}")

Expand All @@ -119,7 +66,7 @@ def main():
if has_price(item) and
within_budget(item, budget) and
under_max_price(item, max_game_price) and
has_discount(item) and
# has_discount(item) and
is_game(item) and
item['gameid'][1] not in exclusions
]
Expand Down
25 changes: 25 additions & 0 deletions utils/combinations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import random

def random_combination(games, budget, min_spend=0):
"""
Generate a random combination of games that can be bought within the budget and with a minimum spend of min_spend.
:param games: list of tuples, where each tuple represents a game title, its price, and discount
:param budget: float, maximum amount that can be spent
:param min_spend: float, minimum amount that must be spent
:return: tuple, where the first element is a list of tuples representing the selected games and their prices, and
the second element is the total price of the combination
"""

# Loop until a valid combination is generated
while True:
# Select a random number of games from the list
combo = random.sample(games, random.randint(1, len(games)))

# Calculate the total price of the combination
total_price = sum(item['price'] for item in combo)

# Check if the total price is within the budget and meets the minimum spend requirement
if min_spend <= total_price <= budget:
break

return combo, total_price
2 changes: 2 additions & 0 deletions utils/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
STEAM_WISHLIST_VANITY_URL = "https://store.steampowered.com/wishlist/id/{}/wishlistdata?p={}"
STEAM_WISHLIST_ID_URL = "https://store.steampowered.com/wishlist/profiles/{}/wishlistdata?p={}"
30 changes: 30 additions & 0 deletions utils/input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
def get_input(prompt, type_=None, min_=None, max_=None):
"""
A function that prompts the user for an input and validates it based on the specified type, minimum and maximum values.
If the input is invalid, it will raise a ValueError with an appropriate error message.
Args:
- prompt: A string that serves as the prompt for the user input.
- type_: A type that the user input will be casted into.
- min_: A number that specifies the minimum allowable value for the user input.
- max_: A number that specifies the maximum allowable value for the user input.
Returns:
- value: The validated user input.
"""
while True:
try:
value = type_(input(prompt))
if min_ is not None and value < min_:
raise ValueError(f"{prompt} cannot be less than {min_}")
if max_ is not None and value > max_:
raise ValueError(f"{prompt} cannot be greater than {max_}")
return value
except ValueError as e:
print(f"Invalid input: {e}\n")
"""
A while loop that continues to prompt the user for an input until a valid input is given.
A try-except block that attempts to cast the user input into the specified type, and validates the input
based on the minimum and maximum allowable values. If the input is invalid, it raises a ValueError with
an appropriate error message. If the input is valid, it returns the validated user input.
"""
17 changes: 17 additions & 0 deletions utils/item_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
def has_price(item):
return item['price']

def within_budget(item, budget):
return item['price'] < budget * 100

def under_max_price(item, max_price):
return item['price'] < max_price * 100

def has_discount(item):
return item['discount']

def get_price(item):
return item['price'] / 100.0

def is_game(item):
return item['type'] == "Game"
84 changes: 84 additions & 0 deletions utils/wishlist_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from utils.constants import STEAM_WISHLIST_VANITY_URL, STEAM_WISHLIST_ID_URL
import json
import requests
from urllib.parse import urlparse

def get_wishlist_url(is_custom):
if is_custom:
return STEAM_WISHLIST_VANITY_URL
else:
return STEAM_WISHLIST_ID_URL

def get_wishlist_from_file(file):
print("Getting wishlist.json")
with open(f"{file}", 'r', encoding="utf-8") as f:
print("wishlist.json loaded")
data = json.load(f)
return data

def get_wishlist_from_steam(input_id):
# Extract id from input
steam_id, is_custom = get_id(input_id)

# Send GET request to Steam wishlist URL and get response content
wishlist_url = get_wishlist_url(is_custom)

# Get the first page of the wishlist data
result = []
page_num = 0
while True:
response = requests.get(wishlist_url.format(steam_id, page_num))
data = json.loads(response.content)

# Check if data is empty list
if len(data) == 0 or data.get('success') == 2:
break

for _, games in data.items():
if games['subs']:
# extract relevant data from the game data
app_id = f"app/{games['subs'][0]['id']}"
title = games['name'].replace("'", "\'")
game_type = games['type']
price = games['subs'][0]['price']
discount = games['subs'][0]['discount_pct']

# create the new dictionary
game_dict = {
"gameid": ["steam", app_id],
"title": title,
"type": game_type,
"price": price,
"discount": discount
}

# add it to the result list
result.append(game_dict)

page_num += 1

wishlist = {"data": result}
return wishlist

def get_id(input_id):
if "https://steamcommunity.com" in input_id:
# Parse the URL and get the path component
path = urlparse(input_id).path

# Split the path on the '/' character
path_parts = path.split('/')

# Check if the first part of the path is 'id' or 'profiles'
if path_parts[1] == 'id':
# Custom ID format
return path_parts[2], True

# Steam ID format
return path_parts[2], False

# it's a custom ID
if not input_id.isnumeric():
return input_id, True

return input_id, False

0 comments on commit f88eae8

Please sign in to comment.