def query_for_deals(user, filter_by, sort): ''' This function takes the user and sort parameters and queries MongoDB accordingly. The retrieved documents will be filtered and sorted as defined by by the parameters user and sort. ''' deals = None type_of_sorts = { 'newest': '-created', 'popular': '-num_votes', 'trending': '-score' } sort = type_of_sorts.get(sort, '-created') if filter_by == 'shared': deals = Deal.objects(deleted=False, author_id=str(user.id))\ .order_by(sort)\ .limit(max_num_documents)\ .exclude('flags', 'sockvotes', 'votes') elif filter_by == 'liked': deals = Deal.objects(id__in=user.deals_voted)\ .order_by(sort)\ .limit(max_num_documents)\ .exclude('flags', 'sockvotes', 'votes') elif filter_by == 'bookmarked': deals = Deal.objects(id__in=user.deals_saved)\ .order_by(sort)\ .limit(max_num_documents)\ .exclude('flags', 'sockvotes', 'votes') else: return abort(404) return deals
def query_for_deals(user, filter_by, sort): ''' This function takes the user and sort parameters and queries MongoDB accordingly. The retrieved documents will be filtered and sorted as defined by by the parameters user and sort. ''' deals = None type_of_sorts = {'newest': '-created', 'popular': '-num_votes', 'trending': '-score'} sort = type_of_sorts.get(sort, '-created') if filter_by == 'shared': deals = Deal.objects(deleted=False, author_id=str(user.id))\ .order_by(sort)\ .limit(max_num_documents)\ .exclude('flags', 'sockvotes', 'votes') elif filter_by == 'liked': deals = Deal.objects(id__in=user.deals_voted)\ .order_by(sort)\ .limit(max_num_documents)\ .exclude('flags', 'sockvotes', 'votes') elif filter_by == 'bookmarked': deals = Deal.objects(id__in=user.deals_saved)\ .order_by(sort)\ .limit(max_num_documents)\ .exclude('flags', 'sockvotes', 'votes') else: return abort(404) return deals
def upvote(deal_id, user_id, remote_addr): try: new_vote = Vote(deal_id=str(deal_id), ip=remote_addr, voter_id=str(user_id)) new_vote.save() Deal.objects(id=deal_id).update_one(push__votes=str(new_vote.id)) user = User.objects(id=user_id).first() user.votes.append(str(new_vote.id)) user.save() except Exception, exc: #log error here upvote.retry(exc=exc, delay=task_retry_delay)
def flag(deal_id, user_id): try: deal_queryset = Deal.objects(id=deal_id) deal_queryset.update_one(push__flags=user_id) except Exception, exc: #log error here flag.retry(exc=exc, delay=task_retry_delay)
def delete_deal(deal_id): ''' This function is used by a user to delete a deal. The user trying to delete this deal must be the author of the deal. We are not sending this off to celery as a async task b'c we want to ensure that this a deal is deleted immediately, rather at time delta later ''' msg = {} user = User.objects(id=current_user.id).first() if str(deal_id) not in user.deals_submitted: msg['status'] = 'error' msg['message'] = 'you cannot delete this deal b\'c you are not the author' return jsonify(msg) try: deal = Deal.objects(id=deal_id).first() deal.deleted = True deal.save() remove_deal(deal.sequence_num) remove_deal_num_from_lists(deal.sequence_num) except Exception as e: print e msg['status'] = 'error' msg['message'] = 'error occured while deleting user object' return jsonify(msg) msg['status'] = 'success' return jsonify(msg)
def edit_deal(deal_id): ''' This function is used to allow a user to edit the description of a deal that he or she has submitted ''' deal = Deal.objects(id=deal_id).first() if deal is None: return abort(404) user = get_current_user() if user is None or str(get_current_user().id) != deal.author_id: return abort(404) msg = {} form = Edit_Form(csrf_enabled=False) if request.method == 'POST' and form.validate_on_submit(): print request.form description = request.form.get('description', None) if description: deal.description = description deal.edited = datetime.now() deal.save() store_deal(deal, overwrite=True) next = Href('/') next = next('deals', deal.sequence_num, deal.short_title) msg['status'] = 'success' else: msg['status'] = 'error' msg['description_error'] = form.description.errors[0] return jsonify(msg)
def delete(deal_id): try: deal = Deal.objects(id=deal_id).first() deal.deleted = True deal.save() except Exception, exc: #log error here delete.retry(exc=exc, countdown=task_retry_delay)
def num_likes_received(self): ''' This method returns the total amounts of points that this user's submitted deal has received ''' key = "".join([self.name, '_num_likes_received']) if r.exists(key): return r.get(key) else: # points = [deal.num_votes for deal in self.deals_submitted] # total_points = sum(points) deals = Deal.objects(id__in=self.deals_submitted) points = [deal.num_votes for deal in deals] total_points = sum(points) r.setex(key, 3600, total_points) return total_points
def show_deal(sequence_num, short_title): deal_json = get_deal(sequence_num) if deal_json is None: deal = Deal.objects(sequence_num=sequence_num, short_title=short_title).first() if deal == None: abort(404) deal_json = jsonify(deal) # current date and sort are needed to build the url in the category and # date filter sidebar current_date = session.get('current_date', 'week') current_sort = session.get('current_sort', 'trending') return render_template('deal.html', deal=deal_json, current_category=deal_json['category'], current_date=current_date, current_sort=current_sort)
def do_action(): ''' This function is called by custom.js to complete various action on a deal. It first checks the validity of the user and the input. Namely, is the user logged in, is the deal id passed in, is the deal_id valid. It returns appropriate error msg if the above conditions are not met. If the conditions are met, this functions calls other helper functions to complete actions as requested by custom.js, such as upvote, save, flag and delete. ''' deal_id = request.form.get('deal_id', None) action = request.form.get('action', None) #error checking below: #user is not logged in msg = {} if current_user.is_anonymous(): msg['status'] = 'error' msg['message'] = 'user not logged in' return jsonify(msg) #deal_id is not passed in if deal_id is None: msg['status'] = 'error' msg['message'] = 'deal id not passed in' return jsonify(msg) #we cannot find a deal with the deal id that's passed in deal_queryset = Deal.objects(id=deal_id) if deal_queryset.first() is None: msg['status'] = 'error' msg['message'] = 'deal does not exist' return jsonify(msg) #call helper tasks to complete the action if action == 'vote': msg = vote_deal(deal_id) elif action == 'save': msg = save_deal(deal_id) elif action == 'flag': msg = flag_deal(deal_id) elif action == 'delete': msg = delete_deal(deal_id) return msg
def query_for_deals(category, date_range, sort): ''' This function queries MongoDB according to the parameters. The retrieved documents will be filtered by category and date, then sorted by sort. ''' from datetime import datetime, timedelta # The following is to account for the possiblity that the parameter # 'category' is equal to 'everything'. If that's case, we need to retrieve # any deal whose category is found in the global list, 'categories' # In order to create this kind of query, we need to use the keyword 'in' # rather than the traditional keyword '='. And queries using # 'in' requires us to query against a list of values rather than one # specific value categories_to_query_against = [] if category == 'everything': # excluding the catch-all-category "everything" categories_to_query_against = categories[1:] else: categories_to_query_against = [category] #filter the documents by category and date date_ranges = { 'today': datetime.now() - timedelta(days=1), 'week': datetime.now() - timedelta(days=7), 'month': datetime.now() - timedelta(days=30), 'year': datetime.now() - timedelta(days=356), } min_date = date_ranges[date_range] type_of_sorts = {'newest': '-created', 'popular': '-num_votes', 'trending': '-score'} sort = type_of_sorts.get(sort, '-created') deals = Deal.objects(created__gte=min_date, category__in=categories_to_query_against, dead=False, deleted=False) \ .order_by(sort) \ .limit(max_num_documents) \ .exclude('flags', 'sockvotes', 'votes') return deals
def get_deal(deal_sequence_num): ''' This function takes in a deal_id and returns the associating deal object. We 1st checks redis to for the deal obj. If not its not found in redis, we retrieve the deal obj from mongohq and store the deal obj in redis ''' if deal_sequence_num.__class__.__name__ == 'str': deal_sequence_num = int(deal_sequence_num, 10) #check to see if this deal is stored in the local redis cache key, fieldset = gen_key_fieldset(deal_sequence_num, 'deal') deal_json = r.hget(key, fieldset) if deal_json: return json.loads(deal_json) #not found in redis, retrieve it from mongodb via mongohq deal = Deal.objects(sequence_num=deal_sequence_num).first() if deal is None: abort(404) deal_json = store_deal(deal, key=key, fieldset=fieldset, return_json=True) return deal_json
def vote_deal(deal_id): ''' This function updates the number of votes of the deal by: 1) increasing num_votes by 1 2) add a new vote object into a deal's 'votes' list ''' msg = {} user = get_current_user() if str(deal_id) in user.votes: msg['status'] = 'error' msg['message'] = 'you cannot vote for the same deal twice' return jsonify(msg) # we want to make sure that the user see's that his or her vote was counted # right away w/o any delay. Hence, the following line is part of # celery_tasks.upvote else: try: user.deals_voted.append(str(deal_id)) user.save() deal_queryset = Deal.objects(id=deal_id) deal_queryset.update_one(inc__num_votes=1) deal = deal_queryset.first() # flushing redis cache to reflect the new vote count remove_deal(deal.sequence_num) # update redis cache: noting that current user has voted this deal in redis set_user_action_as_completed('vote', deal_id, user.sequence_num) for sort in sorts: r.delete("".join([user.name, '_', 'liked', '_', sort])) # update mongodb celery_tasks.upvote.delay(deal_id, user.id, request.remote_addr) msg['status'] = 'success' return jsonify(msg) except Exception as e: print e abort(404)
def post_deal(): form = Deal_Form() # if current_user is None: # msg = {"status": "error", "message": "user not logged in"} # return msg if request.method == 'GET': return render_template('post_deal.html', form=form) elif request.method == 'POST': if form.validate_on_submit(): title = request.form.get('title') title = string.strip(title) short_title = title[0:short_title_length - 1] short_title = string_to_url_fix(short_title) category = request.form.get('categories') category = string.lower(category) location = request.form.get('location', None) if location == "": location = None if location and is_amazon_url(location): location = gen_amazon_affiliate_url(location) description = request.form.get('description', None) user = get_current_user() ip = request.remote_addr new_deal = Deal(title=title, short_title=short_title, location=location, category=category, description=description, author_id=str(user.id), num_votes=1, ip=ip) new_deal.save() new_deal_id = new_deal.id # updating redis cache store_deal(new_deal) insert_new_deal_into_list(category, new_deal.sequence_num) set_user_action_as_completed('vote', new_deal_id, user.sequence_num) for sort in sorts: r.delete("".join([user.name, '_', 'shared', '_', sort])) # updating mongodb or datastore user.deals_voted.append(str(new_deal_id)) user.deals_submitted.append(str(new_deal_id)) user.save() celery_tasks.upvote.delay(new_deal_id, user.id, request.remote_addr) #building this deal's url so to redirect the user next = Href('/') next = next('deals', new_deal.sequence_num, new_deal.short_title) msg = {'status': 'success', 'redirect': next} return jsonify(msg) else: #if form returns errors, return the errors to the users via js msg = {"status": "error"} if form.title.errors: msg["title_error"] = form.title.errors[0] if form.location.errors: msg["location_error"] = form.location.errors[0] if form.categories.errors: msg["category_error"] = form.categories.errors[0] if form.description.errors: msg["description_error"] = form.description.errors[0] return jsonify(msg) else: abort(404)
def get_url(deal_id): deal = Deal.objects(id=deal_id).first() url_root = request.url_root url = "".join([url_root, deal.url[1:]]) # strips the leading "/" msg = {'url': url} return jsonify(msg)