def test_post_with_valid_token(self, token_first, test_eventbrite_credentials): """ Send POST request with valid venue data to create venue endpoint and response should be 201 """ social_network = SocialNetwork.get_by_name(EVENTBRITE.title()) venue = { "social_network_id": social_network.id, "zip_code": "54600", "address_line_2": "H# 163, Block A", "address_line_1": "New Muslim Town", "latitude": 0, "longitude": 0, "state": "CA", "city": "Lahore", "country": "Pakistan" } response = requests.post(SocialNetworkApiUrl.VENUES, data=json.dumps(venue), headers=get_headers(token_first)) logger.info(response.text) assert response.status_code == codes.CREATED, 'Status should be Ok, Resource created (201)' assert 'Location' in response.headers response = response.json() assert response['id'] > 0 Venue.session.commit() venue = Venue.get_by_id(response['id']) assert venue, 'Venue created successfully in db' Venue.delete(venue.id)
def delete(self, venue_id): """ This endpoint deletes one venue owned by this user. :param venue_id: id of venue on getTalent database to be deleted :Example: headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } response = requests.delete( API_URL + '/venues/1', headers=headers, ) .. Response:: { 'message': 'Venue has been deleted successfully' } .. HTTP Status:: 200 (Resource Deleted) 404 (Not found) 500 (Internal Server Error) """ venue = Venue.get_by_user_id_venue_id(request.user.id, venue_id) if not venue: raise ResourceNotFound('Venue not found') Venue.delete(venue) return dict(message='Venue has been deleted successfully')
def delete(self): """ This endpoint deletes venues specified in list in request data. :Example: venue_ids = { 'ids': [1,2,3] } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(venue_ids) response = requests.post( API_URL + '/venues/', data=data, headers=headers, ) .. Response:: { 'message': '3 Venues have been deleted successfully' } .. HTTP Status:: 200 (Resource Deleted) 207 (Not all deleted) 400 (Bad request) 500 (Internal Server Error) """ user_id = request.user.id deleted, not_deleted = [], [] req_data = get_valid_json_data(request) venue_ids = req_data['ids'] if 'ids' in req_data and isinstance( req_data['ids'], list) else [] if venue_ids: for _id in venue_ids: venue = Venue.get_by_user_id_venue_id(user_id, _id) if venue: Venue.delete(_id) deleted.append(_id) else: not_deleted.append(_id) if not not_deleted: return dict(message='%s Venue(s) deleted successfully' % len(deleted)) return dict(message='Unable to delete %s venue(s)' % len(not_deleted), deleted=deleted, not_deleted=not_deleted), 207 else: raise InvalidUsage('Bad request, include ids as list data')
def save_venue(venue_data): """ This function will take dictionary data and will save it in database as Venue reccord. :param dict venue_data: venue data """ valid_fields = ['address_line_1', 'address_line_2', 'city', 'country', 'latitude', 'longitude', 'zip_code', 'user_id', 'social_network_id', 'social_network_venue_id'] venue_data = {key: venue_data[key] for key in venue_data if key in valid_fields} required_fields = ['social_network_id', 'user_id'] for key in required_fields: if key not in venue_data: raise InvalidUsage('Required field missing in venue data. Field: %s' % key) venue = Venue(**venue_data) Venue.save(venue) return venue
def resolve_venue(self, args, request, info): """ Resolves current user's created venue specified by id. """ venue_id = args.get('id') venue = Venue.get_by_user_id_venue_id(request.user.id, venue_id) return venue
def validate_required_fields(data): social_network_id = data['social_network_id'] user_id = data['user_id'] venue_id = data['venue_id'] venue = Venue.get_by_user_id_social_network_id_venue_id( user_id, social_network_id, venue_id) if not venue: raise VenueNotFound('Venue not found in database. Kindly create' ' venue first.')
def add_venue_to_sn(self, venue_data): """ This function sends a POST request to Meetup api to create a venue for event. :param dict venue_data: a dictionary containing data required to create a venue """ if not venue_data.get('group_url_name'): raise InvalidUsage("Mandatory Input Missing: group_url_name", error_code=custom_codes.MISSING_REQUIRED_FIELDS) url = get_url(self, SocialNetworkUrls.VENUES, custom_url=MEETUP_VENUE).format( venue_data['group_url_name']) payload = { 'address_1': venue_data['address_line_1'], 'address_2': venue_data.get('address_line_2'), 'city': venue_data['city'], 'country': venue_data['country'], 'state': venue_data['state'], 'name': venue_data['address_line_1'] } # Sleep for 10 / 30 seconds to avoid throttling time.sleep(0.34) response = http_request('POST', url, params=payload, headers=self.headers, user_id=self.user.id) json_resp = response.json() if response.ok: venue_id = json_resp['id'] logger.info('Venue has been Added. Venue Id: %s', venue_id) elif response.status_code == codes.CONFLICT: # 409 is returned when our venue is matching existing # venue/venues. try: match_id = json_resp['errors'][0]['potential_matches'][0]['id'] except: raise InternalServerError('Invalid response from Meetup', error_code=INVALID_MEETUP_RESPONSE) venue = Venue.get_by_user_id_and_social_network_venue_id( self.user.id, match_id) if venue: raise InvalidUsage( 'Venue already exists in getTalent database', additional_error_info=dict(id=venue.id), error_code=VENUE_EXISTS_IN_GT_DATABASE) venue_id = json_resp['errors'][0]['potential_matches'][0]['id'] else: raise InternalServerError( 'ApiError: Unable to create venue for Meetup', additional_error_info=dict(venue_error=json_resp)) venue_data['user_id'] = self.user.id venue_data['social_network_venue_id'] = venue_id return SocialNetworkBase.save_venue(venue_data)
def put(self, venue_id): """ Updates a venue for current user :param venue_id: id of the requested venue :Example: venue_data = { "address_line_2": "", "city": "Cupertino", "address_line_1": "Infinite Loop", "social_network_id": 13, "country": "us", "zip_code": "95014", "longitude": 0, "social_network_venue_id": "15570022", "state": "CA", "latitude": 0, "id": 1 } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(venue_data) response = requests.post( API_URL + '/venues/1', data=data, headers=headers, ) .. Response:: { 'message': 'Venue updated successfully' } .. HTTP Status:: 200 (Resource Updated) 500 (Internal Server Error) """ user_id = request.user.id venue_data = get_valid_json_data(request) venue = Venue.get_by_user_id_venue_id(user_id, venue_id) if venue: venue_data['user_id'] = user_id venue.update(**venue_data) return dict(message='Venue updated successfully') else: raise ResourceNotFound('Venue not found')
def get(self, venue_id): """ This action returns a venue (given by id) created by current user. :param venue_id: id of venue to be returned :Example: headers = {'Authorization': 'Bearer <access_token>'} response = requests.get( API_URL + '/venues/1', headers=headers ) .. Response:: { "venue": { "address_line_2": "", "city": "Cupertino", "address_line_1": "Infinite Loop", "social_network_id": 13, "country": "us", "zip_code": "95014", "longitude": 0, "social_network_venue_id": "15570022", "state": "CA", "latitude": 0, "id": 1 } } .. HTTP Status:: 200 (OK) 404 (Resource not found) 500 (Internal Server Error) """ user_id = request.user.id venue = Venue.get_by_user_id_venue_id(user_id, venue_id) if not venue: raise ResourceNotFound('Venue not found') venue = venue.to_json() return dict(venue=venue)
def save_or_update_venue(self, venue_data): """ This method takes venue dictionary data and save that venue in database or update the existing one if there is already venue there with this data. :param venue_data: venue dict :rtype: Venue """ venue_in_db = Venue.get_by_user_id_and_social_network_venue_id( self.user.id, venue_data['social_network_venue_id']) if venue_in_db: venue_in_db.update(**venue_data) logger.info('Venue updated successfully:%s' % venue_in_db.to_json()) else: venue_in_db = Venue(**venue_data) Venue.save(venue_in_db) logger.info('Venue imported successfully:%s' % venue_in_db.to_json()) return venue_in_db
def event_sn_to_gt_mapping(self, event): """ We take event's data from social network's API and map its fields to getTalent database fields. Finally we return Event's object to save/update record in getTalent database. We also issue some calls to get updated venue and organizer information. :param event: data from Facebook API. :type event: dictionary :exception Exception: It raises exception if there is an error getting data from API. :return: event: Event object :rtype event: common.models.event.Event """ venue = None location = None venue_id = None organizer = None organizer_id = None assert event is not None owner = event.get('owner') if event.get('place'): venue = event.get('place') location = venue['location'] try: organizer = self.graph.get_object('v2.4/' + owner['id']) organizer = organizer.get('data') except facebook.GraphAPIError: logger.exception( 'event_sn_to_gt_mapping: Getting data of organizer. ' 'user_id: %s, social_network_event_id: %s' % (self.user.id, event['id'])) raise if owner or organizer: organizer_data = dict( user_id=self.user.id, name=owner['name'] if owner and owner.has_key('name') else '', email=organizer['email'] if organizer and organizer.has_key('email') else '', about='') organizer_in_db = EventOrganizer.get_by_user_id_and_name( self.user.id, owner['name'] if owner and owner.has_key('name') else '') if organizer_in_db: organizer_in_db.update(**organizer_data) organizer_id = organizer_in_db.id else: organizer_instance = EventOrganizer(**organizer_data) EventOrganizer.save(organizer_instance) organizer_id = organizer_instance.id if venue: venue_data = dict( social_network_venue_id=venue['id'], user_id=self.user.id, address_line_1=location['street'] if location.has_key('street') else '', address_line_2='', city=location['city'].title() if location.has_key('city') else '', state='', zip_code=location['zip'] if location.has_key('zip') else None, country=location['country'].title() if location.has_key('country') else '', longitude=float(location['longitude']) if location.has_key('longitude') else 0, latitude=float(location['latitude']) if location.has_key('latitude') else 0, ) venue_in_db = Venue.get_by_user_id_and_social_network_venue_id( self.user.id, venue['id']) if venue_in_db: venue_in_db.update(**venue_data) venue_id = venue_in_db.id else: venue = Venue(**venue_data) Venue.save(venue) venue_id = venue.id try: event = Event(social_network_event_id=event['id'], title=event['name'], description=event.get('description', ''), social_network_id=self.social_network.id, user_id=self.user.id, organizer_id=organizer_id, venue_id=venue_id, social_network_group_id=0, start_datetime=event.get('start_time'), end_datetime=event.get('end_time'), timezone=event.get('timezone'), registration_instruction='', cost=0, currency='', max_attendees=event['attending_count'] + event['maybe_count'] + event['noreply_count'] if (event and event.has_key('attending_count') and event.has_key('maybe_count') and event.has_key('noreply_count')) else '') except: logger.exception('event_sn_to_gt_mapping: user_id: %s, ' 'social_network_event_id: %s' % (self.user.id, event['id'])) else: return event
def add_location(self): """ This generates a venue object for the event and returns the id of venue. :exception EventLocationNotCreated: throws exception if unable to create or update venue on Eventbrite :exception VenueNotFound: raises exception if venue does not exist in database :return venue_id: id for venue created on eventbrite.com :rtype venue_id: int :Example: This method is used to create venue or location for event on Eventbrite. It requires a venue already created in getTalent database otherwise it will raise VenueNotFound exception. Given venue id it first gets venue from database and uses its data to create Eventbrite object >> eventbrite = Eventbrite(user=gt_user, headers=authentication_headers) Then we call add location from create event To get a better understanding see *create_event()* method. """ # get venue from db which will be created on Eventbrite venue = Venue.get_by_user_id_social_network_id_venue_id( self.user.id, self.social_network.id, self.venue_id) if venue: if venue.social_network_venue_id: # there is already a venue on Eventbrite with this info. return venue.social_network_venue_id # This dict is used to create venue payload = { 'venue.name': venue.address_line_1, 'venue.address.address_1': venue.address_line_1, 'venue.address.address_2': venue.address_line_2, 'venue.address.region': venue.state, 'venue.address.city': venue.city, # 'venue.address.country': venue.country, 'venue.address.postal_code': venue.zip_code, 'venue.address.latitude': venue.latitude, 'venue.address.longitude': venue.longitude, } # create url to send post request to create venue url = get_url(self, Urls.VENUES) response = http_request('POST', url, params=payload, headers=self.headers, user_id=self.user.id) if response.ok: logger.info('| Venue has been created |') venue_id = response.json().get('id') venue.update(social_network_venue_id=venue_id) return venue_id else: error_message = "Venue was not Created. There are some " \ "errors: Details: %s " % response message = '\nErrors from the Social Network:\n' message += \ ''.join(response.json().get('error') + ',' + response.json().get('error_description')) error_message += message log_error({'error': error_message, 'user_id': self.user.id}) raise EventLocationNotCreated( 'ApiError: Unable to create venue for event\n %s' % message) else: error_message = 'Venue with ID = %s does not exist in db.' \ % self.venue_id log_error({ 'user_id': self.user.id, 'error': error_message, }) raise VenueNotFound('Venue not found in database. Kindly create' ' venue first.')
def event_sn_to_gt_mapping(self, event): """ We take event's data from social network's API and map its fields to getTalent database fields. Finally we return Event's object to save/update record in getTalent database. We also issue some calls to get updated venue and organizer information. :param event: data from eventbrite API. :type event: dictionary :exception Exception: It raises exception if there is an error getting data from API. :return: event_data, venue_data: event dict object, venue dict data :rtype tuple: event and venue dict data """ venue_obj = None venue_data = None assert event is not None # Get information about event's venue venue_id = event.get('venue_id') if venue_id: venue_obj = Venue.get_by_user_id_and_social_network_venue_id( self.user.id, venue_id) if not venue_obj: try: # Get venues from Eventbrite API for this event. response = http_request('GET', get_url(self, Urls.VENUE).format( event['venue_id']), headers=self.headers, user_id=self.user.id) except: logger.exception('event_sn_to_gt_mapping: user_id: %s,' 'social_network_event_id: %s' % (self.user.id, event['id'])) raise if response.ok: # get json data for venue venue = response.json() venue_data = dict( social_network_id=self.social_network.id, social_network_venue_id=event['venue_id'], user_id=self.user.id, address_line_1=venue['address']['address_1'], address_line_2=venue['address']['address_2'], city=venue['address']['city'], state=venue['address']['region'], zip_code=venue['address']['postal_code'], country=venue['address']['country'], longitude=float(venue['address']['longitude']) if venue and venue.has_key('address') else 0, latitude=float(venue['address']['latitude']) if venue and venue.has_key('address') else 0) # return Event object event_data = dict(social_network_event_id=event['id'], title=event['name']['text'], description=event['description']['html'], social_network_id=self.social_network.id, user_id=self.user.id, social_network_group_id=0, url=event.get('url'), group_url_name='', venue_id=venue_obj.id if venue_obj else None, start_datetime=event['start']['local'], end_datetime=event['end']['local'], registration_instruction='', cost=0, currency=event['currency'], timezone=event['start']['timezone'], max_attendees=event['capacity']) return event_data, venue_data
def add_location(self): """ This function adds the location of event. :exception EventLocationNotCreated: raises exception if unable to create venue on Meetup.com. :exception VenueNotFound: raises exception if unable to find venue in getTalent database. :return id: id of venue created if creation is successful. :rtype id: int :Example: This method is used to create venue or location for event on Meetup. It requires a venue already created in getTalent database otherwise it will raise VenueNotFound exception. Given venue id it first gets venue from database and uses its data to create Meetup object >> meetup = Meetup(user=gt_user, headers=authentication_headers) Then we call add location from create event To get a better understanding see *create_event()* method. """ venue_in_db = Venue.get_by_user_id_social_network_id_venue_id( self.user.id, self.social_network.id, self.venue_id) if not venue_in_db: error_message = 'Venue does not exist in db. Venue id is {}'.format( self.venue_id) log_error({'user_id': self.user.id, 'error': error_message}) raise VenueNotFound( 'Venue not found in database. Kindly specify a valid venue.') if venue_in_db.social_network_venue_id: return venue_in_db.social_network_venue_id url = get_url(self, Urls.VENUES, custom_url=MEETUP_VENUE.format(self.group_url_name)) logger.info( 'Creating venue for %s(user id:%s) using url:%s of API of %s.' % (self.user.name, self.user.id, url, self.social_network.name)) payload = { 'address_1': venue_in_db.address_line_1, 'address_2': venue_in_db.address_line_2, 'city': venue_in_db.city, 'country': venue_in_db.country, 'state': venue_in_db.state, 'name': venue_in_db.address_line_1 } # Sleep for 10 / 30 seconds to avoid throttling time.sleep(0.34) response = http_request('POST', url, params=payload, headers=self.headers, user_id=self.user.id) if response.ok: venue_id = json.loads(response.text)['id'] logger.info('| Venue has been Added |') elif response.status_code == 409: # 409 is returned when our venue is matching existing # venue/venues. So we pick the first one in potential # matches. try: venue_id = json.loads( response.text)['errors'][0]['potential_matches'][0]['id'] logger.info('| Venue was picked from matched records |') except Exception as e: raise EventLocationNotCreated( 'ApiError: Unable to create venue for event', additional_error_info=dict(venue_error=str(e))) else: error_message = 'Venue was not Added. There are some errors.' errors = response.json().get('errors') message = '\nErrors from the social network:\n' message += '\n'.join(error['message'] + ', ' + error['code'] for error in errors) if errors else '' error_message += message log_error({'user_id': self.user.id, 'error': error_message}) raise EventLocationNotCreated( 'ApiError: Unable to create venue for event\n %s' % message) venue_in_db.update(social_network_venue_id=venue_id) return venue_id
def event_sn_to_gt_mapping(self, event): """ We take event's data from social network's API and map its fields to getTalent database fields. Finally we return Event's object to save/update record in getTalent database. We also issue some calls to get updated venue and organizer information. event object from Meetup API looks like { u'status': u'upcoming', u'utc_offset': -25200000, u'event_url': u'https://www.meetup.com/sfpython/events/234926670/', u'group': { u'who': u'Python Programmers', u'name': u'San Francisco Python Meetup Group', u'group_lat': 37.77000045776367, u'created': 1213377311000, u'join_mode': u'open', u'group_lon': -122.44000244140625, u'urlname': u'sfpython', u'id': 1187265 }, u'description': u'<p>SF Python is bringing it\'s Project Night to TBA. Please come out and hack with this great community we have built.</p> <p>We are really grateful that our facility host TBA is sponsoring food and beverages (alcoholic and non-alcoholic) for this event.</p> <p>Please email the leadership team if you are interested in:</p> ', u'created': 1457407879000, u'updated': 1457407879000, u'visibility': u'public', "timezone": "US/Pacific", // This field only appears when requested in `fields` parameters u'rsvp_limit': 75, // This field only appears when we set RSVP settings while creating an event u'yes_rsvp_count': 2, u'waitlist_count': 0, u'maybe_rsvp_count': 0, u'time': 1505955600000, u'duration': 11700000, u'headcount': 0, u'id': u'gqjhrlywmbbc', u'name': u'Project Night at TBA'} :param event: data from Meetup's API :type event: dictionary :exception Exception: It raises exception if there is an error getting data from API. :return: event: Event object :rtype event: common.models.event.Event """ venue_obj = None venue_data = None venue = event.get('venue') start_time = event.get('time') utc_offset = event.get('utc_offset') if start_time: start_time = milliseconds_since_epoch_to_dt(start_time + (utc_offset or 0)) end_time = event.get('duration', None) if start_time and end_time: end_time = milliseconds_since_epoch_to_dt(event['time'] + end_time + (utc_offset or 0)) if venue: # venue data looks like # { # u'city': u'Cupertino', u'name': u'Meetup Address', # u'country': u'US', u'lon': -122.030754, # u'address_1': u'Infinite Loop', u'repinned': False, # u'lat': 37.33167, u'id': 24062708 # } venue_obj = Venue.get_by_user_id_and_social_network_venue_id( self.user.id, venue['id']) if not venue_obj: venue_data = dict(social_network_id=self.social_network.id, social_network_venue_id=venue['id'], user_id=self.user.id, address_line_1=venue.get('address_1', ''), address_line_2=venue.get('name', ''), city=venue.get('city', '').title().strip(), state=venue.get('state', '').title().strip(), zip_code=venue.get('zip'), country=venue.get('country', '').title().strip(), longitude=float(venue.get('lon', 0)), latitude=float(venue.get('lat', 0))) event_data = dict( social_network_event_id=event['id'], title=event['name'], description=event.get('description', ''), social_network_id=self.social_network.id, user_id=self.user.id, venue_id=venue_obj.id if venue_obj else None, # group id and urlName are required fields to edit an event # so should raise exception if Null social_network_group_id=event['group']['id'], group_url_name=event['group']['urlname'], # Let's drop error logs if venue has no address, or if address # has no longitude/latitude url=event.get('event_url'), start_datetime=start_time, end_datetime=end_time, registration_instruction='', cost=0, currency='', timezone=event.get('timezone'), max_attendees=event.get('rsvp_limit')) return event_data, venue_data
def post(self): """ Creates a venue for this user :Example: venue_data = { "zip_code": "95014", "social_network_id": 13, "address_line_2": "", "address_line_1": "Infinite Loop", "latitude": 0, "longitude": 0, "state": "CA", "city": "Cupertino", "country": "us" } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(venue_data) response = requests.post( API_URL + '/venues/', data=data, headers=headers, ) .. Response:: { "message" : 'Venue created successfully' 'id' : 123 } .. HTTP Status:: 201 (Resource Created) 500 (Internal Server Error) """ user_id = request.user.id venue_data = get_valid_json_data(request) mandatory_input_data = [ 'address_line_1', 'city', 'country', 'state', 'social_network_id' ] # gets fields which are missing missing_items = [ key for key in mandatory_input_data if not venue_data.get(key) ] if missing_items: raise InvalidUsage("Mandatory Input Missing: %s" % missing_items, error_code=custom_codes.MISSING_REQUIRED_FIELDS) social_network_id = venue_data['social_network_id'] social_network_venue_id = venue_data.get('social_network_venue_id') if social_network_venue_id: venue = Venue.get_by_user_id_and_social_network_venue_id( user_id, social_network_venue_id) if venue: raise InvalidUsage( 'Venue already exists in getTalent database', error_code=VENUE_EXISTS_IN_GT_DATABASE) venue_data['user_id'] = user_id venue = SocialNetworkBase.save_venue(venue_data) else: social_network = SocialNetwork.get(social_network_id) if social_network: # creating class object for respective social network social_network_class = get_class(social_network.name.lower(), 'social_network') social_network = social_network_class(user_id=user_id) else: raise InvalidUsage( 'Unable to find social network with given id: %s' % social_network_id) venue = social_network.add_venue_to_sn(venue_data) headers = { 'Location': '{url}/{id}'.format(url=SocialNetworkApi.VENUES, id=venue.id) } return ApiResponse(dict(message='Venue created successfully', id=venue.id), status=201, headers=headers)