-
Notifications
You must be signed in to change notification settings - Fork 0
/
meetup_union.py
executable file
·128 lines (98 loc) · 3.78 KB
/
meetup_union.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import os
import argparse
from collections import Counter
from json import JSONDecodeError
from time import sleep
import requests
from urllib.parse import urlencode
from meetup.api import Client as MeetupClient
MEETUP_API_ROOT = 'https://api.meetup.com/'
MEETUP_ATTENDANCE_ENDPOINT = '{urlname}/events/{event_id}/attendance'
MEETUP_API_KEY = os.environ.get('MEETUP_API_KEY')
MEMBER, MEMBER_OF_TARGET, MEMBER_OF_BOTH = 1, 2, 3
def fetch_attendee_ids(own_meetup, event_id):
"""
We don't use the meetup api library for this ones, it appears to be buggy
and never returns results...
NB: This returns all RSVPs but further filtering is possible.
"""
# Build url
attendance_endpoint = MEETUP_ATTENDANCE_ENDPOINT.format(**{
'urlname': own_meetup,
'event_id': event_id,
})
auth_params = urlencode({'sign': 'true', 'key': MEETUP_API_KEY})
url = f'{MEETUP_API_ROOT}{attendance_endpoint}?{auth_params}'
# Do query
response = requests.get(url)
# Parse JSON data
return [_a['member']['id'] for _a in response.json()]
def fetch_member_groups_urlnames(client, member_id):
try:
groups_joined = client.GetGroups(member_id=member_id).results
except (JSONDecodeError, TypeError):
sleep(0.5)
try:
# Poor man's retry strategy - it looks like Meetup's API
# can randomly return blank pages, so wait a bit and retry
groups_joined = client.GetGroups(member_id=member_id).results
except (JSONDecodeError, TypeError) as e:
print(e)
print("Unexpected api client error, skipping member")
groups_joined = []
return [_r['urlname'] for _r in groups_joined]
def get_membership_state(urlnames, own_meetup, target_meetup):
common_groups = {
own_meetup,
target_meetup,
}.intersection(set(urlnames))
if len(common_groups) == 0:
# These people probably have their groups set to private
return None
if len(common_groups) == 2:
return MEMBER_OF_BOTH
if MEMBER_OF_TARGET in common_groups:
# Also Hmmm...
# don't they also need to be a member of our meetup to attend?
return MEMBER_OF_TARGET
return MEMBER
def print_results(states, own_meetup, target_meetup):
state_counter = Counter(states)
print("\n"*4)
print("====="*20)
print(f"Members of only {own_meetup}: "
f"{state_counter[MEMBER]}")
print(f"Members of only {target_meetup}: "
f"{state_counter[MEMBER_OF_TARGET]}")
print(f"Members of both: "
f"{state_counter[MEMBER_OF_BOTH]}")
print(f"Members of neither (private?): "
f"{state_counter[None]}")
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("own_meetup",
help="String identifier Found in the Meetup's URL")
parser.add_argument("target_meetup",
help="String identifier Found in the Meetup's URL")
parser.add_argument("event_id",
type=int,
help="Numeric id found in the event's URL")
return parser.parse_args()
def main():
options = parse_arguments()
client = MeetupClient(MEETUP_API_KEY)
attendee_ids = fetch_attendee_ids(options.own_meetup, options.event_id)
states = []
for member_id in enumerate(attendee_ids):
groups_urlnames = fetch_member_groups_urlnames(client, member_id)
# Sleep after each request, so that we don't trigger rate limiting
sleep(0.4)
states.append(
get_membership_state(
groups_urlnames,
options.own_meetup,
options.target_meetup)
)
print_results(states, options.own_meetup, options.target_meetup)
if __name__ == "__main__":
main()