示例#1
0
 def save_event(self):
     """
     This method takes dictionary containing event data. It first checks if
     any event is there with given info (user_id, social_network_id,
     social_network_event_id), then it updates the existing event otherwise
     creates a new event in getTalent database.
     Call this method after successfully publishing event on social network.
     :return event.id: id for event in getTalent database, that was created or updated
     :rtype event.id : int
     """
     data = self.data
     sn_event_id = data['social_network_event_id']
     social_network_id = data['social_network_id']
     event = Event.get_by_user_id_social_network_id_vendor_event_id(
         self.user.id, social_network_id, sn_event_id)
     try:
         # if event exists in database, then update existing one.
         if event:
             del data['id']
             event.update(**data)
         else:
             # event not found in database, create a new one
             event = Event(**data)
             Event.save(event)
     except Exception as error:
         logger.exception(
             'save_event: Event was not updated/saved in Database. '
             'user_id: %s, event_id: %s, social network: %s(id: %s). Error:%s'
             % (self.user.id, event.id, self.social_network.name,
                self.social_network.id, error.message))
         raise EventNotSaveInDb(
             'Error occurred while saving event in database')
     return event.id
示例#2
0
    def authenticate(self):
        """
        Here we use OAuthHandler of tweepy to give us request token. We use that request token and
        redirect the user to Twitter website where user can add its credentials.
        Once user is successfully logged-in, user is again redirected to URL as specified by callback URL of
        OAuthHandler which is http://127.0.0.1:8007/v1/twitter-callback/<int:user_id> (for local environment)
        in this case.
        In case of failure, we log the error and raises InternalServerError.

        This method is called from endpoint http://127.0.0.1:8007/v1/twitter-auth.
        """
        try:

            # redirect_url takes the user to login-page of Twitter to authorize getTalent app.
            redirect_url = self.auth.get_authorization_url()
            # Once user is successfully logged-in to Twitter account, it is redirected to callback URL where
            # we need to exchange request token with access token. This access token is used to access Twitter API.
            # So, we save request_token in the redis and retrieve this in callback() method.
            redis_store.set('twitter_request_token_%s' % self.user.id,
                            json.dumps(self.auth.request_token))
            # redirect the user to Twitter website for authorization.
            return redirect_url
        except tweepy.TweepError as error:
            logger.exception(
                'Error! Failed to get request token from Twitter for User(id:%s).\nError:%s'
                % (self.user.id, error.message))
            raise InternalServerError("Couldn't connect to Twitter account.")
示例#3
0
 def delete_event(self, event_id, delete_from_vendor=True):
     """
     Here we pass an event id, picks it from db, and try to delete
     it both from social network and database. If successfully deleted
     from both sources, returns True, otherwise returns False.
     :param event_id: is the 'id' of event present in our db
     :type event_id: int or long
     :param delete_from_vendor: is flag to delete event from third party
     :type delete_from_vendor: bool
     :return: True if deletion is successful, False otherwise.
     :rtype: bool
     """
     event = Event.get_by_user_and_event_id(self.user.id, event_id)
     if event:
         try:
             if delete_from_vendor:
                 self.unpublish_event(event.social_network_event_id)
             self.archive_email_campaigns_for_deleted_event(
                 event, delete_from_vendor)
             return True
         except Exception:  # some error while removing event
             logger.exception(
                 'delete_event: user_id: %s, event_id: %s, social network: %s(id: %s)'
                 % (self.user.id, event.id, self.social_network.name,
                    self.social_network.id))
     return False  # event not found in database
示例#4
0
 def process_events(self, events):
     """
     :param list events: contains events of a particular user for a specific social network.
     This is the function to process events once we have the events of some social network. It first maps the
     social network fields to gt-db fields. Then it checks if the event is present is db or not.
     If event is already in db, it updates the event fields otherwise it stores the event in db.
     Finally we import RSVPs of all the events in method post_process_events().
     """
     if events:
         self.pre_process_events(events)
     if events:
         logger.info(
             'Events of %s(UserId: %s) are being processed to save in database.'
             % (self.user.name, self.user.id))
         for event in events:
             try:
                 self.events.append(self.import_event(event))
             except Exception:
                 logger.exception(
                     '''Error occurred while importing event.
                                     UserId: %s,
                                     SocialNetworkId: %s
                                     Event: %s
                                  ''' %
                     (self.user.id, self.social_network.id, event))
     self.mark_vendor_deleted(events)
     if events:
         self.post_process_events()
