Skip to content

Commit 885b886

Browse files
Merge pull request #7038 from bnchi/change-meetup-gql
Migrate to the new meetup API
2 parents 724540e + 80c4255 commit 885b886

File tree

2 files changed

+46
-140
lines changed

2 files changed

+46
-140
lines changed

tools/events/meetup-automation/event.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,15 @@ def __init__(self, **kwargs) -> None:
128128
self.date_time_str = node["dateTime"]
129129
self.event_url_str = node["eventUrl"]
130130

131-
venue = node["venue"]
131+
venues = node["venues"]
132+
133+
# Get the first venue
134+
venue = venues[0]
135+
132136
self.venue_type = venue["venueType"]
133137
# TODO: do we need these lat longs?
134138
self.lat = venue["lat"]
135-
self.long = venue["lng"]
139+
self.long = venue["lon"]
136140
self.event_location = Location(venue["city"], venue["state"], venue["country"])
137141

138142
def to_event(self, group_url: str) -> Event:

tools/events/meetup-automation/generate_events_meetup.py

Lines changed: 40 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,44 @@
99

1010
logger = logging.getLogger(__name__)
1111

12+
_EVENT_LISTING_QUERY = """\
13+
query($first: Int = 20, $urlName: String!) {
14+
groupByUrlname(urlname: $urlName) {
15+
events(first: $first, sort: ASC) {
16+
pageInfo {
17+
hasNextPage
18+
endCursor
19+
}
20+
edges {
21+
node {
22+
id
23+
group {
24+
name
25+
city
26+
state
27+
country
28+
}
29+
title
30+
dateTime
31+
eventUrl
32+
venues {
33+
lat
34+
lon
35+
city
36+
state
37+
country
38+
venueType
39+
}
40+
}
41+
}
42+
}
43+
}
44+
}
45+
"""
1246

1347
class TwirMeetupClient:
1448
AUTH_ENDPOINT = "https://secure.meetup.com/oauth2/access"
15-
GQL_ENDPOINT = "https://api.meetup.com/gql"
49+
GQL_ENDPOINT = "https://api.meetup.com/gql-ext"
1650

1751
def __init__(self) -> None:
1852
self._access_token = None
@@ -52,154 +86,22 @@ def _get_access_token(self):
5286
return self._access_token
5387

5488
def _build_event_listing_gql_query(self, group_url_name: str) -> dict:
55-
return {
56-
"query": """
57-
query ($urlName: String!, $searchEventInput: ConnectionInput!) {
58-
groupByUrlname(urlname: $urlName) {
59-
upcomingEvents(input: $searchEventInput, sortOrder: ASC) {
60-
pageInfo {
61-
hasNextPage
62-
endCursor
63-
}
64-
edges {
65-
node {
66-
id
67-
group {
68-
name
69-
city
70-
state
71-
country
72-
}
73-
title
74-
dateTime
75-
eventUrl
76-
venue {
77-
city
78-
state
79-
country
80-
venueType
81-
lat
82-
lng
83-
}
84-
}
85-
}
86-
}
87-
}
88-
}
89-
""",
90-
"variables": {
91-
"urlName": group_url_name,
92-
"searchEventInput": {
93-
# TODO: see if we need this limit or not
94-
"first": 20
95-
}
96-
}
97-
}
89+
return { "query": _EVENT_LISTING_QUERY, "variables": { "urlName": group_url_name } }
9890

9991
def _parse_event_listing_gql_response(self, response: dict) -> List[RawGqlEvent]:
100-
edges = response["groupByUrlname"]["upcomingEvents"]["edges"]
92+
edges = response["groupByUrlname"]["events"]["edges"]
10193

10294
events = []
10395
# TODO: maybe move this validation somewhere else?
10496
for edge_kwargs in edges:
105-
if not edge_kwargs["node"]["venue"]:
106-
logger.error(f"Event response missing venue: {edge_kwargs}")
97+
if not edge_kwargs["node"]["venues"]:
98+
logger.error(f"Event response missing venues: {edge_kwargs}")
10799
continue
108100

