summaryrefslogtreecommitdiffstats
path: root/views/pages.py
diff options
context:
space:
mode:
Diffstat (limited to 'views/pages.py')
-rw-r--r--views/pages.py238
1 files changed, 238 insertions, 0 deletions
diff --git a/views/pages.py b/views/pages.py
new file mode 100644
index 0000000..cfb13ce
--- /dev/null
+++ b/views/pages.py
@@ -0,0 +1,238 @@
+#-*- coding: utf-8 -*-
+
+from calendar import timegm
+from datetime import datetime, timedelta
+import json
+import logging
+import os
+from urlparse import urljoin
+
+from django import forms
+from django.http import HttpResponse, HttpResponseRedirect
+from django.template import RequestContext, loader
+from django.conf import settings
+import urlgrabber
+
+from mm_app.lib.mockup import generate_thread_per_category, generate_top_author
+
+from lib.notmuch import get_thread_info, get_ro_db
+
+# Move this into settings.py
+ARCHIVE_DIR = '/home/toshio/mm3/mailman/var/archives/hyperkitty/'
+
+MONTH_PARTICIPANTS = 284
+MONTH_DISCUSSIONS = 82
+logger = logging.getLogger(__name__)
+
+
+class SearchForm(forms.Form):
+ keyword = forms.CharField(max_length=100,
+ widget=forms.TextInput(
+ attrs={'placeholder': 'Search this list.'}
+ )
+ )
+
+
+def index(request):
+ t = loader.get_template('index2.html')
+ search_form = SearchForm(auto_id=False)
+ base_url = settings.MAILMAN_API_URL % {
+ 'username': settings.MAILMAN_USER, 'password': settings.MAILMAN_PASS}
+ data = json.load(urlgrabber.urlopen(urljoin(base_url, 'lists')))
+ list_data = sorted(data['entries'], key=lambda elem: (elem['mail_host'], elem['list_name']))
+ c = RequestContext(request, {
+ 'app_name': settings.APP_NAME,
+ 'lists': list_data,
+ 'search_form': search_form['keyword'],
+ })
+ return HttpResponse(t.render(c))
+
+def archives(request, mlist_fqdn, year=None, month=None):
+ # No year/month: past 32 days
+ # year and month: find the 32 days for that month
+ end_date = None
+ if year or month:
+ try:
+ begin_date = datetime(int(year), int(month), 1)
+ end_date = begin_date + timedelta(days=32)
+ month_string = begin_date.strftime('%B %Y')
+ except ValueError, err:
+ logger.error('Wrong format given for the date')
+
+ if not end_date:
+ end_date = datetime.utcnow()
+ begin_date = end_date - timedelta(days=32)
+ month_string = 'Past thirty days'
+ begin_timestamp = timegm(begin_date.timetuple())
+ end_timestamp = timegm(end_date.timetuple())
+
+ list_name = mlist_fqdn.split('@')[0]
+
+ search_form = SearchForm(auto_id=False)
+ t = loader.get_template('month_view2.html')
+
+ try:
+ db = get_ro_db(os.path.join(ARCHIVE_DIR, mlist_fqdn))
+ except IOError:
+ logger.error('No archive for mailing list %s' % mlist_fqdn)
+ return
+
+ msgs = db.create_query('%s..%s' % (begin_timestamp, end_timestamp)).search_messages()
+ participants = set()
+ discussions = set()
+ for msg in msgs:
+ message = json.loads(msg.format_message_as_json())
+ # Statistics on how many participants and threads this month
+ participants.add(message['headers']['From'])
+ discussions.add(msg.get_thread_id())
+
+ # Collect data about each thread
+ threads = []
+ for thread_id in discussions:
+ # Note: can't use tuple() due to a bug in notmuch
+ thread = [thread for thread in db.create_query('thread:%s' % thread_id).search_threads()]
+ if len(thread) != 1:
+ logger.warning('Unknown thread_id %(thread)s from %(mlist)s:'
+ ' %(start)s-%(end)s' % {
+ 'thread': thread_id, 'mlist': mlist_fqdn,
+ 'start': begin_timestamp, 'end': end_timestamp})
+ continue
+ thread = thread[0]
+ thread_info = get_thread_info(thread)
+ threads.append(thread_info)
+
+ # For threads, we need to have threads ordered by
+ # youngest to oldest with the oldest message within thread
+ threads.sort(key=lambda entry: entry.most_recent, reverse=True)
+
+ c = RequestContext(request, {
+ 'app_name': settings.APP_NAME,
+ 'list_name' : list_name,
+ 'list_address': mlist_fqdn,
+ 'search_form': search_form['keyword'],
+ 'month': month_string,
+ 'month_participants': len(participants),
+ 'month_discussions': len(discussions),
+ 'threads': threads,
+ })
+ return HttpResponse(t.render(c))
+
+def recent(request, mlist_fqdn):
+ t = loader.get_template('recent_activities.html')
+ search_form = SearchForm(auto_id=False)
+ list_name = mlist_fqdn.split('@')[0]
+
+ # Get stats for last 30 days
+ end_date = datetime.utcnow()
+ begin_date = end_date - timedelta(days=32)
+ begin_timestamp = timegm(begin_date.timetuple())
+ end_timestamp = timegm(end_date.timetuple())
+
+ try:
+ db = get_ro_db(os.path.join(ARCHIVE_DIR, mlist_fqdn))
+ except IOError:
+ logger.error('No archive for mailing list %s' % mlist_fqdn)
+ return
+
+ msgs = db.create_query('%s..%s' % (begin_timestamp, end_timestamp)).search_messages()
+ participants = set()
+ discussions = set()
+ for msg in msgs:
+ message = json.loads(msg.format_message_as_json())
+ # Statistics on how many participants and threads this month
+ participants.add(message['headers']['From'])
+ discussions.add(msg.get_thread_id())
+
+ thread_query = db.create_query('%s..%s' % (begin_timestamp, end_timestamp)).search_threads()
+ top_threads = []
+ for thread in thread_query:
+ thread_info = get_thread_info(thread)
+ top_threads.append(thread_info)
+ # top threads are the ones with the most posts
+ top_threads.sort(key=lambda entry: len(entry.answers), reverse=True)
+
+ # active threads are the ones that have the most recent posting
+ active_threads = sorted(top_threads, key=lambda entry: entry.most_recent, reverse=True)
+
+ # top authors are the ones that have the most kudos. How do we determine
+ # that? Most likes for their post?
+ authors = generate_top_author()
+ authors = sorted(authors, key=lambda author: author.kudos)
+ authors.reverse()
+
+ # threads per category is the top thread titles in each category
+ threads_per_category = generate_thread_per_category()
+ c = RequestContext(request, {
+ 'app_name': settings.APP_NAME,
+ 'list_name' : list_name,
+ 'list_address': mlist_fqdn,
+ 'search_form': search_form['keyword'],
+ 'month': 'Recent activity',
+ 'month_participants': len(participants),
+ 'month_discussions': len(discussions),
+ 'top_threads': top_threads,
+ 'most_active_threads': active_threads,
+ 'top_author': authors,
+ 'threads_per_category': threads_per_category,
+ })
+ return HttpResponse(t.render(c))
+
+def _search_results_page(request, mlist_fqdn, query_string, search_type):
+ search_form = SearchForm(auto_id=False)
+ t = loader.get_template('search2.html')
+
+ list_name = mlist_fqdn.split('@')[0]
+
+ try:
+ db = get_ro_db(os.path.join(ARCHIVE_DIR, mlist_fqdn))
+ except IOError:
+ logger.error('No archive for mailing list %s' % mlist_fqdn)
+ return
+
+ # Note, can't use tuple() because of a bug in notmuch
+ # Collect data about each thread
+ threads = []
+ participants = set()
+ if query_string:
+ for thread in db.create_query(query_string).search_threads():
+ thread_info = get_thread_info(thread)
+ participants.update(thread_info.participants)
+ threads.append(thread_info)
+
+ threads.sort(key=lambda entry: entry.most_recent, reverse=True)
+
+ c = RequestContext(request, {
+ 'app_name': settings.APP_NAME,
+ 'list_name' : list_name,
+ 'list_address': mlist_fqdn,
+ 'search_form': search_form['keyword'],
+ 'month': search_type,
+ 'month_participants': len(participants),
+ 'month_discussions': len(threads),
+ 'threads': threads,
+ })
+ return HttpResponse(t.render(c))
+
+
+def search(request, mlist_fqdn):
+ keyword = request.GET.get('keyword')
+ if keyword:
+ url = '/2/search/%s/%s' % (mlist_fqdn, keyword)
+ else:
+ url = '/2/search/%s' % (mlist_fqdn,)
+ return HttpResponseRedirect(url)
+
+
+def search_keyword(request, mlist_fqdn, keyword=None):
+ if not keyword:
+ keyword = request.GET.get('keyword')
+ return _search_results_page(request, mlist_fqdn, keyword, 'Search')
+
+
+def search_tag(request, mlist_fqdn, tag=None):
+ '''Searches both tag and topic'''
+ if tag:
+ query_string = 'tag:%(tag)s or tag:=topic=%(tag)s' % {'tag': tag}
+ else:
+ query_string = None
+ return _search_results_page(request, mlist_fqdn, query_string, 'Tag search')