示例#5
0
    def get_access_and_refresh_token(cls, user_id, social_network, code_to_get_access_token=None, method_type=None,
                                     payload=None, params=None, api_relative_url=None):
        """
        This function is used by Social Network API to save 'access_token' and 'refresh_token' for specific
        social network against a user (current user) by sending an POST call to respective social network API.
        :param user_id: current user id
        :param social_network: social_network in getTalent database
        :param code_to_get_access_token: Code which is exchanged for an access token.
        :param method_type: In case of Eventbrite, need to make a 'POST' call to get access token.
        :param payload: is set inside this method and is passed in super constructor. This is sent in body
                        of HTTP request.
        :param params: dictionary of data to send in the url params.
        :param api_relative_url: This variable is set in this function and is passed in super constructor to make
                                HTTP request.
        :type user_id: int
        :type social_network: common.models.social_network.SocialNetwork
        :type code_to_get_access_token: str
        :type method_type: str
        :type payload: dict
        :type payload: dict
        :type api_relative_url: str
        :return: returns access token and refresh token
        :rtype: tuple (str, str)
        """
        logger.info('Getting "access_token and refresh_token" of user_id:%s using API of %s.'
                    % (user_id, social_network.name))
        url = social_network.auth_url + api_relative_url
        get_token_response = http_request(method_type, url, data=payload, user_id=user_id, params=params)
        try:
            if get_token_response.ok:
                # access token is used to make API calls, this is what we need
                # to make subsequent calls
                try:
                    response = get_token_response.json()
                    access_token = response.get('access_token')
                    # refresh token is used to refresh the access token
                    refresh_token = response.get('refresh_token')
                except ValueError:
                    if 'facebook' in social_network.api_url:
                        # In case of Facebook, access_token is retrieved as follows
                        access_token = \
                            get_token_response.content.split('=')[1].split('&')[0]
                        refresh_token = ''
                    else:
                        raise
                return access_token, refresh_token
            else:
                log_error({'user_id': user_id, 'error': get_token_response.json().get('error')})
                raise SNServerException('Unable to to get access token for current user')

        except:
            logger.exception('get_access_and_refresh_token: user_id: %s, social network: %s(id: %s)'
                             % (user_id, social_network.name, social_network.id))
            raise SNServerException('Unable to create user credentials for current user')
示例#6
0
    def get_all_pages(self, response, target_list):
        """
         :param response: dictionary containing data after a request is made.
         :param target_list: list in which items to be appended after getting
                from different pages/requests
         :type response: requests.Response
         :type target_list: list

        - This method is used to get the paginated data.
          To get all data about event attendees, event rsvps etc we need to send multiple
          request because facebook sends data in pages or we can say chunks, some specific number
          of records in a single request and a url to next page (resources).
          So to get all pages data call this method and pass first request response and
          target list in which data is to be appended.
          It will send request to get next page given in this request "next" attribute/Key
           and will continue until no next page is there to fetch.

            :Example:

                try:
                    # get those attendees who have confirmed their presence
                    expected_attendees = self.graph.get_object(url + 'confirm')
                except facebook.GraphAPIError as error:
                    # handle errors here
                    pass
                rsvps += expected_attendees['data']
                self.get_all_pages(expected_attendees, rsvps)

                It will add all confirm rsvps in "rsvps" list which was passed as target.

        **See Also**
            .. seealso:: process_rsvps() method in RSVPBase class inside
            social_network_service/rsvp/base.py for more insight.

        :return: attendee object which contains data about the candidate
        """
        while True:
            try:
                response = requests.get(response['paging']['next'])
                if response.ok:
                    response = response.json()
                    if 'data' in response:
                        target_list.extend(response['data'])
            except KeyError:
                break
            except requests.HTTPError as error:
                error_message_dict = dict(url=response['paging']['next'],
                                          error_message=error.message)
                error_message = "Couldn't get data while paginating over " \
                                "Facebook records. URL: %(url)s, " \
                                "%(error_message)s" % error_message_dict
                logger.exception("get_all_pages: %s, user_id: %s" %
                                 (error_message, self.user.id))
                raise
