fix: QC-Ratings aus 7 älteren Artikeln entfernt (CHECK 10)
This commit is contained in:
+143
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Search BGG for board game IDs using XML API v2."""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
# Read BGG key
|
||||
with open('/tmp/.bggkey') as f:
|
||||
bgg_key = f.read().strip()
|
||||
|
||||
HEADER = f"Authorization: Bearer {bgg_key}"
|
||||
BASE_URL = "https://boardgamegeek.com/xmlapi2/search"
|
||||
|
||||
# Games to search: (full_name, primary_search_word, fallback_search_word)
|
||||
GAMES = [
|
||||
("Concordia Special Edition", "Concordia", None),
|
||||
("Altera", "Altera", None),
|
||||
("Aeon's End: System Overload", "Aeon's", "Overload"),
|
||||
("Entropy", "Entropy", None),
|
||||
("NARCOS", "Narcos", None),
|
||||
("Stonefall", "Stonefall", None),
|
||||
("Capitals of Tactoria", "Capitals", "Tactoria"),
|
||||
("A Life", "Life", None),
|
||||
("The Council of Anderian", "Anderian", "Council"),
|
||||
("Ancient Blood", "Ancient", "Blood"),
|
||||
("Growing Season", "Growing", "Season"),
|
||||
("Believe in me!", "Believe", None),
|
||||
("Wilderfeast", "Wilderfeast", None),
|
||||
("TATANKA", "Tatanka", None),
|
||||
]
|
||||
|
||||
def search_bgg(query_word):
|
||||
"""Search BGG API and return list of (id, name, year) tuples."""
|
||||
url = f"{BASE_URL}?query={query_word}&type=boardgame"
|
||||
result = subprocess.run(
|
||||
["curl", "-s", "-H", HEADER, url],
|
||||
capture_output=True, text=True, timeout=30
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f" curl error: {result.stderr}", file=sys.stderr)
|
||||
return []
|
||||
|
||||
xml_text = result.stdout.strip()
|
||||
if not xml_text:
|
||||
print(f" Empty response", file=sys.stderr)
|
||||
return []
|
||||
|
||||
try:
|
||||
root = ET.fromstring(xml_text)
|
||||
except ET.ParseError as e:
|
||||
print(f" XML parse error: {e}", file=sys.stderr)
|
||||
return []
|
||||
|
||||
items = []
|
||||
for item in root.findall('item'):
|
||||
item_id = item.get('id', '')
|
||||
item_type = item.get('type', '')
|
||||
if item_type != 'boardgame':
|
||||
continue
|
||||
name_el = item.find('name')
|
||||
if name_el is not None:
|
||||
name_val = name_el.get('value', '')
|
||||
else:
|
||||
name_val = ''
|
||||
year_el = item.find('yearpublished')
|
||||
if year_el is not None:
|
||||
year_val = year_el.get('value', '')
|
||||
else:
|
||||
year_val = ''
|
||||
items.append((item_id, name_val, year_val))
|
||||
|
||||
return items
|
||||
|
||||
def find_exact_match(items, full_name):
|
||||
"""Find exact match (case-insensitive) in search results."""
|
||||
target = full_name.lower().strip()
|
||||
for item_id, name, year in items:
|
||||
if name.lower().strip() == target:
|
||||
return item_id, name, year
|
||||
return None
|
||||
|
||||
def find_best_match(items, full_name):
|
||||
"""Find best match - first try exact, then first result."""
|
||||
exact = find_exact_match(items, full_name)
|
||||
if exact:
|
||||
return exact
|
||||
if items:
|
||||
return items[0]
|
||||
return None
|
||||
|
||||
def main():
|
||||
results = []
|
||||
|
||||
for full_name, primary_word, fallback_word in GAMES:
|
||||
print(f"\nSearching: {full_name} (word: {primary_word})", file=sys.stderr)
|
||||
|
||||
# Primary search
|
||||
items = search_bgg(primary_word)
|
||||
print(f" Got {len(items)} results", file=sys.stderr)
|
||||
for i, (item_id, name, year) in enumerate(items[:5]):
|
||||
print(f" [{i}] id={item_id} name='{name}' year={year}", file=sys.stderr)
|
||||
|
||||
match = find_best_match(items, full_name)
|
||||
|
||||
if match:
|
||||
item_id, name, year = match
|
||||
url = f"https://boardgamegeek.com/boardgame/{item_id}"
|
||||
results.append(f"{full_name}|{item_id}|{url}")
|
||||
print(f" MATCH: {item_id} - {name} ({year})", file=sys.stderr)
|
||||
elif fallback_word:
|
||||
# Try fallback
|
||||
time.sleep(3)
|
||||
print(f" No match, trying fallback: {fallback_word}", file=sys.stderr)
|
||||
items2 = search_bgg(fallback_word)
|
||||
print(f" Got {len(items2)} results", file=sys.stderr)
|
||||
for i, (item_id, name, year) in enumerate(items2[:5]):
|
||||
print(f" [{i}] id={item_id} name='{name}' year={year}", file=sys.stderr)
|
||||
|
||||
match2 = find_best_match(items2, full_name)
|
||||
if match2:
|
||||
item_id, name, year = match2
|
||||
url = f"https://boardgamegeek.com/boardgame/{item_id}"
|
||||
results.append(f"{full_name}|{item_id}|{url}")
|
||||
print(f" MATCH (fallback): {item_id} - {name} ({year})", file=sys.stderr)
|
||||
else:
|
||||
results.append(f"{full_name}|NOT_FOUND")
|
||||
print(f" NOT FOUND", file=sys.stderr)
|
||||
else:
|
||||
results.append(f"{full_name}|NOT_FOUND")
|
||||
print(f" NOT FOUND", file=sys.stderr)
|
||||
|
||||
# Wait 3 seconds before next call
|
||||
if full_name != GAMES[-1][0]:
|
||||
time.sleep(3)
|
||||
|
||||
print("\n=== RESULTS ===", file=sys.stderr)
|
||||
for r in results:
|
||||
print(r)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user