def delete(self): """ Deletes multiple social network whose ids are given in list in request data. :Example: social_network_ids = { 'ids': [1,2,3] } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(social_network_ids) response = requests.post( API_URL + '/social-network/', data=data, headers=headers, ) .. Response:: { 'message': '3 social networks have been deleted successfully' } .. HTTP Status:: 200 (Resource Deleted) 207 (Not all deleted) 400 (Bad request) 500 (Internal Server Error) """ # get event_ids for events to be deleted req_data = get_valid_json_data(request) social_network_ids = req_data['social_network_ids'] \ if 'social_network_ids' in req_data and isinstance( req_data['social_network_ids'], list) else [] total_deleted = 0 total_not_deleted = 0 if social_network_ids: for sn_id in social_network_ids: try: if SocialNetwork.get_by_id(sn_id): SocialNetwork.delete(sn_id) total_deleted += 1 except Exception as e: total_not_deleted += 1 logger.info( 'Unable to delete social network with ID: %s\nError: %s' % (sn_id, e.message)) if total_not_deleted: return dict(message='Unable to delete %s social networks' % total_not_deleted, deleted=total_deleted, not_deleted=total_not_deleted), codes.MULTI_STATUS elif total_deleted: return dict(message='%s social networks deleted successfully' % total_deleted) raise InvalidUsage('Bad request, include social work ids as list data', error_code=codes.BAD_REQUEST)
def is_subscribed_test_data(user_first): """ This fixture creates two social networks and add credentials for first social network. We actually want to test 'is_subscribed' field in social networks data from API. """ old_records = SocialNetwork.query.filter( SocialNetwork.name.in_(['SN1', 'SN2'])).all() for sn in old_records: if sn.id is not None: try: SocialNetwork.delete(sn.id) except Exception: db.session.rollback() test_social_network1 = SocialNetwork(name='SN1', url='www.SN1.com') SocialNetwork.save(test_social_network1) test_social_network2 = SocialNetwork(name='SN2', url='www.SN1.com') SocialNetwork.save(test_social_network2) test_social_network1_credentials = UserSocialNetworkCredential( user_id=user_first['id'], social_network_id=test_social_network1.id, access_token='lorel ipsum', refresh_token='lorel ipsum') UserSocialNetworkCredential.save(test_social_network1_credentials) return test_social_network1, test_social_network2, test_social_network1_credentials
def post(self, **kwargs): """ This method takes data to create social network in database. :Example: social_network = { "name": 'Github', "url": 'http://www.github.com/', "apiUrl": "http://www.github.com/v1/api/", "clientKey": "client_key_here", "secretKey": "client_secret_goes_here", "redirectUri": "http://gettalent.com", "authUrl": "http://www.github.com/auth", } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(social_network) response = requests.post( API_URL + '/social-network/', data=data, headers=headers, ) .. Response:: { id: 123232 } .. HTTP Status:: 201 (Resource Created) 500 (Internal Server Error) 401 (Unauthorized to access getTalent) :return: id of created event """ # get json post request data sn_data = get_valid_json_data(request) social_network = SocialNetwork(**sn_data) SocialNetwork.save(social_network) headers = { 'Location': '{url}/{id}'.format(url=SocialNetworkApi.SOCIAL_NETWORKS, id=social_network.id) } response = ApiResponse(dict(id=social_network.id), status=201, headers=headers) return response
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 get_user_and_social_network(self, user_id, social_network_id=None): """ This gets the User object and social network object from database. :param int | long user_id: Id of user :param int | long | None social_network_id: Id of SocialNetwork object :rtype: tuple """ raise_if_not_positive_int_or_long(user_id) user = User.query.get(user_id) if not user: raise NoUserFound("No User found in database with id %s." % user_id) if social_network_id: raise_if_not_positive_int_or_long(social_network_id) social_network = SocialNetwork.get_by_id(social_network_id) else: social_network = SocialNetwork.get_by_name(self.__class__.__name__) return user, social_network
def authorize(): """ This is a redirect URL which will be hit when a user accept the invitation on meetup or eventbrite In case of meetup the querystring args contain 'state' and in case of eventbrite the querystring args does not contain 'state' parameter """ error = request.args.get('error') if error: return redirect(SocialNetworkApiUrl.SUBSCRIBE % error) code = request.args.get('code') url = SocialNetworkApiUrl.SUBSCRIBE % code if len(code) == MEETUP_CODE_LENGTH: social_network = SocialNetwork.get_by_name(MEETUP.title()) else: social_network = SocialNetwork.get_by_name(EVENTBRITE.title()) url += '&id=%s' % social_network.id return redirect(url)
def post(self): """ Creates an event organizer for this user. :Example: organizer_data = { "name": "Zohaib Ijaz", "email": "*****@*****.**", "about": "I am a software engineer" } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(organizer_data) response = requests.post( API_URL + '/event-organizers/', data=data, headers=headers, ) .. Response:: { "message" : 'Event organizer created successfully' 'id' : 123 } .. HTTP Status:: 201 (Resource Created) 500 (Internal Server Error) """ organizer_data = get_valid_json_data(request) user_id = request.user.id social_network = SocialNetwork.get_by_name('Eventbrite') eventbrite = Eventbrite(user_id, social_network_id=social_network.id) organizer_id = eventbrite.create_event_organizer(organizer_data) organizer_data['social_network_organizer_id'] = organizer_id organizer_data['social_network_id'] = social_network.id organizer_data['user_id'] = user_id organizer = EventOrganizer(**organizer_data) EventOrganizer.save(organizer) headers = { 'Location': '{url}/{id}'.format(url=SocialNetworkApi.EVENT_ORGANIZERS, id=organizer.id) } return ApiResponse(dict( messsage='Event organizer created successfully', id=organizer.id), status=201, headers=headers)
def test_meetup_rsvp_importer_with_valid_token(self, user_first, talent_pool_session_scope, token_first, meetup_event_dict_second): """ - We post an RSVP on this event. We assert on response of RSVP POST. If it is in 2xx, then we run rsvp importer to import RSVP (that we just posted) in database. After importing RSVPs, we pick the imported record using social_network_rsvp_id and finally assert on the status of RSVP. It should be same as given in POST request's payload. - We add 'id' of newly created event to delete it from social network website in the finalizer of meetup_event_dict. """ event = meetup_event_dict_second['event'] with app.app_context(): social_network_event_id = event.social_network_event_id user_credentials = UserSocialNetworkCredential.get_by_user_and_social_network_id( user_first['id'], event.social_network.id) # create object of respective social network to run RSVP importer social_network = SocialNetwork.get_by_name( user_credentials.social_network.name) social_network_class = get_class(social_network.name.lower(), 'social_network', user_credentials=user_credentials) # we call social network class here for auth purpose, If token is expired # access token is refreshed and we use fresh token to make HTTP calls sn = social_network_class(user_id=user_credentials.user_id) url = '{}/rsvp/'.format(sn.api_url) payload = {'event_id': social_network_event_id, 'rsvp': 'no'} response = http_request('POST', url, params=payload, headers=sn.headers) assert response.ok is True logger.info('RSVP has been posted successfully') social_network_rsvp_id = response.json()['rsvp_id'] sn.process('rsvp', user_credentials=user_credentials) # get the imported RSVP by social_network_rsvp_id and social_network_id rsvp_in_db = RSVP.get_by_social_network_rsvp_id_and_social_network_id( social_network_rsvp_id, social_network.id) assert isinstance(rsvp_in_db, RSVP) assert rsvp_in_db.status == payload['rsvp'] response = send_request('delete', url=SocialNetworkApiUrl.EVENT % event.id, access_token=token_first) assert response.status_code == codes.OK
def test_get_social_network(token_first, eventbrite): """ This test validates that `social_network` and `social_networks` queries are working fine. it also matches eventbrite id with returned data. """ assert_valid_response('social_network', SocialNetwork, token_first, eventbrite['id'], ignore_id_test=True) fields = SocialNetwork.get_fields() query = get_query('social_network', fields, args=dict(name='Eventbrite')) response = get_graphql_data(query, token_first) assert 'errors' not in response, 'Response: %s\nQuery: %s' % (response, query) validate_graphql_response('social_network', response['data'], fields) assert response['data']['social_network']['id'] == eventbrite['id']
def put(self, social_network_id): """ Update access token for specified user and social network. :param int | long social_network_id: social network id :Example: headers = { 'Authorization': 'Bearer <access_token>', } response = requests.get( API_URL + '/social-networks/13/token/refresh', headers=headers ) .. Response:: { "message" : 'Access token has been refreshed' 'status' : true } .. HTTP Status:: 201 (Resource Created) 403 (Failed to refresh token) 500 (Internal Server Error) """ user_id = request.user.id try: social_network = SocialNetwork.get_by_id(social_network_id) if not social_network: raise ResourceNotFound("Social Network not found") # creating class object for respective social network social_network_class = get_class(social_network.name.lower(), 'social_network') sn = social_network_class(user_id=user_id) status = sn.refresh_access_token() except Exception: raise InternalServerError( "Couldn't get fresh token for specified user " "and social network") if status: return dict(messsage='Access token has been refreshed', status=True) else: raise ForbiddenError("Unable to refresh access token")
def is_token_valid(social_network_id, user_id): # Get social network specified by social_network_id social_network = SocialNetwork.get_by_id(social_network_id) if social_network: user_social_network_credential = UserSocialNetworkCredential.get_by_user_and_social_network_id( user_id, social_network_id) if user_social_network_credential: # Get social network specific Social Network class social_network_class = get_class(social_network.name, 'social_network') # create social network object which will validate # and refresh access token (if possible) sn = social_network_class(user_id=user_id, social_network_id=social_network.id) return sn.access_token_status, social_network.name return False, social_network.name else: raise ResourceNotFound("Invalid social network id given")
def import_eventbrite_event(user_id, event_url, action_type): """ This celery task retrieves user event from eventbrite and then saves or """ with app.app_context(): logger = app.config[TalentConfigKeys.LOGGER] logger.info('Going to process Eventbrite Event: %s' % event_url) try: eventbrite = SocialNetwork.get_by_name('Eventbrite') eventbrite_sn = EventbriteSocialNetwork( user_id=user_id, social_network_id=eventbrite.id) eventbrite_event_base = EventbriteEventBase( headers=eventbrite_sn.headers, user_credentials=eventbrite_sn.user_credentials, social_network=eventbrite_sn.user_credentials.social_network) if action_type in [ACTIONS['created'], ACTIONS['published']]: logger.info('Event Published on Eventbrite, Event URL: %s' % event_url) eventbrite_event_base.get_event(event_url) elif action_type == ACTIONS['unpublished']: event_id = event_url.split('/')[-2] event_id = int(event_id) event_in_db = Event.get_by_user_id_social_network_id_vendor_event_id( user_id, eventbrite.id, event_id) if event_in_db: if eventbrite_event_base.delete_event( event_in_db.id, delete_from_vendor=False): logger.info( 'Event has been marked as is_deleted_from_vendor in gt database: %s' % event_in_db.to_json()) else: logger.info( 'Event could not be marked as is_deleted_from_vendor in gt database: %s' % event_in_db.to_json()) else: logger.info( "Event unpublished from Eventbrite but it does not exist, don't worry. Event URL: %s" % event_url) elif action_type == ACTIONS['updated']: pass # We are handling update action yet because it causes duplicate entries except Exception: logger.exception('Failed to save event. URL: %s' % event_url)
def process_eventbrite_rsvp(rsvp): """ This celery task is for an individual RSVP received from Eventbrite to be processed. Response from Eventbrite API looks like { u'config': {u'action': u'order.placed', u'user_id': u'149011448333', u'endpoint_url': u'https://emails.ngrok.io/webhook/1', u'webhook_id': u'274022'}, u'api_url': u'https://www.eventbriteapi.com/v3/orders/573384540/' } :param dict rsvp: rsvp dictionary from Eventbrite """ with app.app_context(): logger = app.config[TalentConfigKeys.LOGGER] logger.info('Going to process Eventbrite RSVP: %s' % rsvp) try: eventbrite = SocialNetwork.get_by_name(EVENTBRITE) webhook_id = rsvp['config']['webhook_id'] user_credentials = UserSocialNetworkCredential.get_by_webhook_id_and_social_network_id( webhook_id, eventbrite.id) if not user_credentials: raise NoUserFound( "No User found in database that corresponds to webhook_id:%s" % webhook_id) # we make social network object here to check the validity of access token. # If access token is valid, we proceed to do the processing to save in getTalent db tables otherwise # we raise exception AccessTokenHasExpired. sn_obj = EventbriteSocialNetwork(user_id=user_credentials.user_id, social_network_id=eventbrite.id) eventbrite_rsvp_object = EventbriteRsvp( user_credentials=user_credentials, social_network=eventbrite, headers=sn_obj.headers) attendee = eventbrite_rsvp_object.process_rsvp_via_webhook(rsvp) if attendee and attendee.rsvp_id: logger.info('RSVP imported successfully. rsvp:%s' % rsvp) elif attendee: logger.info('RSVP already present in database. rsvp:%s' % rsvp) except Exception: logger.exception('Failed to save rsvp: %s' % rsvp) rollback()
def post(self, social_network_id): """ Remove access and refresh token for specified user and social network. :param int | long social_network_id: social network id :Example: headers = { 'Authorization': 'Bearer <access_token>', } response = requests.get( API_URL + '/social-networks/13/disconnect', headers=headers ) .. Response:: { "message" : 'Access token and refresh has been removed' } .. HTTP Status:: 201 (Resource Created) 404 (Social network not found) 500 (Internal Server Error) """ user_id = request.user.id social_network = SocialNetwork.get_by_id(social_network_id) if not social_network: raise ResourceNotFound("Social Network not found") # Get social network specific Social Network class social_network_class = get_class(social_network.name, 'social_network') social_network_class.disconnect(user_id, social_network) events_count = Event.disable_events(user_id, social_network.id) logger.info( 'User (id: %s) has been disconnect from %s and his %s events are marked as hidden' % (user_id, social_network.name, events_count)) return dict( messsage= 'User (id: %s) has been disconnected from social network (name: %s)' % (user_id, social_network.name))
def test_meetup_rsvp_importer_with_invalid_token(self, user_first, token_first, meetup_event_dict_second): """ - Here we post an RSVP on newly created event and assert on response of RSVP POST. It should be 2xx, then we run rsvp importer with invalid token. RSVP for this event should not be imported. - We add 'id' of newly created event to delete it from social network website in the finalizer of meetup_event_dict. """ with app.app_context(): event = meetup_event_dict_second['event'] social_network_event_id = event.social_network_event_id user_credentials = UserSocialNetworkCredential.get_by_user_and_social_network_id( user_first['id'], event.social_network.id) # create object of respective social network to run RSVP importer social_network = SocialNetwork.get_by_name( user_credentials.social_network.name) social_network_class = get_class(social_network.name.lower(), 'social_network', user_credentials=user_credentials) # we call social network class here for auth purpose, If token is expired # access token is refreshed and we use fresh token to make HTTP calls sn = social_network_class(user_id=user_credentials.user_id) url = sn.api_url + '/rsvp/' payload = {'event_id': social_network_event_id, 'rsvp': 'no'} response = http_request('POST', url, params=payload, headers=sn.headers) assert response.ok is True, "Response: {}".format(response.text) logger.info('RSVP has been posted successfully') social_network_rsvp_id = response.json()['rsvp_id'] sn.headers = {'Authorization': 'Bearer invalid_token'} logger.info('Access Token has been malformed.') # Call process method of social network class to start importing RSVPs sn.process('rsvp', user_credentials=user_credentials) # get the imported RSVP by social_network_rsvp_id and social_network_id rsvp_in_db = RSVP.get_by_social_network_rsvp_id_and_social_network_id( social_network_rsvp_id, social_network.id) assert rsvp_in_db is None
def rsvp_events_importer(social_network_name, mode, user_credentials_id, datetime_range): """ Imports RSVPs or events of a user, create candidates store them in db and also upload them on Cloud search :param str social_network_name: Facebook, Eventbrite, Meetup :param str mode: rsvp or event :param int user_credentials_id: user credentials entry :param dict datetime_range: """ with app.app_context(): logger = app.config[TalentConfigKeys.LOGGER] user_credentials = UserSocialNetworkCredential.get_by_id( user_credentials_id) user_id = user_credentials.user_id try: social_network = SocialNetwork.get_by_name( social_network_name.lower()) social_network_class = get_class(social_network.name.lower(), 'social_network', user_credentials=user_credentials) # we call social network class here for auth purpose, If token is expired # access token is refreshed and we use fresh token8 sn = social_network_class(user_id) logger.info( '%s Importer has started for %s(UserId: %s). Social Network is %s.' % (mode.title(), sn.user.name, sn.user.id, social_network.name)) # Call social network process method to start importing rsvps/event sn.process(mode, user_credentials=user_credentials, **datetime_range) # Update last_updated of each user_credentials. user_credentials.update( updated_datetime=datetime.datetime.utcnow()) except Exception as e: logger.exception( 'start: running %s importer, user_id: %s failed. %s', mode, user_id, e.message)
def test_events_post_no_event_organizer(self, token_first, test_event): """ Post event using invalid event_organizer i.e equal to -1. response should be 201 (Event organizer not found) url -> localhost:8007/v1/events """ event_data = test_event social_network_id = event_data['social_network_id'] event_data['social_network_id'] = social_network_id social_network = SocialNetwork.get_by_id(social_network_id) # test with invalid organizer event_data['organizer_id'] = -1 response = send_post_request(SocialNetworkApiUrl.EVENTS, event_data, token_first) logger.info(response.text) if social_network.name.lower() == MEETUP: assert response.status_code == codes.BAD_REQUEST, "Response: {}".format( response.text) return else: assert response.status_code == codes.CREATED, "Response: {}".format( response.text)
def post(self, social_network_id): """ Adds credentials for user for given social network. Gets data from POST request which contains 'code' and 'social_credentials' :param args: :param kwargs: :return: :Example: data = { 'code': '32432ffd2s8fd23e8saq123ds6a3da21221 } headers = { 'Authorization': 'Bearer <access_token>', 'Content-Type': 'application/json' } data = json.dumps(data) response = requests.post( API_URL + '/social-networks/13/user/credentials', data=data, headers=headers, ) .. Response:: { "message" : 'User credentials for social network were added successfully' } .. HTTP Status:: 201 (Resource Updated) 404 (Social Network not found) 500 (Internal Server Error) """ user_id = request.user.id # Get json request data req_data = get_valid_json_data(request) code = req_data['code'] social_network = SocialNetwork.get_by_id(social_network_id) # if social network does not exists, send failure message if social_network: # Get social network specific Social Network class social_network_class = get_class(social_network.name, 'social_network') credentials = social_network_class( user_id, social_network.id, validate_credentials=False).connect(code) logger.info( 'User(id:%s) has been connected successfully with %s. We are going to import events now.' % (user_id, social_network.name)) events_count = Event.enable_events(user_id, social_network.id) logger.info( 'User (id: %s) has been connected to %s and his %s events have been enabled' % (user_id, social_network.name, events_count)) sync_events.delay(credentials) return dict( message='User credentials added successfully'), codes.CREATED else: raise ResourceNotFound('Social Network not found')
def get(self): """ This action returns a list of user social networks. :Example: headers = {'Authorization': 'Bearer <access_token>'} response = requests.get(API_URL + '/venues/', headers=headers) .. Response:: { "count": 3, "social_networks": [ { "api_url": "https://api.meetup.com/2", "auth_url": "https://secure.meetup.com/oauth2", "client_key": "jgjvi3gsvrgjcp2mu9r6nb3kb0", "id": 13, "is_subscribed": true, "name": "Meetup", "redirect_uri": "http://127.0.0.1:8000/web/user/get_token", "updated_time": "", "url": "www.meetup.com/" }, { "api_url": "https://www.eventbriteapi.com/v3", "auth_url": "https://www.eventbrite.com/oauth", "client_key": "MSF5F2NUE35NQTLRLB", "id": 18, "is_subscribed": true, "name": "Eventbrite", "redirect_uri": "http://127.0.0.1:8000/web/user/get_token", "updated_time": "", "url": "www.eventbrite.com" }, { "api_url": "https://graph.facebook.com/v2.4", "auth_url": "https://graph.facebook.com/oauth", "client_key": "1709873329233611", "id": 2, "is_subscribed": false, "name": "Facebook", "redirect_uri": "", "updated_time": "", "url": "www.facebook.com/" } ] } .. HTTP Status:: 200 (OK) 500 (Internal Server Error) """ user_id = request.user.id connected_networks = request.args.get('connected_networks', '0') if connected_networks == '1': user_credentials = UserSocialNetworkCredential.get_connected_networks( request.user.id) social_networks = [ user_credential.social_network.to_json() for user_credential in user_credentials ] return dict(social_networks=social_networks) # Get list of networks user is subscribed to from UserSocialNetworkCredential table subscribed_networks = None subscribed_data = UserSocialNetworkCredential.get_by_user_id( user_id=user_id) if subscribed_data: # Get list of social networks user is subscribed to subscribed_networks = SocialNetwork.get_by_ids( [data.social_network_id for data in subscribed_data]) # Convert it to JSON subscribed_networks[0].to_json() subscribed_networks = map(lambda sn: sn.to_json(), subscribed_networks) # Add 'is_subscribed' key in each object and set it to True because # these are the social networks user is subscribed to subscribed_networks = self.set_is_subscribed(subscribed_networks, value=True) # Get list of social networks user is not subscribed to unsubscribed_networks = SocialNetwork.get_all_except_ids( [data.social_network_id for data in subscribed_data]) if unsubscribed_networks: unsubscribed_networks = map(lambda sn: sn.to_json(), unsubscribed_networks) # Add 'is_subscribed' key in each object and set it to False unsubscribed_networks = self.set_is_subscribed( unsubscribed_networks, value=False) # Now merge both subscribed and unsubscribed networks all_networks = [] if subscribed_networks: all_networks.extend(subscribed_networks) if unsubscribed_networks: all_networks.extend(unsubscribed_networks) if all_networks: for sn in all_networks: del sn['secret_key'] return dict(social_networks=all_networks, count=len(all_networks)) else: return dict(social_networks=[], count=0)
def facebook(): """ This fixture returns Social network model object for facebook in getTalent database """ return SocialNetwork.get_by_name(FACEBOOK.title())
def resolve_subscribed_social_networks(self, args, request, info): """ Resolves social networks that user has subscribed. """ return SocialNetwork.get_subscribed_social_networks(request.user.id)
def resolve_social_networks(self, args, request, info): """ Resolves all social networks in gt database. """ return SocialNetwork.get_all()
def resolve_social_network(self, args, request, info): """ Resolves social networks in gt database based on name """ name = args.get('name') return SocialNetwork.get_by_name(name)
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)
def test_eventbrite_rsvp_importer_endpoint(self, token_first, user_first, talent_pool_session_scope, user_same_domain, token_same_domain): """ Test eventbrite rsvps importer. A pre-existing rsvp is on eventbrite. - Run rsvp importer for eventbrite. - Then check if already created rsvp is imported correctly or not - Then again run rsvp importer and assert there should be only 1 rsvp - Remove user talent pool and run tests and rsvp should not be imported """ rsvp_id = '672393772' social_network_event_id = '26557579435' user_id = user_first['id'] headers = dict(Authorization='Bearer %s' % token_first) headers['Content-Type'] = 'application/json' eventbrite_obj = SocialNetwork.get_by_name('Eventbrite') usercredentials = UserSocialNetworkCredential.get_all_credentials( eventbrite_obj.id) for usercredential in usercredentials: usercredential.update(updated_datetime=None) rsvps = RSVP.filter_by_keywords( **{ 'social_network_rsvp_id': rsvp_id, 'social_network_id': eventbrite_obj.id }) for rsvp in rsvps: RSVP.delete(rsvp.id) """---------------------------Get or Import event for eventbrite-------------------------------""" event = Event.get_by_user_and_social_network_event_id( user_id=user_id, social_network_event_id=social_network_event_id) # If event is not imported then run event importer and import events first if not event: # Import events first then import RSVPs response = requests.post(url=SocialNetworkApiUrl.IMPORTER % ('event', 'eventbrite'), headers=headers) assert response.status_code == codes.OK retry(assert_event, args=(user_id, social_network_event_id), sleeptime=15, attempts=15, sleepscale=1, retry_exceptions=(AssertionError, )) eventbrite_event = Event.get_by_user_and_social_network_event_id( user_id, social_network_event_id) assert eventbrite_event """------------------------------------------------------------------------------------------------ -----------------------------SECTION: Import RSVPs for User 1-------------------------------------- """ response = requests.post(url=SocialNetworkApiUrl.IMPORTER % ('rsvp', 'eventbrite'), data=json.dumps({}), headers=headers) assert response.status_code == codes.OK # Check if rsvp is imported for user 1 def f(_rsvp_id, _eventbrite_id, event_id, count=1): db.db.session.commit() _rsvp = RSVP.filter_by_keywords( **{ 'social_network_rsvp_id': _rsvp_id, 'social_network_id': _eventbrite_id, 'event_id': event_id }) assert len(_rsvp) == count retry(f, sleeptime=15, attempts=15, sleepscale=1, retry_exceptions=(AssertionError, ), args=(rsvp_id, eventbrite_obj.id, eventbrite_event.id)) """------------------------------------------------------------------------------------------------ Get RSVP for user id 2, which shouldn't be imported due to talent pool attached """ db.db.session.commit() eventbrite_event_user_second = Event.get_by_user_and_social_network_event_id( user_same_domain['id'], social_network_event_id) assert eventbrite_event_user_second retry(f, sleeptime=15, attempts=15, sleepscale=1, retry_exceptions=(AssertionError, ), args=(rsvp_id, eventbrite_obj.id, eventbrite_event_user_second.id, 0)) """------------------------------------------------------------------------------------------------ ----------------SECTION: Import RSVPs again and rsvps shouldn't be redundant------------------------ """ # Run rsvp importer again and data should not be redundant. response = requests.post(url=SocialNetworkApiUrl.IMPORTER % ('rsvp', 'eventbrite'), data=json.dumps({}), headers=headers) assert response.status_code == codes.OK retry(f, sleeptime=15, attempts=15, sleepscale=1, retry_exceptions=(AssertionError, ), args=(rsvp_id, eventbrite_obj.id, eventbrite_event.id)) rsvp = RSVP.get_by_social_network_rsvp_id_and_social_network_id( rsvp_id, eventbrite_obj.id) RSVP.delete(rsvp.id)
def process_meetup_event(event): """ This celery task is for an individual event to be processed. When `rsvp_events_importer` task finds that some event belongs to getTalent user, it passes this event to this task for further processing. In this task, we create meetup objects for social network and event and the finally save this event by mapping meetup event fields to gt event fields. If event already exists in database, it is updated. If an event contains venue information, is is save in `venue` table or updated an existing venue. :param dict event: event dictionary from meetup """ with app.app_context(): logger = app.config[TalentConfigKeys.LOGGER] # if same event is received multiple times, accept first and reject remaining meetup_event_lock_key = json.dumps(event) if not redis_store.get(meetup_event_lock_key): # set lock for 5 minutes redis_store.set(meetup_event_lock_key, True, 5 * 60) else: logger.info('Already received this Meetup Event: %s.' % event) return 'Done' logger.info('Going to process Meetup Event: %s' % event) try: time.sleep( 5 ) # wait for event creation api to save event in database otherwise there can be duplicate # event created in database (one by api and other by importer) groups = MeetupGroup.get_all_records_by_group_id( event['group']['id']) meetup = SocialNetwork.get_by_name('Meetup') # have to change in try catch as well try: meetup_sn = MeetupSocialNetwork(user_id=groups[0].user.id, social_network_id=meetup.id) except HitLimitReached: meetup_sn = MeetupSocialNetwork(user_id=groups[0].user.id, social_network_id=meetup.id, validate_token=False) meetup_event_base = Meetup( user_credentials=meetup_sn.user_credentials, social_network=meetup, headers=meetup_sn.headers) if event['status'] in [ MEETUP_EVENT_STATUS['upcoming'], MEETUP_EVENT_STATUS['suggested'], MEETUP_EVENT_STATUS['proposed'] ]: event_data = meetup_event_base.fetch_event(event['id']) gt_event_data, gt_venue_data = meetup_event_base.event_sn_to_gt_mapping( event_data) for group_user in groups: try: group_user_credentials = UserSocialNetworkCredential.get_by_user_and_social_network_id\ (group_user.user.id, meetup.id) meetup_event_obj = Meetup( user_credentials=group_user_credentials, social_network=meetup, headers=meetup_sn.headers) if gt_venue_data: gt_venue_data['user_id'] = group_user.user_id venue_in_db = meetup_event_obj.save_or_update_venue( gt_venue_data) gt_event_data['venue_id'] = venue_in_db.id gt_event_data['user_id'] = group_user.user_id meetup_event_obj.save_or_update_event(gt_event_data) except Exception as e: logger.error( "An error occured while saving event, error: %s" % e) elif event['status'] in [ 'canceled', MEETUP_EVENT_STATUS['deleted'] ]: social_network_event_id = event['id'] for group_user in groups: try: event_in_db = Event.get_by_user_id_social_network_id_vendor_event_id( group_user.user_id, meetup.id, social_network_event_id) if event_in_db: meetup_event_base.user = group_user.user if meetup_event_base.delete_event( event_in_db.id, delete_from_vendor=False): logger.info( 'Meetup event has been marked as is_deleted_from_vendor in gt database: %s' % event_in_db.to_json()) else: logger.info( 'Event could not be marked as is_deleted_from_vendor in gt database: %s' % event_in_db.to_json()) else: logger.info( "Meetup event not found in database. event:`%s`." % event) except Exception as e: logger.error( "An error occured while marking event deleted, error: %s" % e) except Exception: logger.exception('Failed to save event: %s' % event) rollback()
def process_event(data, user_id, method='Create'): """ This functions is called from restful POST service (which gets data from Event Create Form submission). It creates event on vendor as well as saves in database. Data in the arguments is the Data coming from Event creation form submission user_id is the id of current logged in user (which we get from session). :return: id of event :rtype: int """ if data: social_network_id = data.get('social_network_id', 0) 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') event_class = get_class(social_network.name.lower(), 'event') sn = social_network_class(user_id=user_id) event_obj = event_class(user=sn.user, headers=sn.headers, social_network=social_network) else: raise SocialNetworkError('Unable to find social network') data['user_id'] = user_id if social_network.name.lower() == MEETUP and data.get('organizer_id'): raise InvalidUsage( 'organizer_id is not a valid field in case of meetup') event_obj.event_gt_to_sn_mapping(data) activity_data = {'username': request.user.name} if method == 'Create': event_id = event_obj.create_event() # Create activity of event object creation event_obj = Event.get_by_user_and_event_id(user_id=user_id, event_id=event_id) activity_data.update({'event_title': event_obj.title}) add_activity(user_id=user_id, activity_type=Activity.MessageIds.EVENT_CREATE, source_id=event_id, source_table=Event.__tablename__, params=activity_data) return event_id else: event_id = event_obj.update_event() # Create activity of event object creation event_obj = Event.get_by_user_and_event_id(user_id=user_id, event_id=event_id) activity_data.update({'event_title': event_obj.title}) add_activity(user_id=user_id, activity_type=Activity.MessageIds.EVENT_UPDATE, source_id=event_id, source_table=Event.__tablename__, params=activity_data) return event_id else: error_message = 'Data not received from Event Creation/Edit FORM' log_error({'user_id': user_id, 'error': error_message})
def process_meetup_rsvp(rsvp): """ This celery task is for an individual rsvp to be processed. When `meetup_rsvp_importer` task finds that some rsvp belongs to event of getTalent's user, it passes this rsvp to this task for further processing. In this task, we create meetup objects for social network and event and the finally save this event by mapping meetup event fields to gt event fields. If event already exists in database, it is updated. Response from Meetup API looks like { u'group': {u'group_city': u'Denver', u'group_lat': 39.68, u'group_urlname': u'denver-metro-chadd-support', u'group_name': u'Denver-Metro CHADD (Children and Adults with ADHD) Meetup', u'group_lon': -104.92, u'group_topics': [ {u'topic_name': u'ADHD', u'urlkey': u'adhd'}, {u'topic_name': u'ADHD Support', u'urlkey': u'adhd-support'}, {u'topic_name': u'Adults with ADD', u'urlkey': u'adults-with-add'}, {u'topic_name': u'Families of Children who have ADD/ADHD', u'urlkey': u'families-of-children-who-have-add-adhd'}, {u'topic_name': u'ADHD, ADD', u'urlkey': u'adhd-add'}, {u'topic_name': u'ADHD Parents with ADHD Children', u'urlkey': u'adhd-parents-with-adhd-children'}, {u'topic_name': u'Resources for ADHD', u'urlkey': u'resources-for-adhd'}, {u'topic_name': u'Parents of Children with ADHD', u'urlkey': u'parents-of-children-with-adhd'}, {u'topic_name': u'Support Groups for Parents with ADHD Children', u'urlkey': u'support-groups-for-parents-with-adhd-children'}, {u'topic_name': u'Educators Training on AD/HD', u'urlkey': u'educators-training-on-ad-hd'}, {u'topic_name': u'Adults with ADHD', u'urlkey': u'adults-with-adhd'} ], u'group_state': u'CO', u'group_id': 1632579, u'group_country': u'us' }, u'rsvp_id': 1639776896, u'venue': {u'lat': 39.674759, u'venue_id': 3407262, u'lon': -104.936317, u'venue_name': u'Denver Academy-Richardson Hall'}, u'visibility': u'public', u'event': {u'event_name': u'Manage the Impact of Technology on Your Child and Family with Lana Gollyhorn', u'event_id': u'235574682', u'event_url': u'https://www.meetup.com/denver-metro-chadd-support/events/235574682/', u'time': 1479778200000}, u'member': {u'member_name': u'Valerie Brown', u'member_id': 195674019}, u'guests': 0, u'mtime': 1479312043215, u'response': u'yes' } :param dict rsvp: rsvp dictionary from Meetup """ with app.app_context(): logger = app.config[TalentConfigKeys.LOGGER] logger.info('Going to process Meetup RSVP: %s' % rsvp) try: group = MeetupGroup.get_all_records_by_group_id( rsvp['group']['group_id']) meetup = SocialNetwork.get_by_name(MEETUP) social_network_event_id = rsvp['event']['event_id'] for group_user in group: # Retry for 20 seconds in case we have RSVP for newly created event. retry(_get_event, args=(group_user.user_id, meetup.id, social_network_event_id), sleeptime=5, attempts=6, sleepscale=1, retry_exceptions=(EventNotFound, )) meetup_sn = MeetupSocialNetwork(user_id=group_user.user.id, social_network_id=meetup.id) meetup_rsvp_object = MeetupRsvp( user_credentials=meetup_sn.user_credentials, social_network=meetup, headers=meetup_sn.headers) meetup_rsvp_object.rsvp_via_importer = False attendee = meetup_rsvp_object.post_process_rsvp(rsvp) if attendee and attendee.rsvp_id: logger.info('RSVP imported successfully. rsvp:%s' % rsvp) elif attendee: logger.info('RSVP already present in database. rsvp:%s' % rsvp) except Exception: logger.exception('Failed to save rsvp: %s' % rsvp) rollback()