示例#7
0
    def save_attendee_source(self, attendee):
        """
        :param attendee: attendees is a utility object we share in calls that
                 contains pertinent data.
        :type attendee: object of class Attendee defined in utilities.py

        - This method checks if the event is present in candidate_source db
         table. If does not exist, it adds record, otherwise updates the
         record. It then appends id of source in attendee object to be saved in
         candidate table.

        - This method is called from process_rsvps() defined in
          RSVPBase class inside social_network_service/rsvp/base.py.

        - We use this method while importing RSVPs through social network

        :Example:

            attendee = self.save_attendee_source(attendee)

        **See Also**
            .. seealso:: process_rsvps() method in EventBase class
        :return attendee:
        :rtype: Attendee
        """
        attendee.event.description = attendee.event.description[:1000].encode('utf-8') if attendee.event.description \
            else 'Not given'
        candidate_source = {
            "source": {
                "description": attendee.event.description,
                "notes": attendee.event.title
            }
        }
        access_token = User.generate_jw_token(user_id=self.user.id)
        header = {
            'Content-Type': 'application/json',
            'Authorization': access_token
        }
        response = http_request('POST', UserServiceApiUrl.DOMAIN_SOURCES, headers=header,
                                data=json.dumps(candidate_source))
        # Source already exists
        if response.status_code == requests.codes.bad:
            attendee.candidate_source_id = response.json()['error']['source_id']
        elif response.status_code != requests.codes.created:
            logger.exception(response.text)
            raise InternalServerError(error_message="Error while creating candidate source")
        else:
            attendee.candidate_source_id = response.json()['source']['id']

        return attendee
示例#8
0
    def process(self, mode, user_credentials=None, **kwargs):
        """
        :param mode: mode is either 'event' or 'rsvp.
        :param user_credentials: are the credentials of user for
                                    a specific social network in db.
        :type mode: str
        :type user_credentials: common.models.user.UserSocialNetworkCredential

        - Depending upon the mode, here we make the objects of required
            classes (Event Class or RSVP class) and call required methods on
            those objects for importing events or rsvps.

        - This method is called from start() defined in social network manager
            inside social_network_service/manager.py.

        :Example:
                from social_network_service.meetup import Meetup
                sn = Meetup(user_id=1)
                sn.process('event', user_credentials=user_credentials)

        **See Also**
        .. seealso:: start() function defined in social network manager
            inside social_network_service/manager.py.
        """
        user_id = self.user.id
        social_network_id = self.social_network.id
        social_network_name = self.social_network.name
        try:
            sn_name = self.social_network.name.strip()
            # get_required class under social_network_service/event/ to process events
            event_class = get_class(sn_name, 'event')
            # create object of selected event class
            sn_event_obj = event_class(user_credentials=user_credentials, social_network=self.social_network,
                                       headers=self.headers, **kwargs)
            if mode == EVENT:
                # gets events using respective API of Social Network
                logger.info('Getting event(s) of %s(UserId:%s) from %s website.' % (self.user.name, self.user.id,
                                                                                    self.social_network.name))
                self.events = sn_event_obj.get_events()
                logger.info('Got %s live event(s) of %s(UserId: %s) on %s within provided time range.'
                             % (len(self.events), self.user.name, self.user.id, self.social_network.name))
                # process events to save in database
                sn_event_obj.process_events(self.events)
            elif mode == RSVP:
                sn_event_obj.process_events_rsvps(user_credentials, headers=self.headers,
                                                  social_network=self.social_network)
        except Exception:
            logger.exception('process: running %s importer, user_id: %s, social network: %s(id: %s)'
                             % (mode, user_id, social_network_name, social_network_id))
