Exemple #1
0
def new_message(request, mlist_fqdn):
    """ Sends a new thread-starting message to the list.
    TODO: unit tests
    """
    store = get_store(request)
    mlist = store.get_list(mlist_fqdn)
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            _send_email(request, mlist, form.cleaned_data['subject'],
                        form.cleaned_data["message"])
            today = datetime.date.today()
            redirect_url = reverse(
                    'archives_with_month', kwargs={
                        "mlist_fqdn": mlist_fqdn,
                        'year': today.year,
                        'month': today.month})
            redirect_url += "?msg=sent-ok"
            return redirect(redirect_url)
    else:
        form = PostForm()
    context = {
        "mlist": mlist,
        "post_form": form,
        'months_list': get_months(store, mlist.name),
    }
    return render(request, "message_new.html", context)
Exemple #2
0
def index(request, mlist_fqdn, message_id_hash):
    '''
    Displays a single message identified by its message_id_hash (derived from
    message_id)
    '''
    search_form = SearchForm(auto_id=False)
    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)
Exemple #3
0
def index(request, mlist_fqdn, message_id_hash):
    '''
    Displays a single message identified by its message_id_hash (derived from
    message_id)
    '''
    search_form = SearchForm(auto_id=False)
    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)
Exemple #4
0
    """
    store = get_store(request)
    mlist = store.get_list(mlist_fqdn)
    failure = None
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            today = datetime.date.today()
            redirect_url = reverse(
                    'archives_with_month', kwargs={
                        "mlist_fqdn": mlist_fqdn,
                        'year': today.year,
                        'month': today.month})
            redirect_url += "?msg=sent-ok"
            try:
                post_to_list(request, mlist, form.cleaned_data['subject'],
                             form.cleaned_data["message"])
            except PostingFailed, e:
                failure = str(e)
            else:
                return redirect(redirect_url)
    else:
        form = PostForm()
    context = {
        "mlist": mlist,
        "post_form": form,
        "failure": failure,
        'months_list': get_months(store, mlist.name),
    }
    return render(request, "message_new.html", context)
Exemple #5
0
    store = get_store(request)
    mlist = store.get_list(mlist_fqdn)
    failure = None
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            today = datetime.date.today()
            redirect_url = reverse('archives_with_month',
                                   kwargs={
                                       "mlist_fqdn": mlist_fqdn,
                                       'year': today.year,
                                       'month': today.month
                                   })
            redirect_url += "?msg=sent-ok"
            try:
                post_to_list(request, mlist, form.cleaned_data['subject'],
                             form.cleaned_data["message"])
            except PostingFailed, e:
                failure = str(e)
            else:
                return redirect(redirect_url)
    else:
        form = PostForm()
    context = {
        "mlist": mlist,
        "post_form": form,
        "failure": failure,
        'months_list': get_months(store, mlist.name),
    }
    return render(request, "message_new.html", context)
Exemple #6
0
def _thread_list(request, mlist, threads, template_name='thread_list.html', extra_context={}):
    if mlist is None:
        raise Http404("No archived mailing-list by that name.")
    store = get_store(request)
    search_form = SearchForm(auto_id=False)

    participants = set()
    for thread in threads:
        participants.update(thread.participants)

        # Votes
        totalvotes = 0
        totallikes = 0
        totaldislikes = 0
        for message_id_hash in thread.email_id_hashes:
            likes, dislikes, myvote = get_votes(message_id_hash, request.user)
            totallikes = totallikes + likes
            totalvotes = totalvotes + likes + dislikes
            totaldislikes = totaldislikes + dislikes
            if message_id_hash == thread.thread_id:
                # Starting email: same id as the thread_id
                thread.myvote = myvote
        try:
            thread.likes = totallikes / totalvotes
        except ZeroDivisionError:
            thread.likes = 0
        try:
            thread.dislikes = totaldislikes / totalvotes
        except ZeroDivisionError:
            thread.dislikes = 0
        thread.likestatus = "neutral"
        if thread.likes - thread.dislikes >= 10:
            thread.likestatus = "likealot"
        elif thread.likes - thread.dislikes > 0:
            thread.likestatus = "like"
        #elif thread.likes - thread.dislikes < 0:
        #    thread.likestatus = "dislike"

        # Favorites
        thread.favorite = False
        if request.user.is_authenticated():
            try:
                Favorite.objects.get(list_address=mlist.name,
                                     threadid=thread.thread_id,
                                     user=request.user)
            except Favorite.DoesNotExist:
                pass
            else:
                thread.favorite = True

        # Tags
        try:
            thread.tags = Tag.objects.filter(threadid=thread.thread_id,
                                             list_address=mlist.name)
        except Tag.DoesNotExist:
            thread.tags = []

    all_threads = threads
    paginator = Paginator(threads, 10)
    page_num = request.GET.get('page')
    try:
        threads = paginator.page(page_num)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        threads = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        threads = paginator.page(paginator.num_pages)

    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)

    context = {
        'mlist' : mlist,
        'current_page': page_num,
        'search_form': search_form,
        'threads': threads,
        'participants': len(participants),
        'months_list': get_months(store, mlist.name),
        'flash_messages': flash_messages,
    }
    context.update(extra_context)
    return render(request, template_name, context)
Exemple #7
0
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)
Exemple #8
0
def overview(request, mlist_fqdn=None):
    if not mlist_fqdn:
        return redirect('/')
    search_form = SearchForm(auto_id=False)

    # Get stats for last 30 days
    today = datetime.datetime.utcnow()
    # the upper boundary is excluded in the search, add one day
    end_date = today + datetime.timedelta(days=1)
    begin_date = end_date - datetime.timedelta(days=32)

    store = get_store(request)
    mlist = store.get_list(mlist_fqdn)
    threads_result = store.get_threads(list_name=mlist.name, start=begin_date,
        end=end_date)

    threads = []
    Thread = namedtuple('Thread', ["thread_id", "subject", "participants",
                                   "length", "date_active"])
    participants = set()
    for thread_obj in threads_result:
        thread = Thread(thread_obj.thread_id, thread_obj.subject,
                        thread_obj.participants, len(thread_obj),
                        thread_obj.date_active)
        # Statistics on how many participants and threads this month
        participants.update(thread.participants)
        threads.append(thread)

    # top threads are the one with the most answers
    top_threads = sorted(threads, key=lambda t: t.length, reverse=True)

    # active threads are the ones that have the most recent posting
    active_threads = sorted(threads, key=lambda t: t.date_active, reverse=True)

    # top authors are the ones that have the most kudos.  How do we determine
    # that?  Most likes for their post?
    if settings.USE_MOCKUPS:
        authors = generate_top_author()
        authors = sorted(authors, key=lambda author: author.kudos)
        authors.reverse()
    else:
        authors = []

    # List activity
    # Use get_messages and not get_threads to count the emails, because
    # recently active threads include messages from before the start date
    emails_in_month = store.get_messages(list_name=mlist.name,
                                         start=begin_date, end=end_date)
    dates = defaultdict(lambda: 0) # no activity by default
    # populate with all days before adding data.
    for single_date in daterange(begin_date, end_date):
        dates[single_date.strftime("%Y-%m-%d")] = 0

    for email in emails_in_month:
        date_str = email.date.strftime("%Y-%m-%d")
        dates[date_str] = dates[date_str] + 1
    days = dates.keys()
    days.sort()
    evolution = [dates[d] for d in days]
    if not evolution:
        evolution.append(0)
    archives_baseurl = reverse("archives_latest",
                               kwargs={'mlist_fqdn': mlist.name})
    archives_baseurl = archives_baseurl.rpartition("/")[0]

    # threads per category is the top thread titles in each category
    if settings.USE_MOCKUPS:
        threads_per_category = generate_thread_per_category()
    else:
        threads_per_category = {}

    context = {
        'mlist' : mlist,
        'search_form': search_form,
        'top_threads': top_threads[:5],
        'most_active_threads': active_threads[:5],
        'top_author': authors,
        'threads_per_category': threads_per_category,
        'months_list': get_months(store, mlist.name),
        'evolution': evolution,
        'days': days,
        'archives_baseurl': archives_baseurl,
    }
    return render(request, "recent_activities.html", context)
Exemple #9
0
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)
Exemple #10
0
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)
Exemple #11
0
def _thread_list(request,
                 mlist,
                 threads,
                 template_name='thread_list.html',
                 extra_context={}):
    if mlist is None:
        raise Http404("No archived mailing-list by that name.")
    store = get_store(request)
    search_form = SearchForm(auto_id=False)

    participants = set()
    for thread in threads:
        participants.update(thread.participants)

        # Votes
        totalvotes = 0
        totallikes = 0
        totaldislikes = 0
        for message_id_hash in thread.email_id_hashes:
            likes, dislikes, myvote = get_votes(message_id_hash, request.user)
            totallikes = totallikes + likes
            totalvotes = totalvotes + likes + dislikes
            totaldislikes = totaldislikes + dislikes
            if message_id_hash == thread.thread_id:
                # Starting email: same id as the thread_id
                thread.myvote = myvote
        try:
            thread.likes = totallikes / totalvotes
        except ZeroDivisionError:
            thread.likes = 0
        try:
            thread.dislikes = totaldislikes / totalvotes
        except ZeroDivisionError:
            thread.dislikes = 0
        thread.likestatus = "neutral"
        if thread.likes - thread.dislikes >= 10:
            thread.likestatus = "likealot"
        elif thread.likes - thread.dislikes > 0:
            thread.likestatus = "like"
        #elif thread.likes - thread.dislikes < 0:
        #    thread.likestatus = "dislike"

        # Favorites
        thread.favorite = False
        if request.user.is_authenticated():
            try:
                Favorite.objects.get(list_address=mlist.name,
                                     threadid=thread.thread_id,
                                     user=request.user)
            except Favorite.DoesNotExist:
                pass
            else:
                thread.favorite = True

        # Tags
        try:
            thread.tags = Tag.objects.filter(threadid=thread.thread_id,
                                             list_address=mlist.name)
        except Tag.DoesNotExist:
            thread.tags = []

    all_threads = threads
    paginator = Paginator(threads, 10)
    page_num = request.GET.get('page')
    try:
        threads = paginator.page(page_num)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        threads = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        threads = paginator.page(paginator.num_pages)

    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)

    context = {
        'mlist': mlist,
        'current_page': page_num,
        'search_form': search_form,
        'threads': threads,
        'participants': len(participants),
        'months_list': get_months(store, mlist.name),
        'flash_messages': flash_messages,
    }
    context.update(extra_context)
    return render(request, template_name, context)
Exemple #12
0
def overview(request, mlist_fqdn=None):
    if not mlist_fqdn:
        return redirect('/')
    search_form = SearchForm(auto_id=False)

    # Get stats for last 30 days
    today = datetime.datetime.utcnow()
    # the upper boundary is excluded in the search, add one day
    end_date = today + datetime.timedelta(days=1)
    begin_date = end_date - datetime.timedelta(days=32)

    store = get_store(request)
    mlist = store.get_list(mlist_fqdn)
    threads_result = store.get_threads(list_name=mlist.name,
                                       start=begin_date,
                                       end=end_date)

    threads = []
    Thread = namedtuple(
        'Thread',
        ["thread_id", "subject", "participants", "length", "date_active"])
    participants = set()
    for thread_obj in threads_result:
        thread = Thread(thread_obj.thread_id,
                        thread_obj.subject, thread_obj.participants,
                        len(thread_obj), thread_obj.date_active)
        # Statistics on how many participants and threads this month
        participants.update(thread.participants)
        threads.append(thread)

    # top threads are the one with the most answers
    top_threads = sorted(threads, key=lambda t: t.length, reverse=True)

    # active threads are the ones that have the most recent posting
    active_threads = sorted(threads, key=lambda t: t.date_active, reverse=True)

    # top authors are the ones that have the most kudos.  How do we determine
    # that?  Most likes for their post?
    if settings.USE_MOCKUPS:
        authors = generate_top_author()
        authors = sorted(authors, key=lambda author: author.kudos)
        authors.reverse()
    else:
        authors = []

    # List activity
    # Use get_messages and not get_threads to count the emails, because
    # recently active threads include messages from before the start date
    emails_in_month = store.get_messages(list_name=mlist.name,
                                         start=begin_date,
                                         end=end_date)
    dates = defaultdict(lambda: 0)  # no activity by default
    # populate with all days before adding data.
    for single_date in daterange(begin_date, end_date):
        dates[single_date.strftime("%Y-%m-%d")] = 0

    for email in emails_in_month:
        date_str = email.date.strftime("%Y-%m-%d")
        dates[date_str] = dates[date_str] + 1
    days = dates.keys()
    days.sort()
    evolution = [dates[d] for d in days]
    if not evolution:
        evolution.append(0)
    archives_baseurl = reverse("archives_latest",
                               kwargs={'mlist_fqdn': mlist.name})
    archives_baseurl = archives_baseurl.rpartition("/")[0]

    # threads per category is the top thread titles in each category
    if settings.USE_MOCKUPS:
        threads_per_category = generate_thread_per_category()
    else:
        threads_per_category = {}

    context = {
        'mlist': mlist,
        'search_form': search_form,
        'top_threads': top_threads[:5],
        'most_active_threads': active_threads[:5],
        'top_author': authors,
        'threads_per_category': threads_per_category,
        'months_list': get_months(store, mlist.name),
        'evolution': evolution,
        'days': days,
        'archives_baseurl': archives_baseurl,
    }
    return render(request, "recent_activities.html", context)