-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathteemup.py
75 lines (62 loc) · 2.06 KB
/
teemup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import json
from datetime import datetime
from typing import TypedDict
from lxml import html
class Venue(TypedDict):
name: str
address: str | None
city: str | None
state: str | None
country: str | None
class Event(TypedDict):
title: str
url: str
description: str
starts_at: datetime
ends_at: datetime
venue: Venue | None
group_name: str | None
def parse(response_content: str) -> list[Event]:
html_tree = html.fromstring(response_content)
next_state = json.loads(html_tree.cssselect("#__NEXT_DATA__")[0].text_content())
return parse_next_state(next_state)
def parse_next_state(next_state: dict) -> list[Event]:
page_props = next_state["props"]["pageProps"]
apollo_state = page_props["__APOLLO_STATE__"]
groups = select_typename(apollo_state, "Group")
venues = select_typename(apollo_state, "Venue")
return [
Event(
title=event["title"],
url=event["eventUrl"],
description=event["description"],
starts_at=datetime.fromisoformat(event["dateTime"]),
ends_at=datetime.fromisoformat(event["endTime"]),
venue=(
parse_venue(venues[event["venue"]["__ref"]]) if event["venue"] else None
),
group_name=groups[event["group"]["__ref"]]["name"],
)
for event in select_typename(apollo_state, "Event").values()
if event["status"] == "ACTIVE"
]
def select_typename(apollo_state: dict, typename: str) -> dict[str, dict]:
return {
key: value
for key, value in apollo_state.items()
if value["__typename"] == typename
}
def parse_venue(venue: dict) -> Venue | None:
data = {}
for key in ["name", "address", "city", "state", "country"]:
data[key] = venue.get(key) or None
if (
data["name"]
and data["name"].lower() == "online event"
and data["address"] is None
and data["city"] is None
and data["state"] is None
and data["country"] is None
):
return None
return Venue(**data)