示例#9
0
 def create_webhook(cls, user_credentials):
     """
     :param user_credentials: User's social network credentials for which
             we need to create webhook. Webhook is created to be updated
             about any RSVP on an
             event of Eventbrite.
     :type user_credentials:  common.models.user.UserSocialNetworkCredential
     - This method creates a webhook to stream the live feed of RSVPs of
         Eventbrite events to the getTalent app. Once we have the webhook
         id for given user, we update user credentials in db.
     - It also performs a check which ensures that webhook is not generated
         every time code passes through this flow once a webhook has been
         created for a user (since webhook don't expire and are unique for
         every user).
     - This method is called from save_user_credentials_in_db() defined in
         Eventbrite class inside social_network_service/eventbrite.py.
     **See Also**
     .. seealso:: save_user_credentials_in_db() function defined in Eventbrite
         class inside social_network_service/eventbrite.py.
     .. seealso:: get_access_and_refresh_token() function defined in Eventbrite
         class inside social_network_service/eventbrite.py.
     """
     url = user_credentials.social_network.api_url + "/webhooks/"
     payload = {
         'endpoint_url':
         SocialNetworkApiUrl.WEBHOOK % user_credentials.user_id,
         'actions':
         ','.join([
             ACTIONS['published'], ACTIONS['unpublished'], ACTIONS['rsvp']
         ])
     }
     headers = {'Authorization': 'Bearer ' + user_credentials.access_token}
     response = http_request('POST',
                             url,
                             params=payload,
                             headers=headers,
                             user_id=user_credentials.user.id)
     try:
         webhook_id = response.json()['id']
         user_credentials.update(webhook=webhook_id)
     except Exception:
         logger.exception('create_webhook: user_id: %s' %
                          user_credentials.user.id)
         raise InternalServerError(
             "Eventbrite Webhook wasn't created successfully")
示例#10
0
    def callback(self, oauth_verifier):
        """
        This method is called from endpoint http://127.0.0.1:8007/v1/twitter-callback/<int:user_id>
        defined in app.py.
        Here we use "oauth_verifier" to get access token for the user.
        If we get any error in getting access token, we log the error and raise InternalServerError.

        Once we have the access_token, we get the member_id (id of getTalent user on Twitter's website) of user
        from Twitter API and save its credentials in database table "UserSocialNetworkCredential".

        :param string oauth_verifier: Token received from Twitter when user successfully connected to its account.
        """
        self.auth.request_token = json.loads(
            redis_store.get('twitter_request_token_%s' % self.user.id))
        redis_store.delete('twitter_request_token_%s' % self.user.id)
        try:
            self.auth.get_access_token(oauth_verifier)
        except tweepy.TweepError as error:
            logger.exception(
                'Failed to get access token from Twitter for User(id:%s). \nError: %s'
                % (self.user.id, error.message))
            raise InternalServerError(
                'Failed to get access token from Twitter')

        access_token = self.auth.access_token
        # This may be used later
        # access_token_secret = self.auth.access_token_secret
        api = tweepy.API(self.auth)
        twitter_user = api.me()
        user_credentials = UserSocialNetworkCredential.get_by_user_and_social_network_id(
            self.user.id, self.social_network.id)
        if not user_credentials:
            user_credentials_obj = UserSocialNetworkCredential(
                user_id=self.user.id,
                social_network_id=self.social_network.id,
                member_id=twitter_user.id,
                access_token=access_token)
            UserSocialNetworkCredential.save(user_credentials_obj)

        logger.info(
            'User(id:%s) is now connected with Twitter. Member id on twitter is %s'
            % (self.user.id, twitter_user.id))
        return redirect(get_web_app_url())
示例#11
0
    def get_events(self):
        """
        This method retrieves events from facebook through its Graph API and
        saves in database.
        We send GET requests to API URL and get data. We also
        have to handle pagination because Facebook's API
        sends paginated response.
        :return: all events of getTalent user on Facebook within specified
            time range
        :rtype: list

            :Example:

                create facebook object and call get_events on it
                facebook = Facebook(user=gt_user,
                                    headers=auth_headers)
                facebook.get_events()
        """
        self.graph = facebook.GraphAPI(access_token=self.access_token)
        all_events = []
        user_events = []
        # https://developer.facebook.com to see detail on params
        try:
            response = self.graph.get_object(
                'v2.4/me/events',
                fields='is_viewer_admin, description, name, category, owner, '
                'place, start_time, ticket_uri, end_time, parent_group, '
                'attending_count, maybe_count, noreply_count, timezone',
                since=self.start_date,
                until=self.end_date)
        except facebook.GraphAPIError:
            logger.exception('get_events: user_id: %s' % self.user.id)
            raise
        if 'data' in response:
            user_events.extend(response['data'])
            self.get_all_pages(response, user_events)
        # Need only events user is an admin of
        user_events = filter(lambda event: event['is_viewer_admin'] is True,
                             user_events)
        all_events.extend(user_events)
        return all_events
