Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import argparse
- import requests
- import os
- import sys
- import csv
- import time
- def format_price(price):
- return "$" + f"{price:,}" if isinstance(price, int) else price
- def query_market(item_id, api_key):
- all_listings = []
- offset = 0
- page_size = 100 # Torn usually returns ~100 listings per page
- global_seen_uids = set()
- print(f"Querying Torn API v2 for item ID {item_id}...")
- while True:
- url = f"https://api.torn.com/v2/market?selections=itemMarket&id={item_id}&offset={offset}&key={api_key}"
- try:
- response = requests.get(url, timeout=10)
- except Exception as e:
- print(f"ERROR: Failed to query API: {e}")
- sys.exit(1)
- if response.status_code != 200:
- print(f"ERROR: API returned status code {response.status_code}")
- print(response.text)
- sys.exit(1)
- data = response.json()
- if "error" in data:
- print(f"Torn API ERROR: {data['error']}")
- sys.exit(1)
- item_info = data.get("itemmarket", {}).get("item", {})
- listings = data.get("itemmarket", {}).get("listings", [])
- if offset == 0:
- print(f"\nItem: {item_info.get('name', 'Unknown')} (ID: {item_info.get('id', item_id)})")
- if not listings:
- print("No more listings found.")
- break
- for listing in listings:
- price = listing.get("price", "-")
- item_id = item_info.get("id", "-")
- stats = listing.get("item_details", {}).get("stats", {})
- quality = stats.get("quality", None)
- uid = listing.get("item_details", {}).get("uid", None)
- if uid and uid not in global_seen_uids:
- all_listings.append({
- "ItemID": item_id,
- "UID": uid,
- "Price": price,
- "Quality": quality
- })
- global_seen_uids.add(uid)
- if len(listings) < page_size:
- print("Last page reached.")
- break
- offset += page_size
- time.sleep(0.5)
- return all_listings
- def compute_higher_quality_min_prices(listings, percent):
- listings_sorted = sorted(listings, key=lambda x: x["Quality"] if isinstance(x["Quality"], (int, float)) else 0.0, reverse=True)
- min_price_above = None
- results = []
- for i, listing in enumerate(listings_sorted):
- result = listing.copy()
- if min_price_above is None:
- result[">Quality Min Price"] = "-"
- result["PctChange"] = ""
- else:
- result[">Quality Min Price"] = format_price(min_price_above)
- current_price = listing["Price"]
- if isinstance(current_price, int) and current_price < min_price_above:
- pct_increase = ((min_price_above - current_price) / current_price) * 100
- this_quality = listing["Quality"] if isinstance(listing["Quality"], (int, float)) else 0.0
- min_quality_allowed = this_quality - percent
- lowest_price_in_window = None
- for candidate in listings_sorted:
- candidate_quality = candidate["Quality"] if isinstance(candidate["Quality"], (int, float)) else 0.0
- if candidate_quality < min_quality_allowed:
- continue
- candidate_price = candidate["Price"]
- if candidate["UID"] != listing["UID"] and isinstance(candidate_price, int):
- if lowest_price_in_window is None or candidate_price < lowest_price_in_window:
- lowest_price_in_window = candidate_price
- if lowest_price_in_window is not None and lowest_price_in_window != current_price:
- price_diff = current_price - lowest_price_in_window
- price_diff_prefix = "+" if price_diff >= 0 else "-"
- result["PctChange"] = f"(+{pct_increase:.1f}%|{price_diff_prefix}{format_price(abs(price_diff))})"
- else:
- result["PctChange"] = f"(+{pct_increase:.1f}%)"
- else:
- result["PctChange"] = ""
- price = listing["Price"]
- if isinstance(price, int):
- if (min_price_above is None) or (price < min_price_above):
- min_price_above = price
- results.append(result)
- return results
- def print_listings(listings):
- print("\n{:<12} {:>15} {:>10} {:>20} {:>25}".format(
- "Item ID", "Price", "Quality", ">Quality Min Price", "PctChange"
- ))
- print("-" * 90)
- for listing in listings:
- quality_display = f"{listing['Quality']:.2f}" if isinstance(listing["Quality"], (float, int)) else "0.00"
- min_price_display = listing[">Quality Min Price"]
- pct_change_display = listing["PctChange"]
- print("{:<12} {:>15} {:>10} {:>20} {:>25}".format(
- listing["ItemID"],
- format_price(listing["Price"]),
- quality_display,
- min_price_display,
- pct_change_display
- ))
- def main():
- parser = argparse.ArgumentParser(description="Query Torn v2 market listings for an item (with paging, quality sort, higher quality min price).")
- parser.add_argument("--id", type=int, required=True, help="Item ID to query.")
- parser.add_argument("--csv", type=str, help="Optional CSV output filename.")
- parser.add_argument("--percent", type=float, default=10.0, help="Fixed quality delta to compare lower quality prices (default 10.0 quality points).")
- args = parser.parse_args()
- api_key = os.environ.get("TORN_API_KEY")
- if not api_key:
- print("ERROR: Environment variable TORN_API_KEY is not set.")
- sys.exit(1)
- all_listings = query_market(args.id, api_key)
- if not all_listings:
- print("No listings found.")
- sys.exit(0)
- enriched_listings = compute_higher_quality_min_prices(all_listings, args.percent)
- print_listings(enriched_listings)
- if args.csv:
- fieldnames = ["ItemID", "Price", "Quality", ">Quality Min Price", "PctChange"]
- with open(args.csv, mode="w", newline="") as csvfile:
- writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
- writer.writeheader()
- writer.writerows(enriched_listings)
- print(f"\nCSV written to {args.csv}")
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement