92 lines
2.9 KiB
Python
92 lines
2.9 KiB
Python
from datetime import datetime
|
|
|
|
import requests
|
|
|
|
from app.config import settings
|
|
from app.models import RegionScope, WatchType
|
|
|
|
|
|
class TicketmasterProvider:
|
|
base_url = "https://app.ticketmaster.com/discovery/v2/events.json"
|
|
source_name = "ticketmaster"
|
|
|
|
def is_configured(self) -> bool:
|
|
return bool(settings.ticketmaster_api_key)
|
|
|
|
def search_events(
|
|
self,
|
|
term: str,
|
|
watch_type: WatchType,
|
|
region_scope: RegionScope,
|
|
) -> list[dict]:
|
|
if not self.is_configured():
|
|
return []
|
|
|
|
params = {
|
|
"apikey": settings.ticketmaster_api_key,
|
|
"keyword": term,
|
|
"locale": "*",
|
|
"size": 50,
|
|
"sort": "date,asc",
|
|
"countryCode": "DE",
|
|
}
|
|
|
|
if region_scope == RegionScope.hamburg:
|
|
params["city"] = "Hamburg"
|
|
|
|
response = requests.get(self.base_url, params=params, timeout=30)
|
|
response.raise_for_status()
|
|
payload = response.json()
|
|
items = payload.get("_embedded", {}).get("events", [])
|
|
results: list[dict] = []
|
|
|
|
normalized_term = term.casefold()
|
|
for item in items:
|
|
title = item.get("name", "")
|
|
attractions = item.get("_embedded", {}).get("attractions", [])
|
|
attraction_names = [entry.get("name", "") for entry in attractions]
|
|
|
|
if watch_type == WatchType.artist:
|
|
haystack = " ".join(attraction_names + [title]).casefold()
|
|
if normalized_term not in haystack:
|
|
continue
|
|
elif normalized_term not in title.casefold():
|
|
continue
|
|
|
|
dates = item.get("dates", {}).get("start", {})
|
|
local_date = dates.get("localDate")
|
|
local_time = dates.get("localTime", "20:00:00")
|
|
|
|
event_date = None
|
|
if local_date:
|
|
try:
|
|
event_date = datetime.fromisoformat(f"{local_date}T{local_time}")
|
|
except ValueError:
|
|
event_date = datetime.fromisoformat(f"{local_date}T20:00:00")
|
|
|
|
venue = (
|
|
item.get("_embedded", {})
|
|
.get("venues", [{}])[0]
|
|
)
|
|
|
|
results.append(
|
|
{
|
|
"external_id": item.get("id"),
|
|
"title": title,
|
|
"matched_term": term,
|
|
"venue_name": venue.get("name"),
|
|
"city": venue.get("city", {}).get("name"),
|
|
"country_code": venue.get("country", {}).get("countryCode"),
|
|
"event_date": event_date,
|
|
"ticket_url": item.get("url"),
|
|
"image_url": next(
|
|
(image.get("url") for image in item.get("images", []) if image.get("url")),
|
|
None,
|
|
),
|
|
"raw_payload": item,
|
|
}
|
|
)
|
|
|
|
return results
|
|
|