|
@@ -18,6 +18,7 @@ limitations under the License.
|
|
|
"""
|
|
|
|
|
|
import csv
|
|
|
+import copy
|
|
|
import json
|
|
|
import string
|
|
|
import random
|
|
@@ -96,6 +97,121 @@ def hash_password(password, salt=None):
|
|
|
return '$%s$%s' % (salt, hash_.hexdigest())
|
|
|
|
|
|
|
|
|
+has_eventbrite_sdk = False
|
|
|
+try:
|
|
|
+ from eventbrite import Eventbrite
|
|
|
+ has_eventbrite_sdk = True
|
|
|
+except ImportError:
|
|
|
+ Eventbrite = object
|
|
|
+
|
|
|
+
|
|
|
+class CustomEventbrite(Eventbrite):
|
|
|
+ """Custom methods to override official SDK limitations; code take from Yuval Hager; see:
|
|
|
+ https://github.com/eventbrite/eventbrite-sdk-python/issues/18
|
|
|
+
|
|
|
+ This class should be removed onces the official SDK supports pagination.
|
|
|
+ """
|
|
|
+ def custom_get_event_attendees(self, event_id, status=None, changed_since=None, page=1):
|
|
|
+ data = {}
|
|
|
+ if status:
|
|
|
+ data['status'] = status
|
|
|
+ if changed_since:
|
|
|
+ data['changed_since'] = changed_since
|
|
|
+ data['page'] = page
|
|
|
+ return self.get("/events/{0}/attendees/".format(event_id), data=data)
|
|
|
+
|
|
|
+ def get_all_event_attendees(self, event_id, status=None, changed_since=None):
|
|
|
+ page = 1
|
|
|
+ attendees = []
|
|
|
+ while True:
|
|
|
+ r = self.custom_get_event_attendees(event_id, status, changed_since, page=page)
|
|
|
+ attendees.extend(r['attendees'])
|
|
|
+ if r['pagination']['page_count'] <= page:
|
|
|
+ break
|
|
|
+ page += 1
|
|
|
+ return attendees
|
|
|
+
|
|
|
+
|
|
|
+KEYS_REMAP = {
|
|
|
+ ('capacity', 'number_of_tickets'),
|
|
|
+ ('changed', 'updated_at', lambda x: x.replace('T', ' ').replace('Z', '')),
|
|
|
+ ('created', 'created_at', lambda x: x.replace('T', ' ').replace('Z', '')),
|
|
|
+ ('description', 'description', lambda x: x.get('text', ''))
|
|
|
+}
|
|
|
+
|
|
|
+def reworkObj(obj, kind='event'):
|
|
|
+ """Rename and fix some key in the data from the Eventbrite API."""
|
|
|
+ for remap in KEYS_REMAP:
|
|
|
+ transf = lambda x: x
|
|
|
+ if len(remap) == 2:
|
|
|
+ old, new = remap
|
|
|
+ else:
|
|
|
+ old, new, transf = remap
|
|
|
+ if old in obj:
|
|
|
+ obj[new] = transf(obj[old])
|
|
|
+ if old != new:
|
|
|
+ del obj[old]
|
|
|
+ if kind == 'event':
|
|
|
+ if 'name' in obj:
|
|
|
+ obj['title'] = obj.get('name', {}).get('text') or ''
|
|
|
+ del obj['name']
|
|
|
+ if 'start' in obj:
|
|
|
+ t = obj['start'].get('utc') or ''
|
|
|
+ obj['begin_date'] = obj['begin_time'] = t.replace('T', ' ').replace('Z', '')
|
|
|
+ if 'end' in obj:
|
|
|
+ t = obj['end'].get('utc') or ''
|
|
|
+ obj['end_date'] = obj['end_time'] = t.replace('T', ' ').replace('Z', '')
|
|
|
+ else:
|
|
|
+ profile = obj.get('profile') or {}
|
|
|
+ complete_name = profile['name']
|
|
|
+ obj['surname'] = profile.get('last_name') or ''
|
|
|
+ obj['name'] = profile.get('first_name') or ''
|
|
|
+ if not (obj['surname'] and obj['name']):
|
|
|
+ obj['surname'] = complete_name
|
|
|
+ obj['email'] = profile.get('email') or ''
|
|
|
+ return obj
|
|
|
+
|
|
|
+
|
|
|
+def expandBarcodes(attendees):
|
|
|
+ """Generate an attendee for each barcode in the Eventbrite API data."""
|
|
|
+ for attendee in attendees:
|
|
|
+ barcodes = attendee.get('barcodes') or []
|
|
|
+ if not barcodes:
|
|
|
+ yield attendee
|
|
|
+ barcodes = [b.get('barcode') for b in barcodes if b.get('barcode')]
|
|
|
+ for code in barcodes:
|
|
|
+ att_copy = copy.deepcopy(attendee)
|
|
|
+ att_copy['order_nr'] = code
|
|
|
+ yield att_copy
|
|
|
+
|
|
|
+
|
|
|
+def ebAPIFetch(oauthToken, eventID):
|
|
|
+ """Fetch an event, complete with all attendees using Eventbrite API.
|
|
|
+
|
|
|
+ :param oauthToken: Eventbrite API key
|
|
|
+ :type oauthToken: str
|
|
|
+ :param eventID: Eventbrite ID of the even to be fetched
|
|
|
+ :type eventID: str
|
|
|
+
|
|
|
+ :returns: information about the event and all its attendees
|
|
|
+ :rtype: dict
|
|
|
+ """
|
|
|
+ if not has_eventbrite_sdk:
|
|
|
+ raise Exception('unable to import eventbrite module')
|
|
|
+ eb = CustomEventbrite(oauthToken)
|
|
|
+ event = eb.get_event(eventID)
|
|
|
+ eb_attendees = eb.get_all_event_attendees(eventID)
|
|
|
+ event = reworkObj(event, kind='event')
|
|
|
+ attendees = []
|
|
|
+ for eb_attendee in eb_attendees:
|
|
|
+ reworkObj(eb_attendee, kind='attendee')
|
|
|
+ attendees.append(eb_attendee)
|
|
|
+ event['eb_event_id'] = eventID
|
|
|
+ attendees = list(expandBarcodes(attendees))
|
|
|
+ info = {'event': event, 'attendees': attendees}
|
|
|
+ return info
|
|
|
+
|
|
|
+
|
|
|
class ImprovedEncoder(json.JSONEncoder):
|
|
|
"""Enhance the default JSON encoder to serialize datetime and ObjectId instances."""
|
|
|
def default(self, o):
|