def ip(self, request): """ Retrieve ip from request """ ip = get_real_ip(request) or 'undefined' debug_logger.debug("IP request from : " + ip) return Response({'ip': ip})
def user_from_facebook_auth_response(auth_response, initial_user=None, is_test=False): if 'accessToken' in auth_response: facebook_access_token = auth_response['accessToken'] else: facebook_access_token = auth_response fb_user = fb_user_from_facebook_access_token(facebook_access_token) facebook_id = fb_user['id'] try: linked_facebook = LinkedFacebookAccount.objects.filter(facebook_id=facebook_id).select_related( 'user__profile').first() if not linked_facebook: raise LinkedFacebookAccount.DoesNotExist() save_linked_facebook(linked_facebook.user, facebook_access_token, fb_user, linked_facebook=linked_facebook) user = linked_facebook.user location = initial_user and initial_user.get('location') if location: location_controller.update_profile_location(user.ap, location) except LinkedFacebookAccount.DoesNotExist: debug_logger.debug('LinkedFacebookAccount.DoesNotExist for facebook_id %s' % facebook_id) if 'email' not in fb_user: dev_msg = 'Facebook user has no email: %s' % json.dumps(fb_user) debug_logger.error(dev_msg) raise ShoutitBadRequest(message=FB_LINK_ERROR_EMAIL, developer_message=dev_msg) user = user_controller.auth_with_facebook(fb_user, initial_user, is_test) try: save_linked_facebook(user, facebook_access_token, fb_user) except (ValidationError, IntegrityError) as e: raise ShoutitBadRequest(message=FB_LINK_ERROR_TRY_AGAIN, developer_message=str(e)) return user
def auth_with_gplus(gplus_user, credentials, initial_user=None, is_test=False): email = gplus_user.get('emails')[0].get('value').lower() name = gplus_user.get('name', {}) first_name = name.get('givenName') last_name = name.get('familyName') username = initial_user.get('username') gplus_id = gplus_user.get('id') gender = gplus_user.get('gender') profile_fields = {} location = {} if initial_user: if initial_user.get('location'): location = initial_user.get('location') location_controller.add_predefined_city(location) elif initial_user.get('ip'): location = location_controller.from_ip(initial_user.get('ip')) profile_fields.update(location) profile_fields.update({'gender': gender}) try: # Todo: Check! # in rare cases when clients send multiple requests and while the first one is still in progress # (post save isn't yet completed i.e. no profile yet) the second one passes this check and breaks # in the coming lines of updating profile location as there is no profile. The result of such call can be even # worse as two users will be created user = User.objects.get(email=email) debug_logger.debug( 'Found user: {} with same email of gplus_user: {}'.format( user, gplus_id)) if location: location_controller.update_profile_location(user.profile, location, add_pc=False) except User.DoesNotExist: user = create_user(email=email, first_name=first_name, last_name=last_name, username=username, is_activated=True, profile_fields=profile_fields, is_test=is_test) if not user.is_activated: user.activate() if not user.profile.gender and gender: user.profile.update(gender=gender) credentials_json = credentials.to_json() try: LinkedGoogleAccount.objects.create(user=user, credentials_json=credentials_json, gplus_id=gplus_id) except IntegrityError as e: raise ShoutitBadRequest( message=_("Could not access your Google account, try again later"), developer_message=str(e)) image_url = gplus_user['image']['url'].split('?')[0] media_controller.set_profile_media(user.profile, 'image', image_url) return user
def _send_welcome_email(user): subject = _('Welcome!') subs = {'username': user.username} if user.is_activated: subs.update({ 'text1': "", 'action': _("Take me to my profile"), 'link': user.web_url }) else: subs.update({ 'text1': _("To get started using Shoutit, please activate your account below" ), 'action': _("Activate your account"), 'link': user.verification_link }) message = prepare_message(user=user, subject=subject, template=SG_WELCOME_TEMPLATE, subs=subs) result = sg.send(message) debug_logger.debug("Sent Welcome Email to %s Result: %s" % (user, result))
def upload_image_to_s3(bucket_name, public_url, url=None, data=None, filename=None, raise_exception=False): assert url or data, 'Must pass url or data' source = url if url else str(ImageData(data)) debug_logger.debug("Uploading image to S3 from %s" % source) try: if not data: response = requests.get(url, timeout=10) data = response.content if not filename: filename = generate_image_name() # Check if an actual image Image.open(StringIO(data)) # Connect to S3 s3 = boto3.resource('s3') # Upload s3.Object(bucket_name, filename).put( Body=data, ContentType='image/jpg' ) # Todo (mo): set actual content type or convert to jpg # Construct public url s3_image_url = '%s/%s' % (public_url, filename) debug_logger.debug("Uploaded image to S3: %s" % s3_image_url) return s3_image_url except Exception as e: if raise_exception: raise e else: error_logger.warn("Uploading image to S3 failed", exc_info=True)
def remove_member(channel_name, user_id): join = PusherChannelJoin.objects.filter(channel__name=channel_name, user_id=user_id) if join.exists(): join.delete() debug_logger.debug('Removed Member %s from PusherChannel %s' % (user_id, channel_name)) # Try to delete the channel delete_channel(channel_name)
def auth_with_facebook(fb_user, initial_user=None, is_test=False): email = fb_user.get('email').lower() first_name = fb_user.get('first_name') last_name = fb_user.get('last_name') facebook_id = fb_user.get('id') gender = fb_user.get('gender') birthday = fb_user.get('birthday') username = initial_user and initial_user.get('username') location = initial_user and initial_user.get('location') profile_fields = {} update_fields = [] if location: location_controller.add_predefined_city( location) # Todo (mo): are we still using this? profile_fields.update(location) update_fields += location.keys() if gender: profile_fields.update({'gender': gender}) update_fields.append('gender') if birthday: fmt = "%m/%d/%Y" if birthday.count( '/') == 2 else '%d/%m' if birthday.count('/') == 1 else '%Y' birthday = datetime.strptime(birthday, fmt).date() profile_fields.update({'birthday': birthday}) update_fields.append('birthday') try: user = User.objects.filter( email=email).select_related('profile').first() if not user: raise User.DoesNotExist() profile = user.profile debug_logger.debug('Found user: %s with same email of fb_user: %s' % (user, facebook_id)) if location: location_controller.update_object_location(profile, location, save=False) if gender: profile.gender = gender profile.save(update_fields=update_fields) except User.DoesNotExist: user = create_user(email=email, first_name=first_name, last_name=last_name, username=username, is_activated=True, profile_fields=profile_fields, is_test=is_test) if not user.is_activated: user.activate() return user
def delete_channel(channel_name): joins = PusherChannelJoin.objects.filter(channel__name=channel_name) if not joins.exists(): channel = PusherChannel.objects.filter(name=channel_name) if channel.exists(): try: channel.delete() except IntegrityError: debug_logger.debug('Could not delete PusherChannel %s' % channel_name) else: debug_logger.debug('Deleted PusherChannel %s' % channel_name)
def abstract_profile_post_save(sender, instance=None, created=False, **kwargs): from shoutit.controllers import notifications_controller if not issubclass(sender, AbstractProfile): return action = 'Created' if created else 'Updated' notify = getattr(instance, 'notify', True) debug_logger.debug('%s %s: %s | Notify: %s' % (action, instance.model_name, instance, notify)) if not created: if notify: # Send `profile_update` notification notifications_controller.notify_user_of_profile_update( instance.user)
def create_channel(channel_name): if 'presence' in channel_name: channel_type = 2 elif 'private' in channel_name: channel_type = 1 else: channel_type = 0 channel, created = PusherChannel.objects.get_or_create(type=channel_type, name=channel_name) if created: debug_logger.debug('Created PusherChannel %s' % channel_name) else: debug_logger.debug('PusherChannel %s was already created' % channel_name) return channel
def add_member(channel_name, user_id): channel = create_channel(channel_name) try: join, created = PusherChannelJoin.objects.get_or_create( channel=channel, user_id=user_id) except IntegrityError: # Another call has deleted the channel already pass else: if created: debug_logger.debug('Added Member %s to PusherChannel %s' % (user_id, channel.name)) else: debug_logger.debug( 'Member %s was already added to PusherChannel %s' % (user_id, channel.name))
def auth(self, request): """ Authorize channel subscriptions. ###Not used directly by API clients. --- """ user = request.user page_admin_user = getattr(request, 'page_admin_user', None) authorized = page_admin_user or user channel = request.data.get('channel_name', '') # Todo: check if the user is allowed to subscribe to the channel socket_id = request.data.get('socket_id', '') api_version = request.version data = { 'v2': { 'user_id': authorized.pk, 'user': v2_serializers.UserSerializer(authorized, context={ 'request': create_fake_request('v2') }).data }, 'v3': { 'user_id': authorized.pk, 'profile': v3_serializers.ProfileSerializer(authorized, context={ 'request': create_fake_request('v3') }).data } } custom_data = data[api_version] try: auth = pusher.authenticate(channel=channel, socket_id=socket_id, custom_data=custom_data) except ValueError as e: raise ValidationError(str(e)) debug_logger.debug( "Authorized %s to subscribe to %s on %s Pusher on socket_id: %s" % (authorized, channel, api_version, socket_id)) return Response(auth)
def _send_verified_email(user): subject = _('Your email has been verified!') subs = { 'text1': _("Thank you for verifying your email. Your account has been verified and you can now use Shoutit " "full potential."), 'action': _("Take me to my profile"), 'link': user.web_url } message = prepare_message(user=user, subject=subject, template=SG_GENERAL_TEMPLATE, subs=subs) result = sg.send(message) debug_logger.debug("Sent Verified Email to %s Result: %s" % (user, result))
def _send_password_reset_email(user): subject = _('Reset your password') subs = { 'text1': _("You have requested to reset your password. If it wasn't you please let us know as soon as possible." ), 'action': _("Reset my password"), 'link': user.password_reset_link } message = prepare_message(user=user, subject=subject, template=SG_GENERAL_TEMPLATE, subs=subs) result = sg.send(message) debug_logger.debug("Sent Password Reset Email to %s Result: %s" % (user, result))
def _save_shout_index(shout=None, created=False): try: if created: raise NotFoundError() if shout.is_disabled: return delete_object_index(ShoutIndex, shout) shout_index = ShoutIndex.get(shout.pk) except NotFoundError: shout_index = ShoutIndex() shout_index._id = shout.pk shout_index = shout_index_from_shout(shout, shout_index) if shout_index.save(): debug_logger.debug('Created ShoutIndex: %s' % shout.pk) else: debug_logger.debug('Updated ShoutIndex: %s' % shout.pk) # Update the shout without saving the index not to fall in endless loop shout.save_shout_index = False shout.update(is_indexed=True)
def _send_verification_email(user): subject = _('Verify your email') subs = { 'text1': _("Your have changed your email therefore your account is not verified. To " "use Shoutit with full potential we need to verify your email."), 'action': _("Verify it now"), 'link': user.verification_link } message = prepare_message(user=user, subject=subject, template=SG_GENERAL_TEMPLATE, subs=subs) result = sg.send(message) debug_logger.debug("Sent Verification Email to %s Result: %s" % (user, result))
def _send_notification_email(user, notification, emailed_for=None): from shoutit.controllers import pusher_controller # Do nothing if the user is in app (subscribed to Pusher) if pusher_controller.check_pusher(user): return display = notification.display() subject = display['title'] if emailed_for: intro = _("Your page '%(page)s' has a new notification") % { 'page': emailed_for.name } auth_token = emailed_for.get_valid_auth_token(page_admin_user=user) else: intro = _("You have a new notification") auth_token = user.get_valid_auth_token() link = url_with_querystring(notification.web_url, auth_token=auth_token.pk) subs = { 'text1': """ %(intro)s <blockquote style="font-weight:bold;background-color:#EEEEEE;padding:10px;border-radius:5px;">%(text)s</blockquote> <p style="font-style:italic;color:#888888;margin-top:50px;">%(note)s</p> """ % { 'intro': force_text(intro), 'text': force_text(display['text']) or '', 'note': force_text(display.get('note')) or '' }, 'action': display['action'], 'link': link } message = prepare_message(user=user, subject=subject, template=SG_GENERAL_TEMPLATE, subs=subs) result = sg.send(message) debug_logger.debug("Sent Notification Email to %s Result: %s" % (user, result))
def filter_queryset(self, request, index_queryset, view): user = request.user listening = [] # Listened Tags tags = user.listening2_tags_names if tags: country = user.location.get('country') listening_tags = EQ('terms', tags=tags) & EQ('term', country=country) listening.append(listening_tags) # Listened Profiles + user himself profiles = [user.pk ] + user.listening2_pages_ids + user.listening2_users_ids if profiles: listening_profiles = EQ('terms', uid=map(str, profiles)) listening.append(listening_profiles) index_queryset = index_queryset.query('bool', should=listening) index_queryset = index_queryset.sort('-published_at') debug_logger.debug(index_queryset.to_dict()) return index_queryset
def video_auth(self, request): """ Create a video chat endpoint. ###REQUIRES AUTH ###Response <pre><code> { "token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCIsICJjdHkiOiAidHdpbGlvLWZwYTt2PTEifQ.eyJpc3MiOiAiU0s3MDFlYzE", "identity": "7c6ca4737db3447f936037374473e61f" } </code></pre> --- """ # Todo: Move the logic to Serializer user = request.user try: video_client = user.video_client # Check whether client has an expired token if timezone.now() > video_client.expires_at: video_client.delete() raise ValueError() except (AttributeError, ValueError): try: video_client = create_video_client(user) except (ValidationError, IntegrityError) as e: msg = _("Couldn't authorize you to make video calls") raise ShoutitBadRequest(message=msg, developer_message=unicode(e)) # Return token info res = OrderedDict([('identity', video_client.identity), ('token', video_client.token), ('expires_at', video_client.expires_at_unix)]) debug_logger.debug("Authorized %s to use Twilio with identity: %s" % (user, video_client.identity)) return Response(res)
def filter_queryset(self, request, index_queryset, view): user = view.get_object() data = request.query_params listening = [] # Listened Tags tags = user.listening2_tags_names if tags: country = user.location.get('country') listening_tags = Q('terms', tags=tags) & Q('term', country=country) listening.append(listening_tags) # Listened Profiles + user himself users = [user.pk ] + user.listening2_pages_ids + user.listening2_users_ids if users: listening_users = Q('terms', uid=map(str, users)) listening.append(listening_users) index_queryset = index_queryset.query('bool', should=listening) # Sort sort = data.get('sort') sort_types = { None: ('-published_at', ), 'time': ('-published_at', ), 'price_asc': ('price', ), 'price_desc': ('-price', ), } if sort and sort not in sort_types: raise ValidationError({'sort': ["Invalid sort"]}) # selected_sort = ('-priority',) + sort_types[sort] selected_sort = sort_types[sort] index_queryset = index_queryset.sort(*selected_sort) debug_logger.debug(index_queryset.to_dict()) return index_queryset
def user_post_save(sender, instance=None, created=False, update_fields=None, **kwargs): from shoutit.controllers import notifications_controller action = 'Created' if created else 'Updated' is_guest = 'Guest' if instance.is_guest else '' notify = getattr(instance, 'notify', True) debug_logger.debug('%s %sUser: %s | Notify: %s' % (action, is_guest, instance, notify)) # Mute / unmute user shouts if his active state was changed if isinstance(update_fields, frozenset): if 'is_active' in update_fields: if instance.is_active: instance.un_mute_shouts() else: instance.mute_shouts() if not created: if notify: # Send notification about user changes notifications_controller.notify_user_of_profile_update(instance)
def publish_shout_to_facebook(shout): la = getattr(shout.user, 'linked_facebook', None) if not la: debug_logger.debug( 'No linked_facebook, skip publishing Shout %s on Facebook' % shout) return if 'publish_actions' not in la.scopes: debug_logger.debug( 'No publish_actions in scopes, skip publishing Shout %s on Facebook' % shout) return prod = settings.SHOUTIT_ENV == 'prod' namespace = 'shoutitcom' if prod else 'shoutitcom-' + settings.SHOUTIT_ENV actions_url = 'https://graph.facebook.com/v2.6/me/%s:shout' % namespace params = { 'access_token': la.access_token, shout.get_type_display(): shout.web_url, 'privacy': "{'value':'EVERYONE'}" } if prod: params['fb:explicitly_shared'] = True res = requests.post(actions_url, params=params).json() id_on_facebook = res.get('id') if id_on_facebook: shout.published_on['facebook'] = id_on_facebook shout.save(update_fields=['published_on']) # Track mixpanel_controller.track(shout.user.pk, 'share_shout_on_fb', shout.track_properties) debug_logger.debug('Published shout %s on Facebook' % shout) else: error_logger.warn('Error publishing shout on Facebook', extra={ 'res': res, 'shout': shout })
def linked_facebook_account_post_delete(sender, instance, **kwargs): debug_logger.debug('Deleted LinkedFacebookAccount for %s' % instance.user)
def filter_queryset(self, request, index_queryset, view, extra_query_params=None): if not isinstance(index_queryset, Search): return index_queryset # Copy the query dict to be able to modify it as it is immutable, then update it with extra params data = request.query_params.copy() if isinstance(extra_query_params, dict): data.update(extra_query_params) # Update data from discover item shouts query if discover is passed discover = data.get('discover') if discover: try: discover_item = DiscoverItem.objects.get(id=discover) except ValueError: raise InvalidParameter('discover', _("Invalid discover id")) except DiscoverItem.DoesNotExist: msg = _( "Discover Item with id '%(discover)s' does not exist") % { 'discover': discover } raise InvalidParameter('discover', msg) else: data.update(discover_item.shouts_query) # Filter shouts by user id if user username is passed in `profile` query param user = data.get('profile') or data.get('user') if user: # Replace `me` with logged in username if user == 'me' and request.user.is_authenticated(): user = request.user.username # Get the user id using username try: user_id = str( User.objects.values('pk').get(username=user)['pk']) except User.DoesNotExist: msg = _( "Profile with username '%(username)s' does not exist") % { 'username': user } raise InvalidParameter('profile', msg) else: index_queryset = index_queryset.filter('term', uid=user_id) # When listing user's own shouts show him the expired ones if user == request.user.username: setattr(view, 'get_expired', True) # Exclude shouts using their ids exclude = data.get('exclude') if isinstance(exclude, basestring): exclude = exclude.split(',') if exclude and not isinstance(exclude, list): exclude = [exclude] if exclude: index_queryset = index_queryset.filter( ~EQ('terms', _id=map(str, exclude))) # Shout type shout_type = data.get('shout_type') if shout_type: if shout_type not in ['all', 'offer', 'request']: msg = _("Should be `all`, `request` or `offer`") raise InvalidParameter('shout_type', msg) if shout_type != 'all': index_queryset = index_queryset.filter('term', type=shout_type) # Search query search = data.get('search') if search: index_queryset = index_queryset.query( 'multi_match', query=search, fields=['title', 'text', 'tags'], fuzziness='AUTO') # Tags tags = data.get('tags') if tags: tags = tags.replace(',', ' ').split() tag_names = process_tags(tags) index_queryset = index_queryset.filter('terms', tags=tag_names) # Location: Country, State, City, Latitude, Longitude country = data.get('country', '').upper() if country and country != 'all': index_queryset = index_queryset.filter('term', country=country) # todo: add state city = data.get('city') if city and city != 'all': # todo: use other means of finding the surrounding cities like state. try: pd_city = PredefinedCity.objects.filter(city=city, country=country)[0] except IndexError: pass else: nearby_cities = pd_city.get_cities_within( settings.NEARBY_CITIES_RADIUS_KM) cities = map(lambda nc: nc.city, nearby_cities) cities.append(city) cities = arrays.unique(cities) index_queryset = index_queryset.filter('terms', city=cities) down_left_lat = data.get('down_left_lat') down_left_lng = data.get('down_left_lng') up_right_lat = data.get('up_right_lat') up_right_lng = data.get('up_right_lng') latlng_key = '' try: if down_left_lat: latlng_key = 'down_left_lat' down_left_lat = float(down_left_lat) up_right_lat = up_right_lat or 90 if down_left_lat > float(up_right_lat) or not ( 90 >= down_left_lat >= -90): raise InvalidParameter( 'down_left_lat', _("Should be between -90 and 90, also not greater than 'up_right_lat'" )) index_queryset = index_queryset.filter( 'range', **{'latitude': { 'gte': down_left_lat }}) if down_left_lng: latlng_key = 'down_left_lng' down_left_lng = float(down_left_lng) up_right_lng = up_right_lng or 180 if down_left_lng > float(up_right_lng) or not ( 180 >= down_left_lng >= -180): raise InvalidParameter( 'down_left_lng', _("Should be between -180 and 180, also not greater than 'up_right_lng'" )) index_queryset = index_queryset.filter( 'range', **{'longitude': { 'gte': down_left_lng }}) if up_right_lat: latlng_key = 'up_right_lat' if not (90 >= float(up_right_lat) >= -90): raise InvalidParameter('up_right_lat', _("Should be between -90 and 90")) index_queryset = index_queryset.filter( 'range', **{'latitude': { 'lte': up_right_lat }}) if up_right_lng: latlng_key = 'up_right_lng' if not (180 >= float(up_right_lng) >= -180): raise InvalidParameter('up_right_lng', _("Should be between -180 and 180")) index_queryset = index_queryset.filter( 'range', **{'longitude': { 'lte': up_right_lng }}) except ValueError: raise InvalidParameter(latlng_key, _("Invalid number")) # Category and Filters category = data.get('category') if category and category != 'all': try: category = Category.objects.prefetch_related('filters').get( slug=category) except Category.DoesNotExist: msg = _("Category with slug '%(slug)s' does not exist") % { 'slug': category } raise InvalidParameter('category', msg) else: data['category'] = category.slug index_queryset = index_queryset.filter( 'terms', category=[category.name, category.slug]) cat_filters = category.filters.values_list( 'slug', 'values_type') for cat_f_slug, cat_f_type in cat_filters: if cat_f_type == TAG_TYPE_STR: cat_f_param = data.get(cat_f_slug) if cat_f_param: cat_f_params = cat_f_param.split(',') index_queryset = index_queryset.filter( 'terms', **{'filters__%s' % cat_f_slug: cat_f_params}) elif cat_f_type == TAG_TYPE_INT: for m1, m2 in [('min', 'gte'), ('max', 'lte')]: cat_f_param = data.get('%s_%s' % (m1, cat_f_slug)) if cat_f_param: index_queryset = index_queryset.filter( 'range', **{ 'filters__%s' % cat_f_slug: { m2: cat_f_param } }) # Price min_price = data.get('min_price') if min_price: index_queryset = index_queryset.filter( 'range', **{'price': { 'gte': min_price }}) max_price = data.get('max_price') if max_price: index_queryset = index_queryset.filter( 'range', **{'price': { 'lte': max_price }}) # Expired if not getattr(view, 'get_expired', False): now = timezone.now() min_published = now - timedelta(days=int(settings.MAX_EXPIRY_DAYS)) # Recently published and no specified expires_at recently_published = EQ('range', **{'published_at': { 'gte': min_published }}) no_expiry_still_valid = EQ( 'bool', filter=[~EQ('exists', field='expires_at'), recently_published]) # Not expired not_expired = EQ('range', **{'expires_at': {'gte': now}}) expiry_still_valid = EQ( 'bool', filter=[EQ('exists', field='expires_at'), not_expired]) index_queryset = index_queryset.filter(no_expiry_still_valid | expiry_still_valid) # Sorting sort = data.get('sort') sort_types = { None: ('-published_at', ), 'time': ('-published_at', ), 'price_asc': ('price', ), 'price_desc': ('-price', ), } if sort and sort not in sort_types: raise InvalidParameter('sort', _("Invalid sort")) # selected_sort = ('-priority',) + sort_types[sort] selected_sort = sort_types[sort] if search: selected_sort = ('_score', ) + selected_sort index_queryset = index_queryset.sort(*selected_sort) debug_logger.debug(index_queryset.to_dict()) index_queryset.search_data = { k: parse_int(v, 10) or v for k, v in data.items() } return index_queryset
def filter_queryset(self, request, index_queryset, view, extra_query_params=None): if not isinstance(index_queryset, Search): return index_queryset # Copy the query dict to be able to modify it as it is immutable, then update it with extra params data = request.query_params.copy() if isinstance(extra_query_params, dict): data.update(extra_query_params) # Update data from discover item shouts query if discover is passed discover = data.get('discover') if discover: try: discover_item = DiscoverItem.objects.get(id=discover) except DiscoverItem.DoesNotExist: raise ValidationError({ 'discover': ["Discover Item with id '%s' does not exist" % discover] }) else: data.update(discover_item.shouts_query) # Filter shouts by user id if user username or id are passed in `user` query param user = data.get('user') if user: try: user_id = User.objects.get(username=user).pk except User.DoesNotExist: raise ValidationError({ 'user': ["User with username '%s' does not exist" % user] }) else: index_queryset = index_queryset.filter('term', uid=user_id) # Exclude ids exclude_ids = data.get('exclude_ids') if isinstance(exclude_ids, basestring): exclude_ids = exclude_ids.split(',') if exclude_ids and not isinstance(exclude_ids, list): exclude_ids = [exclude_ids] if exclude_ids: index_queryset = index_queryset.filter( ~Q('terms', _id=map(str, exclude_ids))) # Shout type shout_type = data.get('shout_type') if shout_type: if shout_type not in ['all', 'offer', 'request']: raise ValidationError( {'shout_type': ["Should be `all`, `request` or `offer`"]}) if shout_type != 'all': index_queryset = index_queryset.filter('term', type=shout_type) # Search query search = data.get('search') if search: index_queryset = index_queryset.query( 'multi_match', query=search, fields=['title', 'text', 'tags'], fuzziness='AUTO') # Tags tags = data.get('tags') if tags: tags = tags.replace(',', ' ').split() tag_names = process_tags(tags) index_queryset = index_queryset.filter('terms', tags=tag_names) # Location: Country, State, City, Latitude, Longitude country = data.get('country', '').upper() if country and country != 'all': index_queryset = index_queryset.filter('term', country=country) # todo: add state city = data.get('city') if city and city != 'all': # todo: use other means of finding the surrounding cities like state. try: pd_city = PredefinedCity.objects.filter(city=city, country=country)[0] except IndexError: pass else: nearby_cities = pd_city.get_cities_within( settings.NEARBY_CITIES_RADIUS_KM) cities = map(lambda nc: nc.city, nearby_cities) cities.append(city) cities = arrays.unique(cities) index_queryset = index_queryset.filter('terms', city=cities) latlng_errors = OrderedDict() down_left_lat = data.get('down_left_lat') down_left_lng = data.get('down_left_lng') up_right_lat = data.get('up_right_lat') up_right_lng = data.get('up_right_lng') try: if down_left_lat: down_left_lat = float(down_left_lat) if down_left_lat > float(up_right_lat) or not ( 90 >= down_left_lat >= -90): latlng_errors['down_left_lat'] = [ "should be between -90 and 90, also not greater than 'up_right_lat'" ] index_queryset = index_queryset.filter( 'range', **{'latitude': { 'gte': down_left_lat }}) if down_left_lng: down_left_lng = float(down_left_lng) if down_left_lng > float(up_right_lng) or not ( 180 >= down_left_lng >= -180): latlng_errors['down_left_lng'] = [ "should be between -180 and 180, also not greater than 'up_right_lng'" ] index_queryset = index_queryset.filter( 'range', **{'longitude': { 'gte': down_left_lng }}) if up_right_lat: if not (90 >= float(up_right_lat) >= -90): latlng_errors['up_right_lat'] = [ "should be between -90 and 90" ] index_queryset = index_queryset.filter( 'range', **{'latitude': { 'lte': up_right_lat }}) if up_right_lng: if not (180 >= float(up_right_lng) >= -180): latlng_errors['up_right_lng'] = [ "should be between -180 and 180" ] index_queryset = index_queryset.filter( 'range', **{'longitude': { 'lte': up_right_lng }}) except ValueError: latlng_errors['error'] = ["invalid lat or lng parameters"] if latlng_errors: raise ValidationError(latlng_errors) # Category and Filters category = data.get('category') if category and category != 'all': try: category = Category.objects.prefetch_related('filters').get( DQ(name=category) | DQ(slug=category)) except Category.DoesNotExist: raise ValidationError({ 'category': [ "Category with name or slug '%s' does not exist" % category ] }) else: data['category'] = category.slug index_queryset = index_queryset.filter( 'terms', category=[category.name, category.slug]) cat_filters = category.filters.values_list( 'slug', 'values_type') for cat_f_slug, cat_f_type in cat_filters: if cat_f_type == TAG_TYPE_STR: cat_f_param = data.get(cat_f_slug) if cat_f_param: index_queryset = index_queryset.filter( 'term', **{'filters__%s' % cat_f_slug: cat_f_param}) elif cat_f_type == TAG_TYPE_INT: for m1, m2 in [('min', 'gte'), ('max', 'lte')]: cat_f_param = data.get('%s_%s' % (m1, cat_f_slug)) if cat_f_param: index_queryset = index_queryset.filter( 'range', **{ 'filters__%s' % cat_f_slug: { m2: cat_f_param } }) # Price min_price = data.get('min_price') if min_price: index_queryset = index_queryset.filter( 'range', **{'price': { 'gte': min_price }}) max_price = data.get('max_price') if max_price: index_queryset = index_queryset.filter( 'range', **{'price': { 'lte': max_price }}) # Sorting sort = data.get('sort') sort_types = { None: ('-published_at', ), 'time': ('-published_at', ), 'price_asc': ('price', ), 'price_desc': ('-price', ), } if sort and sort not in sort_types: raise ValidationError({'sort': ["Invalid sort"]}) # selected_sort = ('-priority',) + sort_types[sort] selected_sort = sort_types[sort] if search: selected_sort = ('_score', ) + selected_sort index_queryset = index_queryset.sort(*selected_sort) debug_logger.debug(index_queryset.to_dict()) index_queryset.search_data = { k: parse_int(v, 10) or v for k, v in data.items() } return index_queryset
def delete_apns_devices(self): APNSDevice.objects.filter(user=self).delete() debug_logger.debug("Deleted APNSDevices for %s" % self)
def delete_gcm_devices(self): GCMDevice.objects.filter(user=self).delete() debug_logger.debug("Deleted GCMDevices for %s" % self)
def _subscribe_users_to_mailing_list(users=None, user_ids=None, raise_errors=True): if users is None: users = User.objects.filter(id__in=user_ids) request_body = [] for user in users: ap = user.ap fields = { 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, 'is_active': 'true' if user.is_active else 'false', 'is_activated': 'true' if user.is_activated else 'false', 'type': user.v3_type_name, 'username': user.username, 'date_joined': date_unix(user.date_joined), 'last_login': date_unix(user.last_login) if user.last_login else 0, 'country': ap.country, 'image': ap.image, 'platform': " ".join( map(lambda c: str(c.replace('shoutit-', '')), user.api_client_names)), 'gender': getattr(ap, 'gender', ''), } request_body.append(fields) try: response = sg_api.client.contactdb.recipients.post( request_body=request_body) response_data = json.loads(response.response_body) # Check added if response_data['new_count'] > 0: debug_logger.debug("Added %d user(s) to SendGrid Contacts DB" % response_data['new_count']) # Check updated if response_data['updated_count'] > 0: debug_logger.debug("Updated %d user(s) on SendGrid Contacts DB" % response_data['updated_count']) # Update added / updated users added_emails = map(lambda pr: base64.b64decode(pr), response_data['persisted_recipients']) User.objects.filter(email__in=added_emails).update( on_mailing_list=True) # Errors if response_data['error_count'] > 0: debug_logger.warning( "Error adding/updating %d user(s) to SendGrid contacts db" % response_data['error_count']) debug_logger.warning(response_data['errors']) raise ValueError(response_data['errors']) except Exception as e: debug_logger.warning("Error adding/updating %d users to SendGrid: %s" % (len(users), str(e))) if raise_errors: raise
def linked_facebook_account_post_save(sender, instance, created, **kwargs): action = 'Created' if created else 'Updated' debug_logger.debug('%s LinkedFacebookAccount for %s' % (action, instance.user))
def handle(self, *args, **options): users = list(User.objects.filter(username__startswith='test_100')) categories = list(Category.objects.all()) cities = PredefinedCity.objects.all() # adding test users if we don't have them if not len(users) == self.max_users: for i in range(self.max_users): username = '******' + str(1000000 + i) email = username + '@shoutit.com' user, created = User.objects.get_or_create(username=username, first_name='User', last_name=username, email=email, is_test=True) if created: profile = user.profile city = random.choice(cities) profile.city = city.city profile.country = city.country profile.latitude = city.latitude + random.uniform( -3, 3) / 100.0 profile.longitude = city.longitude + random.uniform( -3, 3) / 100.0 profile.save() debug_logger.debug( 'Created test user in: {}, lat: {}, lng: {}'.format( user.profile.city, user.profile.latitude, user.profile.longitude)) users.append(user) for i in range( min(max(options.get('num_shouts')[0], self.min_shouts), self.max_shouts)): user = random.choice(users) type = random.choice(['offer', 'request']) category = random.choice(categories) city = random.choice(cities) tags = Tag.objects.filter(key__categories=category).values_list( 'slug', flat=True) tags = ['filling-shout'] + random.sample( tags, random.randint(0, min(5, len(tags)))) self.stdout.write(str(tags)) images = [ "https://shout-image.static.shoutit.com/opo0928a.jpg", "https://shout-image.static.shoutit.com/heic1501a.jpg", "https://shout-image.static.shoutit.com/heic0702a.jpg" ] random.shuffle(images) shout_data = { "type": type, "title": "{0} {1} in {2} at {3:0.0f}".format(category.name, type, city.city, time.time()), "text": " ".join(tags), "price": random.randint(0, 1000), "currency": "EUR", "images": images, "category": { "name": category.name }, "tags": [{ 'name': t } for t in tags], "location": { "country": city.country, "city": city.city, "latitude": city.latitude + random.uniform(-4, 3) / 100.0, "longitude": city.longitude + random.uniform(-4, 3) / 100.0 } } request = create_fake_request('v2') request._user = user shout = ShoutDetailSerializer(data=shout_data, context={'request': request}) shout.is_valid(True) shout.save() self.stdout.write('Successfully filled shouts')