示例#12
0
 def get_all_pages(self, response, target_list):
     """
     We keep iterating over pages as long as keep finding the URL
     in response['paging']['next'].
     :param response:
     :param target_list:
     :type response: dict
     :type target_list: list
     """
     while True:
         try:
             response = requests.get(response['paging']['next'])
             if response.ok:
                 response = response.json()
             if response and response['data']:
                 target_list.extend(response['data'])
         except KeyError:
             break
         except requests.HTTPError:
             logger.exception('get_all_pages: user_id: %s' % self.user.id)
             raise
示例#13
0
 def archive_email_campaigns_for_deleted_event(self, event,
                                               deleted_from_vendor):
     """
     Whenever an event is deleted from social-network, we update field `is_deleted_from_vendor` to 1.
     We then check if it was promoted via email-campaign to getTalent candidates and mark all linked email-campaigns
     as archived.
     :param Event event: Event object
     :param bool deleted_from_vendor: flag to mark 'is_deleted_from_vendor' field true or false
     """
     # if deleted_from_vendor is True, it means we are directly deleting event from our api call not from third party
     # social network that's why we need to un-publish
     # event from social network and will also mark is_hidden=1.
     if deleted_from_vendor:
         event.update(is_deleted_from_vendor=1, is_hidden=1)
     else:
         event.update(is_deleted_from_vendor=1)
     base_campaign_events = event.base_campaign_event
     for base_campaign_event in base_campaign_events:
         base_campaign = base_campaign_event.base_campaign
         email_campaigns = base_campaign.email_campaigns.all()
         for email_campaign in email_campaigns:
             data = {'is_hidden': 1}
             try:
                 response = http_request('patch',
                                         EmailCampaignApiUrl.CAMPAIGN %
                                         email_campaign.id,
                                         headers=self.gt_headers,
                                         data=json.dumps(data))
                 if response.ok:
                     logger.info(
                         'Email campaign(id:%s) has been archived successfully.'
                         % email_campaign.id)
                 else:
                     logger.info(
                         'Email campaign(id:%s) could not be archived.' %
                         email_campaign.id)
             except Exception:
                 logger.exception(
                     'Email campaign(id:%s) could not be archived.' %
                     email_campaign.id)
示例#14
0
    def save_user_credentials_in_db(cls, user_credentials):
        """
        :param user_credentials: user's social network credentials
        :type user_credentials: dict

        - It checks if user_credentials are already in database. If a record
            is found, it updates the record otherwise it saves as new record.

        - It is called e.g. from refresh_access_token() inside
            social_network_service/meetup.py

        :Example:
                from social_network_service.meetup import Meetup
                sn = Meetup(user_id=1)
                sn.save_user_credentials_in_db(data)

        **See Also**
        .. seealso:: refresh_access_token() method of Meetup class
            inside social_network_service/meetup.py

        :return user's social network credentials
        :rtype: common.models.user.UserCredentials
        """
        user_credentials_in_db = UserSocialNetworkCredential.get_by_user_and_social_network_id(
            user_credentials['user_id'], user_credentials['social_network_id'])
        try:
            if user_credentials_in_db:
                user_credentials_in_db.update(**user_credentials)
            else:
                user_credentials_in_db = UserSocialNetworkCredential(**user_credentials)
                UserSocialNetworkCredential.save(user_credentials_in_db)
            return user_credentials_in_db
        except:
            logger.exception('save_user_credentials_in_db: user_id: %s',
                             user_credentials['user_id'])
            raise SNServerException('APIError: Unable to create user credentials')
示例#15
0
    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
