Exemple #1
0
    def get_rsvps(self, event):
        """
        This method is used to get all attendees of an event
        :param event: Eventbrite event
        :type event: Event
        :return: List of RSVPs
        :rtype: list
        """
        rsvps_url = get_url(self,
                            Urls.RSVPS).format(event.social_network_event_id)
        response = http_request('GET',
                                url=rsvps_url,
                                headers=self.headers,
                                user_id=self.user.id)
        all_rsvps = []
        data = response.json()
        page_size = data['pagination']['page_size']
        total_records = data['pagination']['object_count']
        all_rsvps.extend(data['attendees'])
        current_page = 1
        total_pages = total_records / page_size
        for page in xrange(1, total_pages):
            params = {'page': current_page}
            current_page += 1
            # get data for every page
            response = http_request('GET',
                                    rsvps_url,
                                    params=params,
                                    headers=self.headers,
                                    user_id=self.user.id)
            if response.ok:
                data = response.json()
                all_rsvps.extend(data['attendees'])

        return all_rsvps
Exemple #2
0
 def publish_event(self, social_network_event_id):
     """
     This function publishes the Event on Eventbrite.
     This event is public.
     :param social_network_event_id: id for event on eventbrite.com
     :type social_network_event_id: int
     :exception EventNotPublished: raises this exception when unable to
         publish event on Eventbrite.com
     """
     # create url to publish event
     url = get_url(self,
                   Urls.PUBLISH_EVENT).format(str(social_network_event_id))
     # params are None. Access token is present in self.headers
     response = http_request('POST',
                             url,
                             headers=self.headers,
                             user_id=self.user.id)
     if response.ok:
         logger.info('|  Event has been published  |')
     else:
         error_message = "Event was not Published. There are some " \
                         "errors: Details: %s  |" % response.text
         log_error({
             'user_id': self.user.id,
             'error': error_message,
         })
         raise EventNotPublished('ApiError: Unable to publish event '
                                 'on Eventbrite')
Exemple #3
0
    def get_member_id(self):
        """
        - If getTalent user has an account on some social network, like Meetup.com, it will have a "member id" for
            that social network. This "member id" is used to make API subsequent calls to fetch events or RSVPs and
            relevant data for getTalent user from social network website.

        :Example:

            from social_network_service.meetup import Meetup
            sn = Meetup(user_id=1)
            sn.get_member_id()

        - We call this method from connect() of SocialNetworkBase class so that we don't need to get 'member id'
            of getTalent user while making object of some social network class at different places.
            (e.g. creating object of Meetup() in when importing events)

        **See Also**
        .. seealso:: connect() method defined in SocialNetworkBase class inside social_network_service/base.py.
        """
        logger.info('Getting "member id" of %s(user id:%s) using API of %s.' % (self.user.name, self.user.id,
                                                                                self.social_network.name))
        url = get_url(self, SocialNetworkUrls.VALIDATE_TOKEN)
        # Now we have the URL, access token, and header is set too,
        response = http_request('POST', url, headers=self.headers, user_id=self.user.id, app=app)
        if response.ok:
            return response.json().get('id')
        else:
            logger.error('get_member_id: Error:%s.' % response.text)
Exemple #4
0
 def _filter_event(self, event):
     """
     This method returns True if given event's group is owned by current user.
     :param event: event to be tested
     :type event: dict
     :return True or False
     :rtype Boolean
     """
     social_network_group_id = event['group'].get('id')
     # check if event's group id exists
     if social_network_group_id:
         if social_network_group_id in self.social_network_group_ids:
             return True
         url = get_url(self, Urls.GROUPS) + '/?sign=true'
         # Sleep for 10 / 30 seconds to avoid throttling
         time.sleep(0.34)
         response = http_request(
             'GET',
             url,
             params={'group_id': social_network_group_id},
             headers=self.headers,
             user_id=self.user.id)
         if response.ok:
             group = response.json()
             group_organizer = group['results'][0]['organizer']
             # group_organizer contains a dict that has member_id and name
             if str(group_organizer['member_id']) == self.member_id:
                 # save this group id as user's owned groups, so no need to
                 # fetch it again
                 self.social_network_group_ids.append(
                     social_network_group_id)
                 return True
     return False
