def test_oauth_requests(self, mock_delete, mock_post, mock_get): mock_get.return_value = self.mock_response self.client = MeetupClient(oauth_token=MEETUP_KEY) self.client.invoke(meetup_method="2/groups", params={"member_id": "12345"}, method="GET") mock_get.assert_called_once() called_url = mock_get.call_args[0][0] headers = mock_get.call_args[1]['headers'] self.assertEqual({'Authorization': 'Bearer abc123'}, headers) self.assertGetCallMatches(called_url, '/2/groups', { 'page': ['1000'], 'member_id': ['12345'] }) mock_post.return_value = self.mock_response self.client.invoke(meetup_method="2/groups", params={"name": "Awesome Team"}, method="POST") mock_post.assert_called_once_with( "https://api.meetup.com/2/groups", data={"name": "Awesome Team"}, headers={'Authorization': 'Bearer abc123'}) mock_delete.return_value = self.mock_response self.client.invoke(meetup_method="2/groups/awesome-team", params={"id": 72}, method="DELETE") mock_delete.assert_called_once_with( "https://api.meetup.com/2/groups/awesome-team", params={"id": 72}, headers={'Authorization': 'Bearer abc123'})
def setUp(self): self.client = MeetupClient(api_key=MEETUP_KEY) self.json_body = MagicMock() self.response_headers = { 'X-RateLimit-Remaining': "14", 'X-RateLimit-Reset': "2" } self.mock_json = Mock(return_value=self.json_body) self.mock_response = Mock(headers=self.response_headers, json=self.mock_json)
def handle(self, *args, **options): client = MeetupClient(options.get('api_key', MEETUP_KEY)) # ======================= get the group if len(args) == 1: group_id = int(args[0]) else: group_id = settings.MEETUP_GROUP_ID # ======================= sync events for the group sync_group_events(group_id, client)
def handle_label(self, label, **options): print "Searching for '%s'" % label key = getattr(settings, 'MEETUP_KEY', None) if not key: raise CommandError('MEETUP_KEY is not found in settings.py') client = MeetupClient(key) resp = client.find_containers(label) if resp['meta']['count'] == 0: print "-- no results found --" else: for res in resp['results']: cont_id = str(res['id']).ljust(5, ' ') print "%s %s" % (cont_id, res['name'])
def sync_group_events(group_id, client=None): """ Use meetup group id to sync all events to this data base """ if client is None: client = MeetupClient(MEETUP_KEY) # ======================= get the group params = {} params["group_id"] = group_id results = client.invoke("/2/groups", params=params)["results"] if not len(results): raise ValueError("No meetup group_id {}".format(params["group_id"])) # ======================= sync events for the group for group_data in results: # create group group = Group.objects.from_meetup_data(group_data) print(" -- for group {} --".format(group.name)) # get all status options params["status"] = ",".join(STATUS_OPTIONS) events = client.invoke("/2/events", params)["results"] for event_data in events: event = Event.objects.from_meetup_data(event_data) print(" -- sync event {} --".format(event.name))
def sync_group_events(group_id, client=None): """ Use meetup group id to sync all events to this data base """ if client is None: client = MeetupClient(MEETUP_KEY) # ======================= get the group params = {} params['group_id'] = group_id results = client.invoke("/2/groups", params=params)['results'] if not len(results): raise ValueError("No meetup group_id {}".format(params['group_id'])) # ======================= sync events for the group for group_data in results: # create group group = Group.objects.from_meetup_data(group_data) print(" -- for group {} --".format(group.name)) # get all status options params['status'] = ",".join(STATUS_OPTIONS) events = client.invoke("/2/events", params)['results'] for event_data in events: event = Event.objects.from_meetup_data(event_data) print(" -- sync event {} --".format(event.name))
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)
def __init__(self, api_key): self.meetup_client = MeetupClient(api_key)
class MeetupClientTests(unittest.TestCase): """Tests that ensure GET requests function correctly. """ def setUp(self): self.client = MeetupClient(api_key=MEETUP_KEY) self.json_body = MagicMock() self.response_headers = { 'X-RateLimit-Remaining': "14", 'X-RateLimit-Reset': "2" } self.mock_json = Mock(return_value=self.json_body) self.mock_response = Mock( headers=self.response_headers, json=self.mock_json ) @patch.object(requests, "get") def test_invoke_get_calls_requests(self, mock_get): mock_get.return_value = self.mock_response result = self.client.invoke( meetup_method="2/groups", params={ "member_id": "12345" }, method="GET" ) mock_get.assert_called_once_with( "https://api.meetup.com/2/groups" "?page=1000" "&key=abc123" "&member_id=12345" ) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(requests, "post") def test_invoke_post_calls_requests(self, mock_post): mock_post.return_value = self.mock_response result = self.client.invoke( meetup_method="2/groups", params={ "name": "Awesome Team" }, method="POST" ) mock_post.assert_called_once_with( "https://api.meetup.com/2/groups", data={ "key": "abc123", "page": 1000, "name": "Awesome Team" } ) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(requests, "delete") def test_invoke_delete_calls_requests(self, mock_delete): mock_delete.return_value = self.mock_response result = self.client.invoke( meetup_method="2/groups/awesome-team", params={ "id": 72 }, method="DELETE" ) mock_delete.assert_called_once_with( "https://api.meetup.com/2/groups/awesome-team", params={ "key": "abc123", "page": 1000, "id": 72 } ) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(time, "sleep") @patch.object(requests, "get") def test_hit_rate_limit_waits(self, mock_get, mock_sleep): mock_get.return_value = self.mock_response self.response_headers['X-RateLimit-Remaining'] = "0" self.response_headers['X-RateLimit-Reset'] = "4" self.client.invoke("2/groups/foo") self.response_headers['X-RateLimit-Reset'] = "2" self.client.invoke("2/groups/bar") self.assertEqual(2, len(mock_get.call_args_list)) mock_sleep.assert_called_once_with(4) mock_sleep.reset_mock() self.client.invoke("2/groups/chew") mock_sleep.assert_called_once_with(2) @patch.object(requests, "get") def test_get_next_page_uses_meta_to_fetch_next(self, mock_get): mock_get.return_value = self.mock_response result = self.client.get_next_page( { "meta": { "next": "http://meetup.foo.co/page-2" } } ) mock_get.assert_called_once_with("http://meetup.foo.co/page-2") self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) def test_get_next_page_no_next_is_none(self): result = self.client.get_next_page( { "meta": { "prev": "http://fifo.com/1" } } ) self.assertIsNone(result) def test_get_next_page_no_meta_is_none(self): result = self.client.get_next_page({}) self.assertIsNone(result)
def handle(self, *args, **options): for account in Account.objects.all(): if not account.container_id: print "!!!\tno container ID found for key %s" % account.key else: client = MeetupClient(account.key) resp = client.container_events(account.container_id, extra_fields='rsvp_count') remote_ids = [] for res in resp['results']: event_id = str(res['id']) try: ev = Event.objects.get(pk=event_id, account=account) except Event.DoesNotExist: ev = Event(account=account) ev.meetup_url = res['meetup_url'] ev.title = res.get('title', '') ev.description = res.get('description', '') ev.start_time = parse_timestamp(res.get('time', None)) ev.location = res.get('venue_name', '') ev.address = res.get('address1', '') ev.city = res.get('city', '') ev.state = res.get('state', '') ev.zipcode = res.get('zip', '') ev.latitude = parse_geo(res.get('lat', None)) ev.longitude = parse_geo(res.get('lon', None)) ev.url = res.get('link', '') ev.rsvp_count = res.get('rsvp_count', 0) ev.timestamp = parse_timestamp(res.get('updated', None) or res['created']) ev.status = res['status'] organizer = res.get('organizer', None) if organizer: ev.organizer_id = organizer['member_id'] ev.organizer_name = organizer['name'] # user defined fields if ev.id: print "* updated local event %s" % ev.pk else: ev.pk = event_id print "* created local event %s" % ev.pk ev.save(sync=False) if res['status'] != 'past': remote_ids.append(event_id) local_ids = Event.objects.filter(account=account).exclude(status='past').values_list('id', flat=True) to_delete = set(local_ids) - set(remote_ids) for ev in Event.objects.filter(id__in=to_delete, account=account): ev.delete() print "* deleted %s local events" % len(to_delete)
class MeetupClientTests(unittest.TestCase): """Tests that ensure GET requests function correctly. """ def setUp(self): self.client = MeetupClient(api_key=MEETUP_KEY) self.json_body = MagicMock() self.response_headers = { 'X-RateLimit-Remaining': "14", 'X-RateLimit-Reset': "2" } self.mock_json = Mock(return_value=self.json_body) self.mock_response = Mock(headers=self.response_headers, json=self.mock_json) def assertGetCallMatches(self, called_url, expected_path, params_dict): parsed_url = urlparse(called_url) query_dict = parse_qs(parsed_url.query) self.assertEqual(parsed_url.scheme, 'https') self.assertEqual(parsed_url.netloc, 'api.meetup.com') self.assertEqual(parsed_url.path, expected_path) self.assertDictEqual(params_dict, query_dict) @patch.object(requests, "get") @patch.object(requests, "post") @patch.object(requests, "delete") def test_oauth_requests(self, mock_delete, mock_post, mock_get): mock_get.return_value = self.mock_response self.client = MeetupClient(oauth_token=MEETUP_KEY) self.client.invoke(meetup_method="2/groups", params={"member_id": "12345"}, method="GET") mock_get.assert_called_once() called_url = mock_get.call_args[0][0] headers = mock_get.call_args[1]['headers'] self.assertEqual({'Authorization': 'Bearer abc123'}, headers) self.assertGetCallMatches(called_url, '/2/groups', { 'page': ['1000'], 'member_id': ['12345'] }) mock_post.return_value = self.mock_response self.client.invoke(meetup_method="2/groups", params={"name": "Awesome Team"}, method="POST") mock_post.assert_called_once_with( "https://api.meetup.com/2/groups", data={"name": "Awesome Team"}, headers={'Authorization': 'Bearer abc123'}) mock_delete.return_value = self.mock_response self.client.invoke(meetup_method="2/groups/awesome-team", params={"id": 72}, method="DELETE") mock_delete.assert_called_once_with( "https://api.meetup.com/2/groups/awesome-team", params={"id": 72}, headers={'Authorization': 'Bearer abc123'}) @patch.object(requests, "get") def test_invoke_get_calls_requests(self, mock_get): mock_get.return_value = self.mock_response result = self.client.invoke(meetup_method="2/groups", params={"member_id": "12345"}, method="GET") mock_get.assert_called_once() called_url = mock_get.call_args[0][0] self.assertGetCallMatches( called_url, '/2/groups', { 'page': ['1000'], 'key': ['abc123'], 'member_id': ['12345'], }, ) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(requests, "patch") def test_invoke_patch_calls_requests(self, mock_patch): mock_patch.return_value = self.mock_response result = self.client.invoke(meetup_method="foo/events/1734824", params={"name": "Awesome Team Event"}, method="PATCH") mock_patch.assert_called_once_with( "https://api.meetup.com/foo/events/1734824", data={ "key": "abc123", "name": "Awesome Team Event" }) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(requests, "post") def test_invoke_post_calls_requests(self, mock_post): mock_post.return_value = self.mock_response result = self.client.invoke(meetup_method="2/groups", params={"name": "Awesome Team"}, method="POST") mock_post.assert_called_once_with("https://api.meetup.com/2/groups", data={ "key": "abc123", "name": "Awesome Team" }) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(requests, "delete") def test_invoke_delete_calls_requests(self, mock_delete): mock_delete.return_value = self.mock_response result = self.client.invoke(meetup_method="2/groups/awesome-team", params={"id": 72}, method="DELETE") mock_delete.assert_called_once_with( "https://api.meetup.com/2/groups/awesome-team", params={ "key": "abc123", "id": 72 }) self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) @patch.object(time, "sleep") @patch.object(requests, "get") def test_hit_rate_limit_waits(self, mock_get, mock_sleep): mock_get.return_value = self.mock_response self.response_headers['X-RateLimit-Remaining'] = "0" self.response_headers['X-RateLimit-Reset'] = "4" self.client.invoke("2/groups/foo") self.response_headers['X-RateLimit-Reset'] = "2" self.client.invoke("2/groups/bar") self.assertEqual(2, len(mock_get.call_args_list)) mock_sleep.assert_called_once_with(4) mock_sleep.reset_mock() self.client.invoke("2/groups/chew") mock_sleep.assert_called_once_with(2) @patch.object(requests, "get") def test_get_next_page_uses_meta_to_fetch_next(self, mock_get): mock_get.return_value = self.mock_response result = self.client.get_next_page( {"meta": { "next": "http://meetup.foo.co/page-2" }}) mock_get.assert_called_once_with("http://meetup.foo.co/page-2") self.mock_json.assert_called_once_with() self.assertIs(self.json_body, result) def test_get_next_page_no_next_is_none(self): result = self.client.get_next_page( {"meta": { "prev": "http://fifo.com/1" }}) self.assertIsNone(result) def test_get_next_page_no_meta_is_none(self): result = self.client.get_next_page({}) self.assertIsNone(result)