def _get_thread_replies(request, thread, offset=1, limit=None): ''' Get and sort the replies for a thread. By default, offset = 1 to skip the original message. ''' if not thread: raise Http404 if "sort" in request.GET and request.GET["sort"] == "date": sort_mode = "date" emails = thread.emails else: sort_mode = "thread" emails = thread.emails_by_reply # XXX: Storm-specific emails = emails.find() emails.config(offset=offset, limit=limit) emails = list(emails) for email in emails: # Extract all the votes for this message set_message_votes(email, request.user) if sort_mode == "thread": email.level = email.thread_depth - 1 # replies start ragged left if email.level > 5: email.level = 5 return emails
def vote(request, mlist_fqdn, message_id_hash): """ Add a rating to a given message identified by messageid. """ if request.method != 'POST': raise SuspiciousOperation if not request.user.is_authenticated(): return HttpResponse('You must be logged in to vote', content_type="text/plain", status=403) store = get_store(request) message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash) if message is None: raise Http404 value = int(request.POST['vote']) if value not in [-1, 0, 1]: raise SuspiciousOperation # Checks if the user has already voted for a this message. try: v = Rating.objects.get(user=request.user, messageid=message_id_hash, list_address=mlist_fqdn) if v.vote == value: return HttpResponse("You've already cast this vote", content_type="text/plain", status=403) except Rating.DoesNotExist: if value != 0: v = Rating(list_address=mlist_fqdn, messageid=message_id_hash, vote=value) v.user = request.user else: return HttpResponse("There is no vote to cancel", content_type="text/plain", status=500) if value == 0: v.delete() else: v.vote = value v.save() # Extract all the votes for this message to refresh it set_message_votes(message, request.user) t = loader.get_template('messages/like_form.html') html = t.render( RequestContext(request, { "object": message, "message_id_hash": message_id_hash, })) result = { "like": message.likes, "dislike": message.dislikes, "html": html, } return HttpResponse(json.dumps(result), mimetype='application/javascript')
def search(request, page=1): """ Returns messages corresponding to a query """ results_per_page = 10 store = get_store(request) query = request.GET.get("query") mlist_fqdn = request.GET.get("list") sort_mode = request.GET.get('sort') if mlist_fqdn is None: mlist = None else: mlist = store.get_list(mlist_fqdn) if mlist is None: raise Http404("No archived mailing-list by that name.") if not query: return render( request, "search_results.html", { 'mlist': mlist, "query": query or "", 'messages': [], 'total': 0, 'sort_mode': sort_mode, }) try: page_num = int(request.GET.get('page', "1")) except ValueError: page_num = 1 sortedby = None reverse = False if sort_mode == "date-asc": sortedby = "date" elif sort_mode == "date-desc": sortedby = "date" reverse = True query_result = store.search(query, mlist_fqdn, page_num, results_per_page, sortedby=sortedby, reverse=reverse) total = query_result["total"] messages = query_result["results"] for message in messages: set_message_votes(message, request.user) paginator = SearchPaginator(messages, 10, total) messages = paginate(messages, page_num, paginator=paginator) context = { 'mlist': mlist, "query": query, 'messages': messages, 'total': total, 'sort_mode': sort_mode, } return render(request, "search_results.html", context)
def vote(request, mlist_fqdn, message_id_hash): """ Add a rating to a given message identified by messageid. """ if request.method != 'POST': raise SuspiciousOperation if not request.user.is_authenticated(): return HttpResponse('You must be logged in to vote', content_type="text/plain", status=403) store = get_store(request) message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash) if message is None: raise Http404 value = int(request.POST['vote']) if value not in [-1, 0, 1]: raise SuspiciousOperation # Checks if the user has already voted for a this message. try: v = Rating.objects.get(user=request.user, messageid=message_id_hash, list_address=mlist_fqdn) if v.vote == value: return HttpResponse("You've already cast this vote", content_type="text/plain", status=403) except Rating.DoesNotExist: if value != 0: v = Rating(list_address=mlist_fqdn, messageid=message_id_hash, vote=value) v.user = request.user else: return HttpResponse("There is no vote to cancel", content_type="text/plain", status=500) if value == 0: v.delete() else: v.vote = value v.save() # Invalidate the cache for the thread and user votes cache.delete("list:%s:thread:%s:votes" % (mlist_fqdn, message.thread_id)) if message.user_id: cache.delete("user:%s:list:%s:votes" % (message.user_id, mlist_fqdn)) # Extract all the votes for this message to refresh it set_message_votes(message, request.user) t = loader.get_template('messages/like_form.html') html = t.render(RequestContext(request, { "object": message, "message_id_hash": message_id_hash, })) result = { "like": message.likes, "dislike": message.dislikes, "html": html, } return HttpResponse(json.dumps(result), content_type='application/javascript')
def search(request, page=1): """ Returns messages corresponding to a query """ results_per_page = 10 store = get_store(request) query = request.GET.get("query") mlist_fqdn = request.GET.get("list") sort_mode = request.GET.get('sort') if mlist_fqdn is None: mlist = None else: mlist = store.get_list(mlist_fqdn) if mlist is None: raise Http404("No archived mailing-list by that name.") if not query: return render(request, "search_results.html", { 'mlist' : mlist, "query": query or "", 'messages': [], 'total': 0, 'sort_mode': sort_mode, }) try: page_num = int(request.GET.get('page', "1")) except ValueError: page_num = 1 sortedby = None reverse = False if sort_mode == "date-asc": sortedby = "date" elif sort_mode == "date-desc": sortedby = "date" reverse = True query_result = store.search(query, mlist_fqdn, page_num, results_per_page, sortedby=sortedby, reverse=reverse) total = query_result["total"] messages = query_result["results"] for message in messages: set_message_votes(message, request.user) paginator = SearchPaginator(messages, 10, total) messages = paginate(messages, page_num, paginator=paginator) context = { 'mlist' : mlist, "query": query, 'messages': messages, 'total': total, 'sort_mode': sort_mode, } return render(request, "search_results.html", context)
def posts(request, user_id): store = get_store(request) mlist_fqdn = request.GET.get("list") sort_mode = request.GET.get('sort') if mlist_fqdn is None: mlist = None return HttpResponse("Not implemented yet", status=500) else: mlist = store.get_list(mlist_fqdn) if mlist is None: raise Http404("No archived mailing-list by that name.") if not is_mlist_authorized(request, mlist): return render(request, "errors/private.html", { "mlist": mlist, }, status=403) # Get the user's full name try: client = mailmanclient.Client('%s/3.0' % settings.MAILMAN_REST_SERVER, settings.MAILMAN_API_USER, settings.MAILMAN_API_PASS) mm_user = client.get_user(user_id) except HTTPError: raise Http404("No user with this ID: %s" % user_id) except mailmanclient.MailmanConnectionError: fullname = None else: fullname = mm_user.display_name if not fullname: fullname = store.get_sender_name(user_id) # Get the messages and paginate them messages = store.get_messages_by_user_id(user_id, mlist_fqdn) try: page_num = int(request.GET.get('page', "1")) except ValueError: page_num = 1 messages = paginate(messages, page_num) for message in messages: set_message_votes(message, request.user) context = { 'user_id': user_id, 'mlist' : mlist, 'messages': messages, 'fullname': fullname, } return render(request, "user_posts.html", context)
def index(request, mlist_fqdn, message_id_hash): ''' Displays a single message identified by its message_id_hash (derived from message_id) ''' store = get_store(request) message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash) if message is None: raise Http404 message.sender_email = message.sender_email.strip() set_message_votes(message, request.user) mlist = store.get_list(mlist_fqdn) context = { 'mlist' : mlist, 'message': message, 'message_id_hash' : message_id_hash, 'months_list': get_months(store, mlist.name), 'reply_form': ReplyForm(), } return render(request, "message.html", context)
def index(request, mlist_fqdn, message_id_hash): ''' Displays a single message identified by its message_id_hash (derived from message_id) ''' store = get_store(request) message = store.get_message_by_hash_from_list(mlist_fqdn, message_id_hash) if message is None: raise Http404 message.sender_email = message.sender_email.strip() set_message_votes(message, request.user) mlist = store.get_list(mlist_fqdn) context = { 'mlist': mlist, 'message': message, 'message_id_hash': message_id_hash, 'months_list': get_months(store, mlist.name), 'reply_form': ReplyForm(), } return render(request, "message.html", context)
def thread_index(request, mlist_fqdn, threadid, month=None, year=None): ''' Displays all the email for a given thread identifier ''' store = get_store(request) thread = store.get_thread(mlist_fqdn, threadid) if not thread: raise Http404 prev_thread, next_thread = store.get_thread_neighbors(mlist_fqdn, threadid) sort_mode = request.GET.get("sort", "thread") set_message_votes(thread.starting_email, request.user) # Tags tag_form = AddTagForm() try: tags = Tag.objects.filter(threadid=threadid, list_address=mlist_fqdn) except Tag.DoesNotExist: tags = [] # Favorites fav_action = "add" if request.user.is_authenticated(): try: Favorite.objects.get(list_address=mlist_fqdn, threadid=threadid, user=request.user) except Favorite.DoesNotExist: pass else: fav_action = "rm" # Category category, category_form = get_category_widget(request, thread.category) # Extract relative dates today = datetime.date.today() days_old = today - thread.starting_email.date.date() days_inactive = today - thread.last_email.date.date() mlist = store.get_list(mlist_fqdn) subject = stripped_subject(mlist, thread.starting_email.subject) # Last view last_view = None if request.user.is_authenticated(): last_view_obj, created = LastView.objects.get_or_create( list_address=mlist_fqdn, threadid=threadid, user=request.user) if not created: last_view = last_view_obj.view_date last_view_obj.save() # update timestamp # get the number of unread messages if last_view is None: if request.user.is_authenticated(): unread_count = len(thread) else: unread_count = 0 else: # XXX: Storm-specific unread_count = thread.replies_after(last_view).count() # Flash messages flash_messages = [] flash_msg = request.GET.get("msg") if flash_msg: flash_msg = { "type": FLASH_MESSAGES[flash_msg][0], "msg": FLASH_MESSAGES[flash_msg][1] } flash_messages.append(flash_msg) # TODO: eventually move to a middleware ? # http://djangosnippets.org/snippets/1865/ is_bot = True user_agent = request.META.get('HTTP_USER_AGENT', None) if user_agent: is_bot = robot_detection.is_robot(user_agent) context = { 'mlist': mlist, 'threadid': threadid, 'subject': subject, 'tags': tags, 'addtag_form': tag_form, 'month': thread.date_active, 'first_mail': thread.starting_email, 'neighbors': (prev_thread, next_thread), 'months_list': get_months(store, mlist.name), 'days_inactive': days_inactive.days, 'days_old': days_old.days, 'sort_mode': sort_mode, 'fav_action': fav_action, 'reply_form': ReplyForm(), 'is_bot': is_bot, 'num_comments': len(thread), 'participants': thread.participants, 'last_view': last_view, 'unread_count': unread_count, 'category_form': category_form, 'category': category, 'flash_messages': flash_messages, } context["participants"].sort(key=lambda x: x[0].lower()) if is_bot: # Don't rely on AJAX to load the replies # The limit is a safety measure, don't let a bot kill the DB context["replies"] = _get_thread_replies(request, thread, limit=1000) return render(request, "thread.html", context)
def thread_index(request, mlist_fqdn, threadid, month=None, year=None): ''' Displays all the email for a given thread identifier ''' search_form = SearchForm(auto_id=False) store = get_store(request) thread = store.get_thread(mlist_fqdn, threadid) if not thread: raise Http404 prev_thread, next_thread = store.get_thread_neighbors(mlist_fqdn, threadid) sort_mode = request.GET.get("sort", "thread") set_message_votes(thread.starting_email, request.user) from_url = reverse("thread", kwargs={"mlist_fqdn":mlist_fqdn, "threadid":threadid}) # Tags tag_form = AddTagForm(initial={'from_url' : from_url}) try: tags = Tag.objects.filter(threadid=threadid, list_address=mlist_fqdn) except Tag.DoesNotExist: tags = [] # Favorites fav_action = "add" if request.user.is_authenticated(): try: Favorite.objects.get(list_address=mlist_fqdn, threadid=threadid, user=request.user) except Favorite.DoesNotExist: pass else: fav_action = "rm" # Extract relative dates today = datetime.date.today() days_old = today - thread.starting_email.date.date() days_inactive = today - thread.last_email.date.date() mlist = store.get_list(mlist_fqdn) subject = stripped_subject(mlist, thread.starting_email.subject) # TODO: eventually move to a middleware ? # http://djangosnippets.org/snippets/1865/ is_bot = True user_agent = request.META.get('HTTP_USER_AGENT', None) if user_agent: is_bot = robot_detection.is_robot(user_agent) context = { 'mlist': mlist, 'threadid': threadid, 'subject': subject, 'tags': tags, 'search_form': search_form, 'addtag_form': tag_form, 'month': thread.date_active, 'first_mail': thread.starting_email, 'neighbors': (prev_thread, next_thread), 'months_list': get_months(store, mlist.name), 'days_inactive': days_inactive.days, 'days_old': days_old.days, 'sort_mode': sort_mode, 'fav_action': fav_action, 'reply_form': ReplyForm(), 'is_bot': is_bot, 'participants': thread.participants, } context["participants"].sort(key=lambda x: x[0].lower()) if is_bot: # Don't rely on AJAX to load the replies context["replies"] = _get_thread_replies(request, thread) return render(request, "thread.html", context)
def thread_index(request, mlist_fqdn, threadid, month=None, year=None): ''' Displays all the email for a given thread identifier ''' search_form = SearchForm(auto_id=False) store = get_store(request) thread = store.get_thread(mlist_fqdn, threadid) if not thread: raise Http404 prev_thread, next_thread = store.get_thread_neighbors(mlist_fqdn, threadid) sort_mode = request.GET.get("sort", "thread") set_message_votes(thread.starting_email, request.user) from_url = reverse("thread", kwargs={ "mlist_fqdn": mlist_fqdn, "threadid": threadid }) # Tags tag_form = AddTagForm(initial={'from_url': from_url}) try: tags = Tag.objects.filter(threadid=threadid, list_address=mlist_fqdn) except Tag.DoesNotExist: tags = [] # Favorites fav_action = "add" if request.user.is_authenticated(): try: Favorite.objects.get(list_address=mlist_fqdn, threadid=threadid, user=request.user) except Favorite.DoesNotExist: pass else: fav_action = "rm" # Extract relative dates today = datetime.date.today() days_old = today - thread.starting_email.date.date() days_inactive = today - thread.last_email.date.date() mlist = store.get_list(mlist_fqdn) subject = stripped_subject(mlist, thread.starting_email.subject) # TODO: eventually move to a middleware ? # http://djangosnippets.org/snippets/1865/ is_bot = True user_agent = request.META.get('HTTP_USER_AGENT', None) if user_agent: is_bot = robot_detection.is_robot(user_agent) context = { 'mlist': mlist, 'threadid': threadid, 'subject': subject, 'tags': tags, 'search_form': search_form, 'addtag_form': tag_form, 'month': thread.date_active, 'first_mail': thread.starting_email, 'neighbors': (prev_thread, next_thread), 'months_list': get_months(store, mlist.name), 'days_inactive': days_inactive.days, 'days_old': days_old.days, 'sort_mode': sort_mode, 'fav_action': fav_action, 'reply_form': ReplyForm(), 'is_bot': is_bot, 'participants': thread.participants, } context["participants"].sort(key=lambda x: x[0].lower()) if is_bot: # Don't rely on AJAX to load the replies context["replies"] = _get_thread_replies(request, thread) return render(request, "thread.html", context)
def thread_index(request, mlist_fqdn, threadid, month=None, year=None): ''' Displays all the email for a given thread identifier ''' search_form = SearchForm(auto_id=False) store = get_store(request) thread = store.get_thread(mlist_fqdn, threadid) if not thread: raise Http404 prev_thread, next_thread = store.get_thread_neighbors(mlist_fqdn, threadid) if "sort" in request.GET and request.GET["sort"] == "date": sort_mode = "date" emails = thread.emails else: sort_mode = "thread" emails = thread.emails_by_reply participants = {} for email in emails: # Extract all the votes for this message set_message_votes(email, request.user) # Statistics on how many participants and messages this month participants[email.sender_name] = email.sender_email if sort_mode == "thread": email.level = email.thread_depth - 1 # replies start ragged left if email.level > 5: email.level = 5 from_url = reverse("thread", kwargs={"mlist_fqdn":mlist_fqdn, "threadid":threadid}) # Tags tag_form = AddTagForm(initial={'from_url' : from_url}) try: tags = Tag.objects.filter(threadid=threadid, list_address=mlist_fqdn) except Tag.DoesNotExist: tags = [] # Favorites fav_action = "add" if request.user.is_authenticated(): try: Favorite.objects.get(list_address=mlist_fqdn, threadid=threadid, user=request.user) except Favorite.DoesNotExist: pass else: fav_action = "rm" # Extract relative dates today = datetime.date.today() days_old = today - thread.starting_email.date.date() days_inactive = today - thread.last_email.date.date() mlist = store.get_list(mlist_fqdn) subject = stripped_subject(mlist, thread.starting_email.subject) context = { 'mlist' : mlist, 'threadid' : threadid, 'subject': subject, 'tags' : tags, 'search_form': search_form, 'addtag_form': tag_form, 'month': thread.date_active, 'participants': participants, 'first_mail': thread.starting_email, 'replies': list(emails)[1:], 'neighbors': (prev_thread, next_thread), 'months_list': get_months(store, mlist.name), 'days_inactive': days_inactive.days, 'days_old': days_old.days, 'sort_mode': sort_mode, 'fav_action': fav_action, 'reply_form': ReplyForm(), } return render(request, "thread.html", context)