示例#16
0
    def post_process_rsvp(self, rsvp):
        """
        :param dict rsvp: is likely the response from social network API.

        ** Working **
             - Here we do the following steps
                a)- We move on to get attendee using the given rsvp by
                    get_attendees() call. "attendees" is a utility object we
                    share in calls that contains pertinent data. get_attendee()
                    should be implemented by a child.
                b)- We pick the source product of RSVP (e.g. meetup or
                    eventbrite).
                c)- We store the source of candidate in candidate_source db
                    table.
                d)- Once we have the attendees data we call
                    save_attendee_as_candidate() which stores each attendee as
                    a candidate.
                e)- Finally we save the RSVP in following tables
                    1- rsvp
                    3- Activity

        - This method is called from process_rsvps() defined in
            RSVPBase class inside social_network_service/rsvp/base.py.

        - We use this method while importing RSVPs through social network
        # TODO: Through nightly script which fetches data from different social networks

        :Example:
            - rsvp_obj = Meetup(social_network=self.social_network,
                            headers=self.headers,
                            user_credentials=user_credentials)
            - event = Event.get_by_id(1)
            - rsvps = rsvp_obj.get_rsvps(event)
            - rsvp_obj.post_process_rsvps(rsvps[0])

        **See Also**
        .. seealso:: process_events_rsvps() method in EventBase class social_network_service/event/base.py
        """
        self.user = db.session.merge(self.user)
        self.social_network = db.session.merge(self.social_network)

        try:
            attendee = self.get_attendee(rsvp)
            if not attendee:
                logger.info('Attendee object couldn\'t be created because event is not imported yet. RSVP data: %s'
                            % rsvp)
                return
            # following picks the source product id for attendee
            attendee = self.pick_source_product(attendee)
            # following will store candidate info in attendees
            attendee = self.save_attendee_source(attendee)
            # following will store candidate info in attendees
            attendee = self.save_attendee_as_candidate(attendee)
            # following call will store rsvp info in attendees
            attendee = self.save_rsvp(attendee)
            # finally we store info in table activity
            attendee = self.save_rsvp_in_activity_table(attendee)
            return attendee
        except Exception:
            # Shouldn't raise an exception, just log it and move to process next RSVP
            logger.exception('post_process_rsvps: user_id: %s, RSVP data: %s, social network: %s(id:%s)'
                             % (self.user.id, rsvp, self.social_network.name, self.social_network.id))
示例#17
0
    def get_all_rsvps(self, events):
        """
        :param events: events contains all the events of a particular
                       user present in database table "event".
        :type events: list

        ** Working **
            - We go over each event one by one and get RSVPs of that event.
                This is done in the get_rsvps() method which fetches RSVPs
                and attach them to rsvps list of dicts.

        :Example:

        If we are importing rsvps of social network meetup, then we create
        RSVP class object in EventBase class method process_events_rsvps() as

        sn_rsvp_obj = sn_rsvp_class(social_network=self.social_network,
                                    headers=self.headers,
                                    user_credentials=user_credentials)

        Then we call get_all_rsvps() on sn_rsvp_obj by passing events in
        parameters as follow

            self.rsvps = sn_rsvp_obj.get_all_rsvps(self.events)

        :return: It appends rsvps of all events of a particular user in
            self.rsvps and returns it.

        - We use this method inside process_events_rsvps() defined in
            EventBase class inside social_network_service/event/base.py.

        - We use this method while importing RSVPs through social_network either by direct hitting endpoint or
        by running an hourly job scheduled by scheduler service.
        **See Also**
            .. seealso:: process_events_rsvps() method in EventBase class
            inside social_network_service/event/base.py
        """
        if events:
            logger.info('Getting RSVPs for events of %s(UserId: %s) from %s website.'
                        % (self.user.name, self.user.id, self.social_network.name))
            for event in events:
                # events is a list of dicts where each dict is likely a
                # response return from the database.
                # We pick one event from events_list, and get its rsvps
                # from respective social network.
                try:
                    rsvps = self.get_rsvps(event)
                    # rsvps is a list of dicts, where each dict is likely a response returned from the
                    # social network side.
                    if rsvps:
                        # appends RSVPs of all events in self.rsvps
                        self.rsvps += rsvps
                except Exception as error:
                    # Shouldn't raise an exception, just log it and move to get RSVPs of next event
                    logger.exception('get_all_rsvps: user_id: %s, event_id: %s, social network: %s(id:%s)'
                                     % (self.user.id, event.id, self.social_network.name, self.social_network.id))
                    if hasattr(error, 'response'):
                        if error.response.status_code == codes.UNAUTHORIZED:
                            # Access token is Invalid, Stop the execution.
                            break
            logger.info('There are %d RSVPs to process for events of %s(UserId: %s).'
                        % (len(self.rsvps), self.user.name, self.user.id))
        return self.rsvps
