def setup_user_by_token(): user_token = request.headers.get('X-Wigo-User-Key') if user_token: try: user_id = get_user_id_for_key(user_token) # the current user should always get a fresh copy of themself model_cache.invalidate(user_id) user = User.find(user_id) g.user = user group = getattr(g, 'group', None) if group and not user.location_locked: # if a group was passed in via geo, switch the users group user.group_id = group.id elif user.group_id: # if the user has a group defined, use it group = Group.find(user.group_id) g.group = group else: # we need a group, so default to boston group = Group.find(code='boston') user.group_id = group.id g.group = group if not user.location_locked and hasattr(g, 'latitude') and hasattr( g, 'longitude'): if user.modified <= (datetime.utcnow() - timedelta(minutes=30)): user.latitude = round(g.latitude, 3) user.longitude = round(g.longitude, 3) platform = request.headers.get('X-Wigo-Device') if not platform: platform = request.user_agent.platform if platform: platform = platform.lower() if platform in ('android', 'iphone', 'ipad'): user.set_custom_property('platforms', [platform]) if user.is_changed(): user.save() agent.add_custom_parameter('user_id', user.id) if user.group_id: agent.add_custom_parameter('group_code', group.code) except DoesNotExist: pass
def post(self): json = request.get_json() if 'city_id' in json: group = get_group_by_city_id(json['city_id']) elif 'group_id' in json: group = Group.find(json['group_id']) else: group = g.group try: event = Event({ 'name': json.get('name'), 'group_id': group.id, 'owner_id': g.user.id, 'privacy': json.get('privacy') or 'public' }) if 'date' in json: date = parse(json.get('date')) event.date = group.get_day_start(date) event.expires = group.get_day_end(date) else: event.date = group.get_day_start() event.expires = group.get_day_end() if 'latitude' in json: event.latitude = json.get('latitude') if 'longitude' in json: event.longitude = json.get('longitude') event.save() return self.serialize_list(Event, [event]) except AlreadyExistsException, e: return self.handle_already_exists_exception(e)
def apply(self, query, name, value): if name == 'group_code': try: group = Group.find(code=value) return query.group(group) except DoesNotExist: pass return query.where(**{name: value})
def get(self, group_id): group = Group.find(group_id) cities = get_close_cities(group.latitude, group.longitude) return [{ 'city_id': c.city_id, 'name': c.name, 'population': int(c.population) } for c in cities]
def test_update_user_group(): from server.models.group import Group from server.models.user import User with client() as c: user = User.find(key='test') g = user.group user.group_id = Group.find(code='san_diego').id user.save() assert User.find(key='test').group.name == 'San Diego' # posting with geo should change the users group resp = api_post(c, user, '/api/users/me', { 'bio': '321' }, lat=42.3584, lon=-71.0598) assert User.find(key='test').group.name == 'Boston'
def send_friend_invites(user_id, event_id): try: user = User.find(user_id) event = Event.find(event_id) except DoesNotExist: return if event.is_expired or not user.is_attending(event): return groups = {} for friend in user.friends_iter(): if wigo_db.sorted_set_is_member( skey('event', event_id, user, 'invited'), friend.id): continue if friend.group_id: friend_group = groups.get(friend.group_id) if friend_group is None: friend_group = Group.find(friend.group_id) groups[friend.group_id] = friend_group distance = Location.getLatLonDistance( (user.group.latitude, user.group.longitude), (friend_group.latitude, friend_group.longitude)) if distance > 160: # > 160km, 100 miles continue try: invite = Invite() invite.user_id = user.id invite.invited_id = friend.id invite.event_id = event_id invite.save() except ValidationException, e: logger.warn('error creating invite, {}'.format(e.message))
def new_group(group_id): group = Group.find(group_id) logger.info('new group {} created, importing events'.format( group.name.encode('utf-8'))) num_imported = 0 imported = set() min = epoch(group.get_day_end() - timedelta(days=7)) with wigo_db.transaction(commit_on_select=False): for close_group in get_close_groups(group.latitude, group.longitude, 100): if close_group.id == group.id: continue for event in Event.select().group(close_group).min(min): # only import the events the group actually owns if event.group_id != close_group.id: continue # no double imports if event.id not in imported: event.update_global_events(group=group) imported.add(event.id) num_imported += 1 for event in Event.select().key(skey('global', 'events')).min(min): if event.id not in imported: event.update_global_events(group=group) imported.add(event.id) num_imported += 1 logger.info('imported {} events into group {}'.format( num_imported, group.name.encode('utf-8'))) group.track_meta('last_event_change', expire=None) group.status = 'active' group.save()
def setup_request(): g.user = None g.group = None if is_request_secure( ) and request.environ.get('wsgi.url_scheme') != 'https': request.environ['wsgi.url_scheme'] = 'https' if request.path.startswith('/api/swagger') or request.path.startswith( '/admin'): agent.ignore_transaction() api_key = request.headers.get('X-Wigo-API-Key') if not api_key and 'key' in request.args: request.args = request.args.copy() api_key = request.args.pop('key') if api_key: g.api_key = api_key api_version = request.headers.get('X-Wigo-API-Version') if not api_version: api_version = '1000000000.0.0' try: g.api_version = Version(api_version) except: raise ValidationException('Invalid version number', 'X-Wigo-API-Version') # check api key auth if request.path.startswith('/api/hooks/'): # webhooks do their own auth pass elif request.path.startswith('/api/swagger'): pass elif request.path.startswith('/api') and api_key != app.config['API_KEY']: abort(403, message='Bad API key') # resolve by lat/long geolocation = request.headers.get('Geolocation') if geolocation: parsed_geo = urlparse(geolocation) if parsed_geo.scheme == 'geo': lat, lon = parsed_geo.path.split(',') lat, lon = float(lat), float(lon) if lat and lon: g.latitude, g.longitude = float(lat), float(lon) try: g.group = Group.find(lat=g.latitude, lon=g.longitude) except DoesNotExist: logger.info( 'could not resolve group from geo, lat={}, lon={}'. format(g.latitude, g.longitude)) city_id = request.headers.get('X-Wigo-City-ID') if city_id: g.group = Group.find(city_id=int(city_id)) group_id = request.headers.get('X-Wigo-Group-ID') if group_id: g.group = Group.find(int(group_id)) # setup the user after the geo lookup, since the user might need to update its group setup_user_by_token()
def event_related_change(group_id, event_id, is_global=False, deleted=False): from server.db import redis lock = redis.lock('locks:group_event_change:{}:{}'.format( group_id, event_id), timeout=120) if lock.acquire(blocking=False): try: agent.add_custom_parameter('group_id', group_id) logger.debug('recording event change in group {}'.format(group_id)) if not deleted: try: event = Event.find(event_id) event.deleted = False except DoesNotExist: event = Event({'id': event_id, 'group_id': group_id}) event.deleted = True else: event = Event({'id': event_id, 'group_id': group_id}) event.deleted = True group = Group.find(group_id) with wigo_db.transaction(commit_on_select=False): # add to the time in case other changes come in while this lock is taken, # or in case the job queues get backed up group.track_meta('last_event_change', time() + EVENT_CHANGE_TIME_BUFFER) if is_global or event.is_global: groups_to_add_to = get_all_groups() else: radius = 100 population = group.population or 50000 if population < 60000: radius = 40 elif population < 100000: radius = 60 groups_to_add_to = get_close_groups( group.latitude, group.longitude, radius) num_visited = 0 for group_to_add_to in groups_to_add_to: if group_to_add_to.id == group.id: continue # index this event into the close group if event.deleted is False: event.update_global_events(group=group_to_add_to) else: event.remove_index(group=group_to_add_to) # track the change for the group group_to_add_to.track_meta( 'last_event_change', time() + EVENT_CHANGE_TIME_BUFFER) num_visited += 1 if (num_visited % 25) == 0: lock.extend(30) finally: lock.release()
def group(self): if self.group_id: from server.models.group import Group return Group.find(self.group_id) return None
def get(self, group_id): group = Group.find(group_id) groups = get_close_groups(group.latitude, group.longitude) return self.serialize_list(self.model, groups)
def __get_group(self): try: group = Group.find(lat=self._lat, lon=self._lon) return 1, self._page, [group] except: return 0, self._page, []