Exemple #5
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 by API of Meetup.

        - 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.

        :return: list of RSVPs
        """
        rsvps = []
        social_network_id = event.social_network_id
        assert social_network_id is not None
        rsvps_url = get_url(self, Urls.RSVPS)
        params = {'event_id': event.social_network_event_id}
        response = http_request('GET', rsvps_url, params=params, headers=self.headers, user_id=self.user.id)
        if response.ok:
            data = response.json()
            rsvps.extend(data['results'])
            # next_url determines the pagination, this variable keeps appearing in response if there are more pages
            # and stops showing when there are no more. We have almost the same code for events' pagination,
            # might consolidate it.
            next_url = data['meta']['next'] or None
            while next_url:
                # Sleep for 10 / 30 seconds to avoid throttling
                time.sleep(0.34)
                # attach the key before sending the request
                response = http_request('GET', next_url, headers=self.headers, user_id=self.user.id)
                if response.ok:
                    data = response.json()
                    rsvps.extend(data['results'])
                    next_url = data['meta']['next'] or None
                    if not next_url:
                        break
            return rsvps
Exemple #6
0
 def update_event(self):
     """
     It first creates/ updates a venue on Meetup.com and then passes that
     venue's id in event's payload to update event location along with event
     data.
     :exception EventNotCreated: raises exception if unable to update event
             on Meetup.com
     :return: id of event
     :rtype: int
     """
     # create url to update event
     url = get_url(self, Urls.EVENT).format(self.social_network_event_id)
     # create or update venue for event
     venue_id = self.add_location()
     # add venue id in event payload to update event venue on Meetup.com
     self.payload.update({'venue_id': venue_id})
     # Sleep for 10 / 30 seconds to avoid throttling
     time.sleep(0.34)
     response = http_request('POST',
                             url,
                             params=self.payload,
                             headers=self.headers,
                             user_id=self.user.id)
     if response.ok:
         event_id = response.json().get('id')
         logger.info('|  Event %s updated Successfully  |' %
                     self.payload['name'])
         self.data['social_network_event_id'] = event_id
         return self.save_event()
     else:
         error_message = 'Event was not created. Error occurred during ' \
                         'event update on Meetup'
         log_error({'user_id': self.user.id, 'error': error_message})
         raise EventNotCreated('ApiError: Unable to update event on Meetup')
Exemple #7
0
 def unpublish_event(self, event_id, method=HttpMethods.DELETE):
     """
     This function is used while running unit tests. It deletes the Event from database that were created
     during the lifetime of a unit test.
     :param int | long event_id: id of newly created event
     :param string method: http standard method , default is DELETE
     :return: True if event is deleted from vendor, False otherwise.
     :rtype: bool
     """
     # create url to unpublish event
     url = get_url(self, Urls.EVENT).format(event_id)
     # Sleep for 10 / 30 seconds to avoid throttling
     time.sleep(0.34)
     # params are None. Access token is present in self.headers
     response = http_request(method,
                             url,
                             headers=self.headers,
                             user_id=self.user.id)
     if response.ok:
         logger.info('|  Event has been unpublished (deleted)  |')
     else:
         error_message = "Event was not unpublished (deleted):%s" % response.text
         log_error({'user_id': self.user.id, 'error': error_message})
         raise EventNotUnpublished(
             'ApiError: Unable to remove event from %s' %
             self.social_network.name)
Exemple #8
0
    def add_venue_to_sn(self, venue_data):
        """
        This function sends a POST request to Eventbrite api to create a venue for event.
        :param dict venue_data: a dictionary containing data required to create a venue
        """

        payload = {
            'venue.name': venue_data['address_line_1'],
            'venue.address.address_1': venue_data['address_line_1'],
            'venue.address.address_2': venue_data.get('address_line_2'),
            'venue.address.region': venue_data['state'],
            'venue.address.city': venue_data['city'],
            'venue.address.postal_code': venue_data.get('zip_code'),
            'venue.address.latitude': venue_data.get('latitude'),
            'venue.address.longitude': venue_data.get('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)
        json_resp = response.json()
        if response.ok:
            logger.info('|  Venue has been created  |')
            venue_id = json_resp.get('id')
        else:
            raise InternalServerError(
                'ApiError: Unable to create venue for Eventbrite',
                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)
Exemple #9
0
 def update_tickets(self, social_network_event_id):
     """
     This method update tickets for specific event on Eventbrite.com.
     This method should be called after updating event contents on
     social_network.
     See "social_network_service.event.Eventbrite.update_event" method for
         further info
     :param social_network_event_id: event id which refers to event on
     eventbrite.com
     :type social_network_event_id: str
     :exception TicketsNotCreated (throws exception if unable to update
         tickets)
     :return: tickets_id (an id which refers to tickets updated on
         eventbrite.com)
     :rtype: str
     """
     tickets_url = get_url(self,
                           Urls.TICKETS).format(social_network_event_id)
     event = Event.get_by_user_and_social_network_event_id(
         self.user.id, social_network_event_id)
     if event.tickets_id:
         tickets_url = tickets_url + str(event.tickets_id) + '/'
     else:
         logger.info('Tickets ID is not available for event with id %s,'
                     ' User:  %s' %
                     (social_network_event_id, self.user.name))
         raise TicketsNotCreated('ApiError: Unable to update event tickets'
                                 ' on Eventbrite as tickets_id was not '
                                 'found for this event')
     return self.manage_event_tickets(tickets_url)
Exemple #10
0
    def get_groups(self):
        """
        - This function fetches the groups of user from Meetup website for
            which the user is an organizer. These groups are shown
            in drop down while creating event on Meetup through Event Creation
            Form.

        - This function is called from GET method of class MeetupGroups() inside
            social_network_service/app/restful/social_network.py

        :Example:
                from social_network_service.meetup import Meetup
                sn = Meetup(user_id=1)
                sn.get_groups()
        :return: Meetup groups for which gt-user is an organizer
        :rtype: list (list of dicts where each dict is likely the response from
                    Meetup API)
        **See Also**
        .. seealso:: GET method of class MeetupGroups() inside
            social_network_service/app/restful/social_network.py
        """
        url = get_url(self, SocialNetworkUrls.GROUPS)
        params = {'organizer_id': self.user_credentials.member_id}
        # Sleep for 10 / 30 seconds to avoid throttling
        time.sleep(0.34)
        response = http_request('GET',
                                url,
                                params=params,
                                headers=self.headers,
                                user_id=self.user.id)
        if response.ok:
            return response.json()['results']
        else:
            return []
Exemple #11
0
 def get_events(self):
     """
     We send GET requests to API URL and get data. We also
     have to handle pagination because Meetup's API
     does that too.
     :return: all_events: Events of getTalent user on Meetup.com
     :rtype all_events: list
     """
     all_events = []  # contains all events of gt-users
     # page size is 100 so if we have 500 records we will make
     # 5 requests (using pagination where each response will contain
     # 100 records).
     events_url = get_url(self, Urls.EVENTS)
     # we can specify status=upcoming,past,draft,cancelled etc. By default we
     # have status=upcoming, so we are not explicitly specifying in fields.
     meetup_groups = MeetupGroup.filter_by_keywords(user_id=self.user.id)
     if not meetup_groups:
         logger.warn(
             '''No MeetupGroup is associated with this user subscription for Meetup.
                        UserId: %s
                        MemberId: %s
                        ''' %
             (self.user.id, self.user_credentials.member_id))
         return all_events
     params = {
         'group_id':
         ','.join([str(group.group_id) for group in meetup_groups]),
         'status': "upcoming,proposed,suggested",
         'fields': 'timezone'
     }
     response = http_request('GET',
                             events_url,
                             params=params,
                             headers=self.headers,
                             user_id=self.user.id)
     if response.ok:
         data = response.json()
         all_events = []
         all_events.extend(data['results'])
         # next_url determines the pagination, this variable keeps
         # appearing in response if there are more pages and stops
         # showing up when there are no more.
         next_url = data['meta']['next'] or None
         while next_url:
             url = next_url
             # Sleep for 10 / 30 seconds to avoid throttling
             time.sleep(0.34)
             response = http_request('GET',
                                     url,
                                     headers=self.headers,
                                     user_id=self.user.id)
             if response.ok:
                 data = response.json()
                 all_events.extend(data['results'])
                 next_url = data['meta']['next'] or None
                 if not next_url:
                     break
     return all_events
Exemple #12
0
    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)
Exemple #13
0
    def get_events(self, status='live', order_by='start_asc'):
        """
        We send GET requests to Eventbrite API and get already created events
        by this user on eventbrite.com.
        We also have to handle pagination because Eventbrite's API does that
        too.
        :return all_events: a collection of eventbrite events for specific user
        :rtype all_events: list
        """
        # create url to fetch events from eventbrite.com
        search = str(self.member_id) + '/owned_events'
        events_url = get_url(self, Urls.USER).format(search)
        params = {'status': status}
        # initialize event list to empty
        all_events = []
        try:
            # send a GET request to eventbrite's api to get events for given
            # user and after start_date
            response = http_request('GET',
                                    events_url,
                                    params=params,
                                    headers=self.headers,
                                    user_id=self.user.id)
        except:
            logger.exception('get_events: user_id: %s' % self.user.id)
            raise

        if response.ok:
            # if response is ok, get json data
            data = response.json()
            all_events.extend(data['events'])
            current_page = 1
            total_pages = data['pagination']['page_count']
            for page in range(1, total_pages):
                params_copy = params.copy()
                current_page += 1
                params_copy['page'] = current_page
                try:
                    # get data for every page
                    response = http_request('GET',
                                            events_url,
                                            params=params_copy,
                                            headers=self.headers,
                                            user_id=self.user.id)
                except Exception as e:
                    logger.exception('get_events: user_id: %s' % self.user.id)

                if response.ok:
                    data = response.json()
                all_events.extend(data['events'])
        return all_events
Exemple #14
0
    def fetch_event(self, event_id):
        """
        This method creates api url to fetch an event and then sends a GET request to fetch that event.
        :param str | int | long event_id: social network event id
        :return: event dict or None
        """
        event_url = get_url(self, SocialNetworkUrls.EVENT).format(event_id)
        try:
            response = http_request('get', event_url, headers=self.headers)

            if response.ok:
                return response.json()
        except ResourceNotFound:
            logger.info('Event not found for url: %s' % event_url)
            return None
Exemple #15
0
 def create_tickets(self, social_network_event_id):
     """
     This method creates tickets for specific event on Eventbrite.com.
     This method should be called after creating event on social_network.
     See "social_network_service.event.Eventbrite.create_event" method for
     further info
     :param social_network_event_id: event id which refers to event on
         eventbrite.com
     :type social_network_event_id: str
     :exception TicketsNotCreated (throws exception if unable to
         create tickets)
     :return: tickets_id (an id which refers to tickets created on
         eventbrite.com
     :rtype: str
     """
     tickets_url = get_url(self,
                           Urls.TICKETS).format(social_network_event_id)
     return self.manage_event_tickets(tickets_url)
Exemple #16
0
    def validate_token(self, payload=None):
        """
        :param payload: contains the access token of Facebook (Child class
            sets the payload) or is None for other social networks.
        :type payload: dict
        :return: True if token is valid otherwise False
        :rtype: bool

        - This function is called from validate_and_refresh_access_token() social network service base class
        inside social_network_service/base.py to check the validity of the access token of current user for a
        specific social network. We take the access token, make request to social network API on url
            say for Meetup 'https://api.meetup.com/2/member/self'

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

        **See Also**
        .. seealso:: __init__() function defined in social network manager
            inside social_network_service/manager.py.

        :return status of of access token either True or False.
        """
        status = False
        url = get_url(self, SocialNetworkUrls.VALIDATE_TOKEN)
        logger.info("%s access_token validation url: %s", self.social_network.name, url)
        try:
            response = requests.get(url, headers=self.headers, params=payload)
            if response.ok:
                status = True
            # If hit rate limit reached for Eventbrite or Meetup, too many requests
            elif response.status_code == codes.TOO_MANY_REQUESTS:
                data = response.json()
                logger.error("HitLimit reached for user(id:%s). Error:%s" % (self.user.id, data))
                raise HitLimitReached(data)
            else:
                logger.info("Access token has expired for %s(UserId:%s). Social Network is %s."
                            % (self.user.name, self.user.id, self.social_network.name))
        except requests.RequestException as error:
            raise AccessTokenHasExpired('Error: %s, Please connect with %s again from "Profile" page.'
                                        % (error.message, self.social_network.name))
        return status
Exemple #17
0
 def create_event(self):
     """
     This function is used to create Meetup event using vendor's API.
     It first creates a venue for event. Then venue_id is passed to
     event_payload.
     Then a POST request to Meetup API creates event on Meetup.com
     :exception EventNotCreated: raises exception if unable to
     publish/create event on Meetup.com.
     :return: id of event in db
     :rtype: int
     """
     venue_id = self.add_location()
     url = get_url(self, Urls.EVENT).format('')
     self.payload.update({
         'venue_id': venue_id,
         'publish_status': 'published'
     })
     logger.info(
         'Creating event for %s(user id:%s) using url:%s of API of %s.' %
         (self.user.name, self.user.id, url, self.social_network.name))
     # Sleep for 10 / 30 seconds to avoid throttling
     time.sleep(0.34)
     response = http_request('POST',
                             url,
                             params=self.payload,
                             headers=self.headers,
                             user_id=self.user.id)
     if response.ok:
         event = response.json()
         event_id = event['id']
         logger.info('|  Event %s created Successfully  |' %
                     self.payload['name'])
         self.data['social_network_event_id'] = event_id
         self.data['url'] = event.get('event_url', '')
         return self.save_event()
     else:
         error_message = 'Event was not Created. Error occurred during draft creation'
         log_error({'user_id': self.user.id, 'error': error_message})
         raise EventNotCreated('ApiError: Unable to create event on Meetup')
Exemple #18
0
    def import_meetup_groups(self):
        """
        This method is to fetch user's meetup groups and save them in gt database.
        """
        url = get_url(self, SocialNetworkUrls.GROUPS)
        params = {'organizer_id': self.user_credentials.member_id}
        # Sleep for 10 / 30 seconds to avoid throttling
        time.sleep(0.34)
        response = http_request('GET',
                                url,
                                params=params,
                                headers=self.headers,
                                user_id=self.user.id)
        meetup_groups = []
        if response.ok:
            groups = response.json()['results']
            for group in groups:
                meetup_group = MeetupGroup.get_by_group_id(group['id'])

                if meetup_group:
                    if meetup_group.user_id == self.user.id:
                        meetup_groups.append(meetup_group.to_json())
                        continue
                meetup_group = MeetupGroup(
                    group_id=group['id'],
                    user_id=self.user.id,
                    name=group['name'],
                    url_name=group['urlname'],
                    description=group.get('description'),
                    created_datetime=group.get('created'),
                    visibility=group.get('visibility'),
                    country=group.get('country'),
                    state=group.get('state'),
                    city=group.get('city'),
                    timezone=group.get('timezone'))
                MeetupGroup.save(meetup_group)
                meetup_groups.append(meetup_group.to_json())
        return meetup_groups
Exemple #19
0
    def create_event_organizer(self, data):
        """
        This method sends a POST request to Eventbrite API to create an event organizer.
        :param dict[str, T] data: organizer data
        :return: organizer id on Eventbrite
        :rtype string
        """
        mandatory_input_data = ['name', 'about']
        # gets fields which are missing
        missing_items = find_missing_items(data, mandatory_input_data)
        if missing_items:
            raise InvalidUsage("Mandatory Input Missing: %s" % missing_items)

        payload = {
            'organizer.name': data['name'],
            'organizer.description.html': data['about']
        }
        # create url to send post request to create organizer
        url = get_url(self, Urls.ORGANIZERS)
        response = http_request('POST',
                                url,
                                params=payload,
                                headers=self.headers,
                                user_id=self.user.id)
        json_response = response.json()
        if response.ok:
            return json_response['id']
        elif response.status_code == requests.codes.BAD_REQUEST and json_response.get(
                'error') == "ARGUMENTS_ERROR":
            raise InvalidUsage(
                'Organizer name `{}` already exists on Eventbrite'.format(
                    data['name']),
                error_code=ORGANIZER_ALREADY_EXISTS)
        raise InternalServerError(
            'Error occurred while creating organizer.',
            additional_error_info=dict(error=json_response))
Exemple #20
0
    def update_event(self):
        """
        This function is used to update an event on Eventbrite.com
        It uses update_tickets() method to update number of tickets for this
         event

        :exception EventNotCreated: throws exception if unable to update event
         on Eventbrite.com)
        :return: id of event
        :rtype: int

            :Example:

                In order to updates event first create EventBrite object and it
                takes user and authentication headers e.g.

                >> eventbrite = Eventbrite(user=gt_user,
                                           headers=authentication_headers)

                Then call event_gt_to_sn_mapping() method on this object and
                pass it event dictionary.
                >> eventbrite.event_gt_to_sn_mapping(event_data)

                It will create event payload which is required to post event on
                Eventbrite.com.
                Now call update_event to update event on Eventbrite.com and in
                getTalent database.

                >> eventbrite.update_event()

                This method returns id of updated getTalent event.
        """
        # create url to update event
        url = get_url(
            self, Urls.EVENT).format(str(self.social_network_event_id) + '/')
        venue_id = self.add_location()  # adding venue for the event
        self.event_payload['event.venue_id'] = venue_id
        response = http_request('POST',
                                url,
                                params=self.event_payload,
                                headers=self.headers,
                                user_id=self.user.id)
        if response.ok:  # event has been updated on Eventbrite.com
            event_id = response.json()['id']
            # Ticket are going to be created/updated
            ticket_id = self.update_tickets(event_id)
            logger.info('|  Event %s updated Successfully  |' %
                        self.event_payload['event.name.html'])
            self.data['social_network_event_id'] = event_id
            self.data['tickets_id'] = ticket_id
            return self.save_event()
        else:
            error_message = 'Event was not updated Successfully'
            response = response.json()
            error_detail = response.get('error', '') + ': ' \
                           + response.get('error_description', '')
            if error_detail != ': ':
                error_message += '\n%s' % error_detail
            log_error({
                'user_id': self.user.id,
                'error': error_detail,
            })
            raise EventNotCreated(error_message)
Exemple #21
0
    def refresh_access_token(self):
        """
        - When user authorizes Meetup account, we get a refresh token
            and access token. Access token expires in one hour.
            Here we refresh the access_token using refresh_token without user
            involvement and save in user_credentials db table.


        - This function is called from validate_and_refresh_access_token()
            defined in SocialNetworkBase class inside
            social_network_service/base.py

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

        **See Also**
        .. seealso:: validate_and_refresh_token() function defined in
            SocialNetworkBase class inside social_network_service/base.py.

        :return True if token has been refreshed successfully and False
                otherwise.
        :rtype: bool
        """
        status = False
        user_refresh_token = self.user_credentials.refresh_token

        auth_url = get_url(self, SocialNetworkUrls.REFRESH_TOKEN, is_auth=True)
        client_id = self.social_network.client_key
        client_secret = self.social_network.secret_key

        payload_data = {
            'client_id': client_id,
            'client_secret': client_secret,
            'grant_type': u'refresh_token',
            'refresh_token': user_refresh_token
        }
        # Sleep for 10 / 30 seconds to avoid throttling
        time.sleep(0.34)
        response = http_request('POST',
                                url=auth_url,
                                data=payload_data,
                                user_id=self.user.id,
                                app=app)
        if response.ok:
            try:
                # access token has been refreshed successfully, need to update
                # self.access_token and self.headers
                response = response.json()
                self.access_token = response.get('access_token')
                self.headers.update(
                    {'Authorization': 'Bearer ' + self.access_token})
                refresh_token = response.get('refresh_token')
                UserSocialNetworkCredential.query.filter_by(social_network_id=self.social_network.id,
                                                            member_id=self.user_credentials.member_id).\
                    update({'access_token': self.access_token, 'refresh_token': refresh_token})
                db.session.commit()
                logger.info("Access token has been refreshed.")
                status = True
            except Exception:
                logger.exception('refresh_access_token: user_id: %s' %
                                 self.user.id)
        else:
            # Error has been logged inside http_request()
            pass
        return status
Exemple #22
0
    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
Exemple #23
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 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
Exemple #24
0
    def create_event(self):
        """
        This function is used to post/create event on Eventbrite.com
        It uses create_tickets() method to allow user subscriptions and
        publish_event() to make it public
        :exception EventNotCreated: throws exception if unable to create
            event on Eventbrite.com
        :return: event_id, tickets_id: a tuple containing event_id on
            Eventbrite and tickets_id for this event

            :Example:

                In order to create event first create EventBrite object and it
                takes user and authentication headers e.g.

                >> eventbrite = Eventbrite(user=gt_user,
                                           headers=authentication_headers)

                Then call event_gt_to_sn_mapping() method on this object and
                 pass it event dictionary.
                >> eventbrite.event_gt_to_sn_mapping(event_data)

                It will create event payload which is required to post event on
                Eventbrite.com
                Now call create event to create event on Eventbrite.com

                >> eventbrite.create_event()

                This method returns id of getTalent event that was created on
                 Eventbrite.com as well.

        """
        # create url to post/create event on eventbrite.com
        url = get_url(self, Urls.EVENTS)
        # adding venue for the event or reuse if already created on
        # eventbrite.com
        venue_id = self.add_location()
        # add venue_id in event payload so it can be associated with this event
        # on eventbrite
        self.event_payload['event.venue_id'] = venue_id
        # create event on eventbrite by sending POST request
        response = http_request('POST',
                                url,
                                params=self.event_payload,
                                headers=self.headers,
                                user_id=self.user.id)
        if response.ok:
            # Event has been created on vendor and saved in draft there.
            # Now we need to create tickets for it and then publish it.
            event = response.json()
            event_id = event['id']
            # Ticket are going to be created/updated
            ticket_id = self.create_tickets(event_id)
            # Ticket(s) have been created for newly created Event
            if app.config[TalentConfigKeys.ENV_KEY] not in [
                    TalentEnvs.JENKINS
            ]:
                self.publish_event(event_id)
            logger.info('|  Event %s created Successfully  |' %
                        self.event_payload['event.name.html'])
            self.data['social_network_event_id'] = event_id
            self.data['tickets_id'] = ticket_id
            self.data['url'] = event['url']
            return self.save_event()
        else:
            error_message = 'Event was not created Successfully as draft'
            response = response.json()
            error_detail = response.get('error', '') + ': ' \
                           + response.get('error_description', '')
            if error_detail != ': ':
                error_message += '\n%s' % error_detail
            log_error({
                'user_id': self.user.id,
                'error': error_detail,
            })
            raise EventNotCreated(error_message)
Exemple #25
0
    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.')
Exemple #26
0
    def get_attendee_for_rsvp_via_webhook(self, rsvp):
        """
        :param rsvp: rsvp is likely the response of social network API.
        :type rsvp: dict
        :return: attendee
        :rtype: object

        Webhook returns data for RSVP as:

        {
            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/'
        }

        we extract order_id from above response and treat it as social_network_rsvp_id.
        So, rsvp object in this method looks like

            {
                'rsvp_id': 573384540
            }

        When we request Eventbrite API with above rsvp_id, we get response as
            {
                u'status': u'placed',
                u'first_name': u'Muhammad',
                u'last_name': u'Aslam',
                u'name': u'Muhammad Aslam',
                u'created': u'2016-11-29T15:52:15Z',
                u'event_id': u'29641929810',
                u'changed': u'2016-11-29T15:52:16Z',
                u'email': u'*****@*****.**',
                u'costs':
                        {
                            u'payment_fee': {u'currency': u'USD', u'display': u'$0.00',
                                             u'value': 0, u'major_value': u'0.00'
                                             },
                            u'gross': { u'currency': u'USD', u'display': u'$0.00', u'value': 0,
                                        u'major_value': u'0.00'},
                            u'eventbrite_fee': {u'currency': u'USD', u'display': u'$0.00', u'value': 0,
                                                u'major_value': u'0.00'},
                            u'tax': {u'currency': u'USD', u'display': u'$0.00', u'value': 0, u'major_value': u'0.00'},
                            u'base_price': {u'currency': u'USD', u'display': u'$0.00', u'value': 0,
                                            u'major_value': u'0.00'}
                        },
                u'time_remaining': None,
                u'id': u'575508020',
                u'resource_uri': u'https://www.eventbriteapi.com/v3/orders/575508020/'
            }

        - 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 get_attendee() defined in this file.

        :Example:
            attendee = self.get_attendee_for_rsvp_via_webhook(rsvp)

        **See Also**
            .. seealso:: get_attendee() method in this class.
        """
        order_url = get_url(self, Urls.ORDER).format(rsvp['rsvp_id'])
        order_response = http_request('GET',
                                      order_url,
                                      headers=self.headers,
                                      user_id=self.user.id)
        if order_response.ok:
            data = order_response.json()
            # get event_id
            social_network_event_id = data['event_id']
            event = Event.get_by_user_id_social_network_id_vendor_event_id(
                self.user.id, self.social_network.id, social_network_event_id)
            if not event:
                raise EventNotFound(
                    'Event is not present in db, social_network_event_id is %s. User Id: %s'
                    % (social_network_event_id, self.user.id))
            created_datetime = datetime.strptime(data['created'][:19],
                                                 "%Y-%m-%dT%H:%M:%S")
            attendee = Attendee()
            attendee.event = event
            attendee.first_name = data['first_name']
            attendee.full_name = data['name']
            attendee.last_name = data['last_name']
            attendee.added_time = created_datetime
            attendee.rsvp_status = 'yes' if data[
                'status'] == 'placed' else data['status']
            attendee.email = data['email']
            attendee.vendor_rsvp_id = rsvp['rsvp_id']
            attendee.gt_user_id = self.user.id
            attendee.social_network_id = self.social_network.id
            # TODO: This won't work now, need to figure out a way
            attendee.vendor_img_link = \
                "<img class='pull-right'" \
                " style='width:60px;height:30px' " \
                "src='/web/static/images/activities/eventbrite_logo.png'/>"
            # GET attendees of event
            rsvps_url = get_url(self, Urls.RSVPS).format(
                event.social_network_event_id)
            response_attendees = http_request('GET',
                                              rsvps_url,
                                              headers=self.headers)
            event_attendees = response_attendees.json()['attendees']
            for event_attendee in event_attendees:
                # Get profile url of candidate to save
                if event_attendee['created'] == order_response.json(
                )['created']:
                    # In case of Eventbrite, we have a Attendee object created
                    # on Eventbrite website. We save that link as profile url.
                    attendee.social_profile_url = event_attendee[
                        'resource_uri']
                    break
            return attendee