示例#18
0
    def get_attendee(self, rsvp):
        """
        :param rsvp: rsvp is likely the response of social network API.
        :type rsvp: dict
        :return: attendee
        :rtype: object

        - This function is used to get the data of candidate related
          to given rsvp. It attaches all the information in attendee object.
          attendees is a utility object we share in calls that contains
          pertinent data.

        - This method is called from process_rsvps() defined in
          RSVPBase class.

        :Example:

            attendee = self.get_attendee(rsvp)

        **See Also**
            .. seealso:: process_rsvps() method in RSVPBase class inside
            social_network_service/rsvp/base.py for more insight.
        """
        try:
            data = self.graph.get_object('v2.4/' + rsvp['id'],
                                         fields='first_name, last_name, name, '
                                         'email, location, address, '
                                         'link, picture')
        except facebook.GraphAPIError:
            logger.exception(
                "get_attendee: Couldn't get Facebook's attendee info. "
                "user_id: %s, social_network_rsvp_id: %s" %
                (self.user.id, rsvp['id']))
            raise
        if 'location' in data:
            try:
                location = self.graph.get_object('v2.4/' +
                                                 data['location']['id'],
                                                 fields='location')
            except facebook.GraphAPIError:
                logger.exception(
                    "get_attendee: Couldn't get location info (Facebook). "
                    "user_id: %s, social_network_rsvp_id: %s" %
                    (self.user.id, rsvp['id']))
                raise
            if 'location' in location:
                location = location['location']
        else:
            location = {}
        if data:
            try:
                attendee = Attendee()
                attendee.first_name = data.get('first_name', '')
                attendee.last_name = data.get('last_name', '')
                attendee.full_name = data.get('name', '')
                attendee.email = data.get('email', '')
                attendee.city = location.get('city', '')
                attendee.country = location.get('country', '')
                attendee.latitude = location.get('latitude')
                attendee.longitude = location.get('longitude')
                attendee.zip = location.get('zip')
                attendee.social_profile_url = data.get('link', '')
                attendee.picture_url = data['picture']['data']['url'] \
                    if 'picture' in data and 'data' in data['picture']\
                       and 'url' in data['picture']['data'] else ''
                attendee.gt_user_id = self.user.id
                attendee.social_network_id = self.social_network.id
                # we are using profile_id here as we don't have any
                # rsvp_id for this vendor.
                attendee.vendor_rsvp_id = rsvp['id']
                # We do not have 'time' of rsvp from Facebook API response.
                # We cannot use datetime.now() here because every time we run
                # importer, we will have duplicate candidates as their added
                # time will not be same as the added time of previous record.
                # So for now, we are saving it as blank.
                attendee.added_time = ' '
                attendee.vendor_img_link = \
                    "<img class='pull-right' " \
                    "style='width:60px;height:30px' " \
                    "src='/web/static/images/activities/facebook_logo.png'/>"
                social_network_event_id = rsvp['vendor_event_id']
                if rsvp['rsvp_status'].strip() == 'attending' \
                        or rsvp['rsvp_status'].strip() == 'maybe':
                    attendee.rsvp_status = 'yes'
                else:
                    attendee.rsvp_status = 'no'
                event = Event.get_by_user_id_social_network_id_vendor_event_id(
                    self.user.id, self.social_network.id,
                    social_network_event_id)
                if event:
                    attendee.event = event
                    return attendee
                else:
                    raise EventNotFound(
                        'Event is not present in db, '
                        'social_network_event_id is '
                        '%s. User Id: %s' %
                        (social_network_event_id, self.user.id))
            except Exception:
                raise