109101
events.append(RawGqlEvent(**edge_kwargs))
110102

111103
return events
112104

113-
def fetch_groups(self, endCursor=""):
114-
"""
115-
Returns the response from the API call, which includes data on groups matching the criteria specified in the GraphQL query.
116-
:type endCursor: An optional string parameter used for pagination, indicating the starting point of the query for fetching subsequent pages of results
117-
:rtype: requests.Response
118-
"""
119-
120-
# Sets the content type to application/json for the request body.
121-
headers = {
122-
"Authorization": f"Bearer {self._get_access_token()}",
123-
"Content-Type": "application/json",
124-
}
125-
126-
# GraphQL Query:
127-
# Below is a GraphQL query that requests information about groups such as ID, name, link, URL name, latitude, and longitude.
128-
data = {
129-
"query": """
130-
query (
131-
$searchGroupInput: ConnectionInput!,
132-
$searchGroupFilter: SearchConnectionFilter!,
133-
$sortOrder: KeywordSort!
134-
) {
135-
keywordSearch(
136-
input: $searchGroupInput,
137-
filter: $searchGroupFilter,
138-
sort: $sortOrder
139-
) {
140-
pageInfo {
141-
hasNextPage
142-
endCursor
143-
}
144-
edges {
145-
node {
146-
result {
147-
... on Group {
148-
id
149-
name
150-
link
151-
urlname
152-
latitude
153-
longitude
154-
}
155-
}
156-
}
157-
}
158-
}
159-
}
160-
""",
161-
# The query filters results based on the keyword "Rust" and sorts them by relevance
162-
"variables": {
163-
"searchGroupFilter": {
164-
"query": "Rust",
165-
"lat": 0.0,
166-
"lon": 0.0,
167-
"radius": 20000,
168-
"source": "GROUPS"
169-
},
170-
"searchGroupInput": {
171-
"first": 200,
172-
"after": endCursor
173-
},
174-
"sortOrder":{
175-
"sortField": "RELEVANCE"
176-
}
177-
}
178-
}
179-
return requests.post(url=self.GQL_ENDPOINT, headers=headers, json=data)
180-
181-
def get_rust_groups(self) -> dict:
182-
"""
183-
Returns a dictionary where each key represents the unique ID of a group, and the corresponding value is another dictionary containing details about the group such as name, link, URL name, latitude, and longitude
184-
:rtype: dict
185-
"""
186-
endCursor = None
187-
groups = dict()
188-
while True:
189-
response = self.fetch_groups(endCursor).json()
190-
data = response['data']
191-
edges = data['keywordSearch']['edges']
192-
pageInfo = data['keywordSearch']['pageInfo']
193-
for node in edges:
194-
group = node["node"]["result"]
195-
if not (group["id"] in groups):
196-
groups[group["id"]] = group
197-
if pageInfo['hasNextPage']:
198-
endCursor = pageInfo['endCursor']
199-
else:
200-
break
201-
return groups
202-
203105
def get_raw_events_for_group(self, group: MeetupGroupUrl) -> List[RawGqlEvent]:
204106
headers = {
205107
"Authorization": f"Bearer {self._get_access_token()}",
@@ -209,6 +111,7 @@ def get_raw_events_for_group(self, group: MeetupGroupUrl) -> List[RawGqlEvent]:
209111
logger.info(f"Fetching events for group {group}")
210112
query = self._build_event_listing_gql_query(group.url_name)
211113
response = requests.post(url=self.GQL_ENDPOINT, headers=headers, json=query)
114+
response.raise_for_status()
212115
data = response.json()["data"]
213116
logger.debug(data)
214117

@@ -217,4 +120,3 @@ def get_raw_events_for_group(self, group: MeetupGroupUrl) -> List[RawGqlEvent]:
217120
return []
218121

219122
return self._parse_event_listing_gql_response(data)
220-

0 commit comments

Comments
 (0)