示例#19
0
    def get_rsvps(self, event):
        """
        :param event: event in getTalent database
        :type event: common.models.event.Event
        :return: rsvps of given event
        :rtype: list

        - We get RSVPs of given event from Graph API of Facebook

        - We use this method while importing RSVPs through social network
            manager.

        :Example:

        - Create RSVP class object as

        sn_rsvp_obj = sn_rsvp_class(social_network=self.social_network,
                                    headers=self.headers,
                                    user_credentials=user_credentials)

        - Then call get_all_rsvps() on sn_rsvp_obj by passing events in
        parameters as follow

            self.rsvps = sn_rsvp_obj.get_all_rsvps(self.events)

        - Inside get_all_rsvps(), we call get_rsvps() on class object.

        - It appends rsvps of an events in a list and returns it

        **See Also**
            .. seealso:: get_all_rsvps() method in RSVPBase class
            inside social_network_service/rsvp/base.py for more insight.
        """
        rsvps = []
        try:
            self.graph = facebook.GraphAPI(access_token=self.access_token)
            url = 'v2.4/%s' % str(event.social_network_event_id) + '/'
            # Get list of people surely attending
            confirm_attendees = self.graph.get_object(url + 'attending')
        except facebook.GraphAPIError:
            logger.exception(
                "get_rsvps: Couldn't get 'attending' RSVPs (Facebook), "
                "user_id: %s, social_network_event_id: %s" %
                (self.user.id, event.social_network_event_id))
            raise
        rsvps += confirm_attendees['data']
        self.get_all_pages(confirm_attendees, rsvps)
        # Get list of people who aren't certain
        try:
            expected_attendees = self.graph.get_object(url + 'maybe')
        except facebook.GraphAPIError:
            logger.exception(
                "get_rsvps: Couldn't get 'maybe' RSVPs (Facebook), "
                "user_id: %s, social_network_event_id: %s" %
                (self.user.id, event.social_network_event_id))
            raise
        rsvps += expected_attendees['data']
        self.get_all_pages(expected_attendees, rsvps)
        # Get list of people who declined
        try:
            declined_attendees = self.graph.get_object(url + 'declined')
        except facebook.GraphAPIError:
            logger.exception(
                "get_rsvps: Couldn't get 'declined' RSVPs (Facebook), "
                "user_id: %s, social_network_event_id: %s" %
                (self.user.id, event.social_network_event_id))
            raise
        rsvps += declined_attendees['data']
        self.get_all_pages(declined_attendees, rsvps)
        for rsvp in rsvps:
            rsvp.update(
                {'vendor_event_id': str(event.social_network_event_id)})
        return rsvps
示例#20
0
    def get(self, *args, **kwargs):
        """
        This action returns a list of user events. In the response, we return fields
        as returned from Meetup's /groups call given at http://www.meetup.com/meetup_api/docs/2/groups/

        :Example:
            headers = {'Authorization': 'Bearer <access_token>'}
            response = requests.get(API_URL + '/venues/', headers=headers)

        .. Response::

            This response is from Meetup API which will be returned.

            {
              "count": 1,
              "groups": [
                {
                  "category": {
                    "shortname": "tech",
                    "name": "tech",
                    "id": 34
                  },
                  "city": "Lahore",
                  "utc_offset": 18000000,
                  "who": "Python Lovers",
                  "rating": 0,
                  "description": "This group is for anyone interested in computer programming. Python is one of the top ranking programming languages. All skill levels are welcome. Basic purpose is to get exposure about python from smart people all over the world. We can also meet at some restaurant for some food and drink afterward. Let's meetup and share knowledge.",
                  "created": 1439705650000,
                  "country": "PK",
                  "topics": [
                    {
                      "name": "Python",
                      "urlkey": "python",
                      "id": 1064
                    },
                    {
                      "name": "Web Development",
                      "urlkey": "web-development",
                      "id": 15582
                    },
                    {
                      "name": "Programming Languages",
                      "urlkey": "programming-languages",
                      "id": 17628
                    },
                    {
                      "name": "Computer programming",
                      "urlkey": "computer-programming",
                      "id": 48471
                    },
                    {
                      "name": "Python web development",
                      "urlkey": "python-web-development",
                      "id": 917242
                    }
                  ],
                  "join_mode": "open",
                  "lon": 74.3499984741211,
                  "visibility": "public",
                  "link": "http://www.meetup.com/QC-Python-Learning/",
                  "members": 59,
                  "urlname": "QC-Python-Learning",
                  "lat": 31.559999465942383,
                  "timezone": "Asia/Karachi",
                  "organizer": {
                    "name": "Waqas Younas",
                    "member_id": 183366764
                  },
                  "id": 18837246,
                  "name": "QC - Python Learning"
                }
              ]
            }

        .. HTTP Status:: 200 (OK)
                    500 (Internal Server Error)
        """
        user_id = request.user.id
        try:
            meetup = Meetup(user_id=user_id)
            groups = meetup.get_groups()
            response = dict(groups=groups, count=len(groups))
        except Exception as e:
            logger.exception('Could not get meetup groups')
            raise InternalServerError(e.message)
        return response