From 156aa73a85a79c34c6e013862bbce59a49d0d15b Mon Sep 17 00:00:00 2001 From: Sergio Oliveira Date: Fri, 12 Jul 2013 18:40:48 -0300 Subject: [PATCH] Moving stuff around --- colab/api/__init__.py | 0 colab/api/handlers.py | 103 ------------------------------------------------------------------------------------------------------- colab/api/urls.py | 16 ---------------- colab/rss/__init__.py | 0 colab/rss/feeds.py | 78 ------------------------------------------------------------------------------ colab/rss/urls.py | 9 --------- colab/super_archives/__init__.py | 0 colab/super_archives/admin.py | 54 ------------------------------------------------------ colab/super_archives/fixtures/initial_data.json | 10 ---------- colab/super_archives/forms.py | 66 ------------------------------------------------------------------ colab/super_archives/management/__init__.py | 0 colab/super_archives/management/commands/__init__.py | 0 colab/super_archives/management/commands/import_emails.py | 258 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ colab/super_archives/management/commands/message.py | 101 ----------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0001_initial.py | 255 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py | 133 ------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0003_auto__add_field_thread_score.py | 134 -------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0004_auto__add_field_vote_created.py | 135 --------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py | 143 ----------------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0006_auto.py | 143 ----------------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0007_auto.py | 137 ----------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0008_add_mailinglist_name_to_url.py | 142 ---------------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py | 136 ---------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py | 136 ---------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/migrations/__init__.py | 0 colab/super_archives/models.py | 279 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- colab/super_archives/queries.py | 54 ------------------------------------------------------ colab/super_archives/templates/message-list.html | 68 -------------------------------------------------------------------- colab/super_archives/templates/message-preview.html | 51 --------------------------------------------------- colab/super_archives/templates/message-thread.html | 77 ----------------------------------------------------------------------------- colab/super_archives/templatetags/__init__.py | 0 colab/super_archives/templatetags/append_to_get.py | 56 -------------------------------------------------------- colab/super_archives/templatetags/form_field.py | 64 ---------------------------------------------------------------- colab/super_archives/tests.py | 16 ---------------- colab/super_archives/urls.py | 9 --------- colab/super_archives/validators.py | 15 --------------- colab/super_archives/views.py | 80 -------------------------------------------------------------------------------- src/api/__init__.py | 0 src/api/handlers.py | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/api/urls.py | 16 ++++++++++++++++ src/rss/__init__.py | 0 src/rss/feeds.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rss/urls.py | 9 +++++++++ src/super_archives/__init__.py | 0 src/super_archives/admin.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/fixtures/initial_data.json | 10 ++++++++++ src/super_archives/forms.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/management/__init__.py | 0 src/super_archives/management/commands/__init__.py | 0 src/super_archives/management/commands/import_emails.py | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/management/commands/message.py | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0001_initial.py | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0003_auto__add_field_thread_score.py | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0004_auto__add_field_vote_created.py | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0006_auto.py | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0007_auto.py | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0008_add_mailinglist_name_to_url.py | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0009_auto__del_field_message_mailinglist.py | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/migrations/__init__.py | 0 src/super_archives/models.py | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/queries.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/templates/message-list.html | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/templates/message-preview.html | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/templates/message-thread.html | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/templatetags/__init__.py | 0 src/super_archives/templatetags/append_to_get.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/templatetags/form_field.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/super_archives/tests.py | 16 ++++++++++++++++ src/super_archives/urls.py | 9 +++++++++ src/super_archives/validators.py | 15 +++++++++++++++ src/super_archives/views.py | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 74 files changed, 2958 insertions(+), 2958 deletions(-) delete mode 100644 colab/api/__init__.py delete mode 100644 colab/api/handlers.py delete mode 100644 colab/api/urls.py delete mode 100644 colab/rss/__init__.py delete mode 100644 colab/rss/feeds.py delete mode 100644 colab/rss/urls.py delete mode 100644 colab/super_archives/__init__.py delete mode 100644 colab/super_archives/admin.py delete mode 100644 colab/super_archives/fixtures/initial_data.json delete mode 100644 colab/super_archives/forms.py delete mode 100644 colab/super_archives/management/__init__.py delete mode 100644 colab/super_archives/management/commands/__init__.py delete mode 100644 colab/super_archives/management/commands/import_emails.py delete mode 100644 colab/super_archives/management/commands/message.py delete mode 100644 colab/super_archives/migrations/0001_initial.py delete mode 100644 colab/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py delete mode 100644 colab/super_archives/migrations/0003_auto__add_field_thread_score.py delete mode 100644 colab/super_archives/migrations/0004_auto__add_field_vote_created.py delete mode 100644 colab/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py delete mode 100644 colab/super_archives/migrations/0006_auto.py delete mode 100644 colab/super_archives/migrations/0007_auto.py delete mode 100644 colab/super_archives/migrations/0008_add_mailinglist_name_to_url.py delete mode 100644 colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py delete mode 100644 colab/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py delete mode 100644 colab/super_archives/migrations/__init__.py delete mode 100644 colab/super_archives/models.py delete mode 100644 colab/super_archives/queries.py delete mode 100644 colab/super_archives/templates/message-list.html delete mode 100644 colab/super_archives/templates/message-preview.html delete mode 100644 colab/super_archives/templates/message-thread.html delete mode 100644 colab/super_archives/templatetags/__init__.py delete mode 100644 colab/super_archives/templatetags/append_to_get.py delete mode 100644 colab/super_archives/templatetags/form_field.py delete mode 100644 colab/super_archives/tests.py delete mode 100644 colab/super_archives/urls.py delete mode 100644 colab/super_archives/validators.py delete mode 100644 colab/super_archives/views.py create mode 100644 src/api/__init__.py create mode 100644 src/api/handlers.py create mode 100644 src/api/urls.py create mode 100644 src/rss/__init__.py create mode 100644 src/rss/feeds.py create mode 100644 src/rss/urls.py create mode 100644 src/super_archives/__init__.py create mode 100644 src/super_archives/admin.py create mode 100644 src/super_archives/fixtures/initial_data.json create mode 100644 src/super_archives/forms.py create mode 100644 src/super_archives/management/__init__.py create mode 100644 src/super_archives/management/commands/__init__.py create mode 100644 src/super_archives/management/commands/import_emails.py create mode 100644 src/super_archives/management/commands/message.py create mode 100644 src/super_archives/migrations/0001_initial.py create mode 100644 src/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py create mode 100644 src/super_archives/migrations/0003_auto__add_field_thread_score.py create mode 100644 src/super_archives/migrations/0004_auto__add_field_vote_created.py create mode 100644 src/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py create mode 100644 src/super_archives/migrations/0006_auto.py create mode 100644 src/super_archives/migrations/0007_auto.py create mode 100644 src/super_archives/migrations/0008_add_mailinglist_name_to_url.py create mode 100644 src/super_archives/migrations/0009_auto__del_field_message_mailinglist.py create mode 100644 src/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py create mode 100644 src/super_archives/migrations/__init__.py create mode 100644 src/super_archives/models.py create mode 100644 src/super_archives/queries.py create mode 100644 src/super_archives/templates/message-list.html create mode 100644 src/super_archives/templates/message-preview.html create mode 100644 src/super_archives/templates/message-thread.html create mode 100644 src/super_archives/templatetags/__init__.py create mode 100644 src/super_archives/templatetags/append_to_get.py create mode 100644 src/super_archives/templatetags/form_field.py create mode 100644 src/super_archives/tests.py create mode 100644 src/super_archives/urls.py create mode 100644 src/super_archives/validators.py create mode 100644 src/super_archives/views.py diff --git a/colab/api/__init__.py b/colab/api/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/api/__init__.py +++ /dev/null diff --git a/colab/api/handlers.py b/colab/api/handlers.py deleted file mode 100644 index a1a02c4..0000000 --- a/colab/api/handlers.py +++ /dev/null @@ -1,103 +0,0 @@ - -from django.core.cache import cache -from django.db import IntegrityError -from django.core.exceptions import ObjectDoesNotExist -from django.contrib.auth.decorators import login_required - -from piston.utils import rc -from piston.handler import BaseHandler - -from colab import solrutils -from colab.super_archives.models import Message, PageHit - - -class VoteHandler(BaseHandler): - allowed_methods = ('GET', 'POST', 'DELETE') - - def create(self, request, message_id): - if not request.user.is_authenticated(): - return rc.FORBIDDEN - - try: - Message.objects.get(id=message_id).vote(request.user) - except IntegrityError: - return rc.DUPLICATE_ENTRY - - return rc.CREATED - - def read(self, request, message_id): - return Message.objects.get(id=message_id).votes_count() - - def delete(self, request, message_id): - if not request.user.is_authenticated(): - return rc.FORBIDDEN - - try: - Message.objects.get(id=message_id).unvote(request.user) - except ObjectDoesNotExist: - return rc.NOT_HERE - - return rc.DELETED - - -class CountHandler(BaseHandler): - allowed_methods = ('POST') - - def create(self, request): - """Add one page view for the given url""" - - # If missing the path_info argument we can't do anything - path_info = request.POST.get('path_info') - if not path_info: - return rc.BAD_REQUEST - - # Here we cache the user's IP to ensure that the same - # IP won't hit the same page again for while - ip_addr = request.META.get('REMOTE_ADDR') - page_hits_cache = cache.get('page_hits', {}) - duplicate = page_hits_cache.get(path_info, {}).get(ip_addr) - - if duplicate: - return rc.DUPLICATE_ENTRY - else: - page_hits_cache.update({path_info: {ip_addr: True }}) - cache.set('page_hits', page_hits_cache) - - # Everything ok, so just increment the page count - page_hit = PageHit.objects.get_or_create(url_path=path_info)[0] - page_hit.hit_count += 1 - page_hit.save() - - return rc.CREATED - -class SearchHandler(BaseHandler): - allowed_methods = ('GET', ) - - def read(self, request): - query = request.GET.get('q') - page = request.GET.get('p', 1) - results_per_page = request.GET.get('n', 50) - order = request.GET.get('o') - - if not query: - return 'Query cannot be empty.' - else: - query = query.encode('utf-8') - - try: - n = int(results_per_page) - except ValueError: - n = 10 - - if 1 > n > 500: - n = 1 - - try: - page = int(page) - except ValueError: - page = 1 - - if page < 1: - page = 1 - - return solrutils.select(query, results_per_page, page, order) diff --git a/colab/api/urls.py b/colab/api/urls.py deleted file mode 100644 index f89db6c..0000000 --- a/colab/api/urls.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.conf.urls.defaults import patterns, include, url - -from piston.resource import Resource - -from colab.api.handlers import VoteHandler, CountHandler, SearchHandler - - -vote_handler = Resource(VoteHandler) -count_handler = Resource(CountHandler) -search_handler = Resource(SearchHandler) - -urlpatterns = patterns('', - url(r'message/(?P\d+)/vote$', vote_handler), - url(r'hit/$', count_handler), - url(r'search/$', search_handler), -) diff --git a/colab/rss/__init__.py b/colab/rss/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/rss/__init__.py +++ /dev/null diff --git a/colab/rss/feeds.py b/colab/rss/feeds.py deleted file mode 100644 index 36ba6d5..0000000 --- a/colab/rss/feeds.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from django.contrib.syndication.views import Feed -from django.utils.translation import ugettext as _ - -from colab.super_archives.models import Thread -from colab.super_archives import queries -from colab import solrutils - -class LatestThreadsFeeds(Feed): - title = _(u'Latest Discussions') - link = '/rss/threads/latest/' - - def items(self): - return queries.get_latest_threads()[:20] - - def item_link(self, item): - return item.latest_message.url - - def item_title(self, item): - title = '[' + item.mailinglist.name + '] ' - title += item.latest_message.subject_clean - return title - - def item_description(self, item): - return item.latest_message.body - - -class HottestThreadsFeeds(Feed): - title = _(u'Discussions Most Relevance') - link = '/rss/threads/hottest/' - - def items(self): - return queries.get_hottest_threads()[:20] - - def item_link(self, item): - return item.latest_message.url - - def item_title(self, item): - title = '[' + item.mailinglist.name + '] ' - title += item.latest_message.subject_clean - return title - - def item_description(self, item): - return item.latest_message.body - - -class LatestColabFeeds(Feed): - title = _(u'Latest collaborations') - link = '/rss/colab/latest/' - - def items(self): - items = solrutils.get_latest_collaborations(20) - return items - - def item_title(self, item): - type_ = item.get('Type') + ': ' - mailinglist = item.get('mailinglist') - - if mailinglist: - prefix = type_ + mailinglist + ' - ' - else: - prefix = type_ - - return prefix + item.get('Title') - - def item_description(self, item): - return item.get('Description') - - def item_link(self, item): - if item.get('Type') != 'thread': - url = item.get('url') - else: - url = 'http://colab.interlegis.leg.br' - url += item.get('url') - return url - diff --git a/colab/rss/urls.py b/colab/rss/urls.py deleted file mode 100644 index c995183..0000000 --- a/colab/rss/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.conf.urls.defaults import patterns, url -import feeds - -urlpatterns = patterns('', - url(r'threads/latest/$', feeds.LatestThreadsFeeds(), name='rss_latest_threads'), - url(r'colab/latest/$', feeds.LatestColabFeeds(), name='rss_latest_colab'), - url(r'threads/hottest/$', feeds.HottestThreadsFeeds(), name='rss_hottest_threads'), -) - diff --git a/colab/super_archives/__init__.py b/colab/super_archives/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/super_archives/__init__.py +++ /dev/null diff --git a/colab/super_archives/admin.py b/colab/super_archives/admin.py deleted file mode 100644 index 12d9c15..0000000 --- a/colab/super_archives/admin.py +++ /dev/null @@ -1,54 +0,0 @@ - -from django.contrib import admin -from colab.super_archives.models import Message, Thread, UserProfile - -class MessageAdmin(admin.ModelAdmin): - list_filter = ('spam', 'thread__mailinglist', 'received_time', ) - search_fields = ( - 'id', - 'subject', - 'subject_clean', - 'body', - 'from_address__real_name', - 'from_address__address', - 'from_address__user__first_name', - 'from_address__user__last_name', - 'from_address__user__username', - ) - readonly_fields = ('thread', 'from_address', 'mailinglist') - - -class ThreadAdmin(admin.ModelAdmin): - list_filter = ('spam', 'mailinglist', 'message__received_time',) - search_fields = ( - 'id', - 'subject_token', - 'message__subject', - 'message__subject_clean', - 'message__from_address__real_name', - 'message__from_address__address', - 'message__from_address__user__first_name', - 'message__from_address__user__last_name', - 'message__from_address__user__username', - ) - - readonly_fields = ( - 'mailinglist', - 'subject_token', - 'latest_message', - 'score', - ) - - fields = ( - 'mailinglist', - 'subject_token', - 'latest_message', - 'score', - 'spam', - ) - - -admin.site.register(UserProfile) -admin.site.register(Thread, ThreadAdmin) -admin.site.register(Message, MessageAdmin) - diff --git a/colab/super_archives/fixtures/initial_data.json b/colab/super_archives/fixtures/initial_data.json deleted file mode 100644 index 42c25fb..0000000 --- a/colab/super_archives/fixtures/initial_data.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "pk": 1, - "model": "auth.group", - "fields": { - "name": "developer", - "permissions": [] - } - } -] diff --git a/colab/super_archives/forms.py b/colab/super_archives/forms.py deleted file mode 100644 index d061cda..0000000 --- a/colab/super_archives/forms.py +++ /dev/null @@ -1,66 +0,0 @@ -# -*- coding: utf-8 -*- - -from django import forms -from django.core.exceptions import ValidationError -from django.contrib.auth.models import User -from django.contrib.auth.forms import UserCreationForm as UserCreationForm_ -from django.utils.translation import ugettext_lazy as _ - -from colab.super_archives.models import MailingList -from colab.super_archives.validators import UniqueValidator - -# XXX: I know that this code does not look nice AT ALL. -# probably it should be implemented using formsets instead of -# the hack below. Feel free to improve it! :) - -# User fields -username_field = UserCreationForm_().fields.get(u'username') -first_name_field = forms.CharField(max_length=30, label=_(u'Name')) -last_name_field = forms.CharField(max_length=30, label=_(u'Last name')) -email_field = forms.EmailField(validators=[UniqueValidator(User, 'email')]) - -# UserProfile fields -institution_field = forms.CharField(max_length=120, label=_(u'Institution'), - required=False) -role_field = forms.CharField(max_length=60, label=_(u'Function'), required=False) -twitter_field = forms.URLField(label=_(u'Twitter'), required=False) -facebook_field = forms.URLField(label=_(u'Facebook'), required=False) -google_talk_field = forms.EmailField(label=_(u'Google Talk'), required=False) -webpage_field = forms.URLField(label=_(u'Personal Website/Blog'), required=False) - -all_lists = MailingList.objects.all() -lists_names = [] -for list_ in all_lists: - choice = (list_.name, list_.name) - lists_names.append(choice) - -lists_field = forms.MultipleChoiceField( - label=u'Listas', - required=False, - widget=forms.CheckboxSelectMultiple, - choices=lists_names -) - - -class UserCreationForm(UserCreationForm_): - first_name = first_name_field - last_name = last_name_field - email = email_field - institution = institution_field - role = role_field - twitter = twitter_field - facebook = facebook_field - google_talk = google_talk_field - webpage = webpage_field - lists = lists_field - - -class UserUpdateForm(forms.Form): - username = username_field - username.required = False - institution = institution_field - role = role_field - twitter = twitter_field - facebook = facebook_field - google_talk = google_talk_field - webpage = webpage_field diff --git a/colab/super_archives/management/__init__.py b/colab/super_archives/management/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/super_archives/management/__init__.py +++ /dev/null diff --git a/colab/super_archives/management/commands/__init__.py b/colab/super_archives/management/commands/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/super_archives/management/commands/__init__.py +++ /dev/null diff --git a/colab/super_archives/management/commands/import_emails.py b/colab/super_archives/management/commands/import_emails.py deleted file mode 100644 index cfffb5a..0000000 --- a/colab/super_archives/management/commands/import_emails.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -"""Import emails from a mailman storage to the django database.""" - -import os -import re -import sys -import mailbox -from optparse import make_option - -from django.db import transaction -from django.template.defaultfilters import slugify -from django.core.management.base import BaseCommand, CommandError - -from colab.super_archives.models import MailingList, Message, \ - Thread, EmailAddress -from colab.super_archives.management.commands.message import Message as \ - CustomMessage - - -class Command(BaseCommand, object): - """Get emails from mailman archives and import them in the django db. """ - - help = __doc__ - - default_archives_path = '/var/lib/mailman/archives/private' - RE_SUBJECT_CLEAN = re.compile('((re|res|fw|fwd|en|enc):)|\[.*?\]', - re.IGNORECASE) - THREAD_CACHE = {} - EMAIL_ADDR_CACHE = {} - - # A new command line option to get the dump file to parse. - option_list = BaseCommand.option_list + ( - make_option('--archives_path', - dest='archives_path', - help='Path of email archives to be imported. (default: %s)' % - default_archives_path, - default=default_archives_path), - - make_option('--exclude-list', - dest='exclude_lists', - help=("Mailing list that won't be imported. It can be used many" - "times for more than one list."), - action='append', - default=None), - - make_option('--all', - dest='all', - help='Import all messages (default: False)', - action="store_true", - default=False), - ) - - def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) - - def log(self, msg, error=False): - """Log message helper.""" - output = self.stdout - if error: - output = self.stderr - - output.write(msg) - output.write('\n') - - def parse_emails(self, email_filename, index=0): - """Generator function that parse and extract emails from the file - `email_filename` starting from the position `index`. - - Yield: An instance of `mailbox.mboxMessage` for each email in the - file. - - """ - self.log("Parsing email dump: %s." % email_filename) - mbox = mailbox.mbox(email_filename, factory=CustomMessage) - - # Get each email from mbox file - # - # The following implementation was used because the object - # mbox does not support slicing. Converting the object to a - # tuple (as represented in the code down here) was a valid - # option but its performance was too poor. - # - #for message in tuple(mbox)[index:]: - # yield message - # - key = index - while mbox.has_key(key): - key += 1 - yield key-1, mbox[key-1] - - def get_emails(self, mailinglist_dir, all, exclude_lists): - """Generator function that get the emails from each mailing - list dump dirctory. If `all` is set to True all the emails in the - mbox will be imported if not it will just resume from the last - message previously imported. The lists set in `exclude_lists` - won't be imported. - - Yield: A tuple in the form: (mailing list name, email message). - - """ - self.log("Getting emails dumps from: %s" % mailinglist_dir) - - # Get the list of directories ending with .mbox - mailing_lists_mboxes = (mbox for mbox in os.listdir(mailinglist_dir) - if mbox.endswith('.mbox')) - - # Get messages from each mbox - for mbox in mailing_lists_mboxes: - mbox_path = os.path.join(mailinglist_dir, mbox, mbox) - mailinglist_name = mbox.split('.')[0] - - # Check if the mailinglist is set not to be imported - if exclude_lists and mailinglist_name in exclude_lists: - continue - - # Find the index of the last imported message - if all: - n_msgs = 0 - else: - try: - mailinglist = MailingList.objects.get( - name=mailinglist_name) - n_msgs = mailinglist.last_imported_index - except MailingList.DoesNotExist: - n_msgs = 0 - - for index, msg in self.parse_emails(mbox_path, n_msgs): - yield mailinglist_name, msg, index - - def get_thread(self, email, mailinglist): - """Group messages by thread looking for similar subjects""" - - subject_slug = slugify(email.subject_clean) - thread = self.THREAD_CACHE.get(subject_slug, {}).get(mailinglist.id) - if thread is None: - thread = Thread.objects.get_or_create( - mailinglist=mailinglist, - subject_token=subject_slug - )[0] - - if self.THREAD_CACHE.get(subject_slug) is None: - self.THREAD_CACHE[subject_slug] = dict() - self.THREAD_CACHE[subject_slug][mailinglist.id] = thread - - thread.latest_message = email - thread.save() - return thread - - def save_email(self, list_name, email_msg, index): - """Save email message into the database.""" - - # Update last imported message into the DB - mailinglist, created = MailingList.objects.get_or_create(name=list_name) - mailinglist.last_imported_index = index - - if created: - # if the mailinglist is newly created it's sure that the message - # is not in the DB yet. - self.create_email(mailinglist, email_msg) - - else: - # If the message is already at the database don't do anything - try: - messages = Message.objects.get( - message_id=email_msg.get('Message-ID'), - thread__mailinglist=mailinglist - ) - - except Message.DoesNotExist: - self.create_email(mailinglist, email_msg) - - mailinglist.save() - - def create_email(self, mailinglist, email_msg): - - real_name, from_ = email_msg.get_from_addr() - - email_addr = self.EMAIL_ADDR_CACHE.get(from_) - if email_addr is None: - email_addr = EmailAddress.objects.get_or_create( - address=from_)[0] - self.EMAIL_ADDR_CACHE[from_] = email_addr - - if not email_addr.real_name and real_name: - email_addr.real_name = real_name[:64] - email_addr.save() - - subject = email_msg.get_subject() - - email = Message.objects.create( - message_id=email_msg.get('Message-ID'), - from_address=email_addr, - subject=subject, - subject_clean=self.RE_SUBJECT_CLEAN.sub('', subject).strip(), - body=email_msg.get_body(), - received_time=email_msg.get_received_datetime(), - ) - email.thread = self.get_thread(email, mailinglist) - email.save() - - @transaction.commit_manually - def import_emails(self, archives_path, all, exclude_lists=None): - """Get emails from the filesystem from the `archives_path` - and store them into the database. If `all` is set to True all - the filesystem storage will be imported otherwise the - importation will resume from the last message previously - imported. The lists set in `exclude_lists` won't be imported. - - """ - - count = 0 - email_generator = self.get_emails(archives_path, all, exclude_lists) - for mailinglist_name, msg, index in email_generator: - try: - self.save_email(mailinglist_name, msg, index) - except: - # This anti-pattern is needed to avoid the transations to - # get stuck in case of errors. - transaction.rollback() - raise - - count += 1 - if count % 1000 == 0: - transaction.commit() - - transaction.commit() - - def handle(self, *args, **options): - """Main command method.""" - - lock_file = '/var/lock/colab/import_emails.lock' - - # Already running, so quit - if os.path.exists(lock_file): - self.log(("This script is already running. (If your are sure it's " - "not please delete the lock file in %s')") % lock_file) - sys.exit(0) - - if not os.path.exists(os.path.dirname(lock_file)): - os.mkdir(os.path.dirname(lock_file), 0755) - - run_lock = file(lock_file, 'w') - run_lock.close() - - archives_path = options.get('archives_path') - self.log('Using archives_path `%s`' % self.default_archives_path) - - if not os.path.exists(archives_path): - raise CommandError('archives_path (%s) does not exist' % - archives_path) - - self.import_emails(archives_path, - options.get('all'), options.get('exclude_lists')) - - os.remove(lock_file) - diff --git a/colab/super_archives/management/commands/message.py b/colab/super_archives/management/commands/message.py deleted file mode 100644 index dc3b48a..0000000 --- a/colab/super_archives/management/commands/message.py +++ /dev/null @@ -1,101 +0,0 @@ - -import re -import pytz -import email -import codecs -import mailbox -import datetime -from email.iterators import typed_subpart_iterator - -import chardet - - -def get_charset(message, default='ASCII'): - """Get the message charset""" - - charset = message.get_content_charset() - - if not charset: - charset = message.get_charset() - - if not charset: - charset = default - - try: - codecs.lookup(charset) - except LookupError: - charset = default - - return charset - - -class Message(mailbox.mboxMessage): - - RECEIVED_DELIMITER = re.compile('\n|;') - - def get_subject(self): - subject = email.header.decode_header(self['Subject']) - - if isinstance(subject, list): - new_subject = u'' - for text_part, encoding in subject: - if not encoding: - encoding = get_charset(self) - - try: - new_subject += unicode(text_part, encoding) - except (UnicodeDecodeError, LookupError): - try: - new_subject += unicode(text_part, get_charset(self)) - except (UnicodeDecodeError, LookupError): - encoding = chardet.detect(text_part)['encoding'] - new_subject += unicode(text_part, encoding) - - return ''.join(new_subject) - - def get_body(self): - """Get the body of the email message""" - - if self.is_multipart(): - #get the plain text version only - text_parts = [part - for part in typed_subpart_iterator(self, - 'text', - 'plain')] - body = [] - for part in text_parts: - charset = get_charset(part, get_charset(self)) - body.append(unicode(part.get_payload(decode=True), - charset, - "replace")) - - return u"\n".join(body).strip() - - else: # if it is not multipart, the payload will be a string - # representing the message body - body = unicode(self.get_payload(decode=True), - get_charset(self), - "replace") - return body.strip() - - def get_received_datetime(self): - # The time received should always be the last element - # in the `Received` attribute from the message headers - received_header = self.RECEIVED_DELIMITER.split(self['Received']) - received_time_header = received_header[-1].strip() - - date_tuple = email.utils.parsedate_tz(received_time_header) - utc_timestamp = email.utils.mktime_tz(date_tuple) - utc_datetime = datetime.datetime.fromtimestamp(utc_timestamp, - pytz.utc) - - return utc_datetime - - def get_from_addr(self): - real_name_raw, from_ = email.utils.parseaddr(self['From']) - real_name_str, encoding = email.header.decode_header(real_name_raw)[0] - if not encoding: - encoding = 'ascii' - - real_name = unicode(real_name_str, encoding, errors='replace') - return real_name, from_ diff --git a/colab/super_archives/migrations/0001_initial.py b/colab/super_archives/migrations/0001_initial.py deleted file mode 100644 index cbf3c99..0000000 --- a/colab/super_archives/migrations/0001_initial.py +++ /dev/null @@ -1,255 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding model 'PageHit' - db.create_table('super_archives_pagehit', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('url_path', self.gf('django.db.models.fields.CharField')(unique=True, max_length=2048, db_index=True)), - ('hit_count', self.gf('django.db.models.fields.IntegerField')(default=0)), - )) - db.send_create_signal('super_archives', ['PageHit']) - - # Adding model 'EmailAddress' - db.create_table('super_archives_emailaddress', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='emails', null=True, to=orm['auth.User'])), - ('address', self.gf('django.db.models.fields.EmailField')(unique=True, max_length=75)), - ('real_name', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)), - ('md5', self.gf('django.db.models.fields.CharField')(max_length=32, null=True)), - )) - db.send_create_signal('super_archives', ['EmailAddress']) - - # Adding model 'UserProfile' - db.create_table('super_archives_userprofile', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)), - ('institution', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), - ('role', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), - ('twitter', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), - ('facebook', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), - ('google_talk', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True)), - ('webpage', self.gf('django.db.models.fields.CharField')(max_length=256)), - )) - db.send_create_signal('super_archives', ['UserProfile']) - - # Adding model 'MailingList' - db.create_table('super_archives_mailinglist', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=80)), - ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)), - ('description', self.gf('django.db.models.fields.TextField')()), - ('logo', self.gf('django.db.models.fields.files.FileField')(max_length=100)), - ('last_imported_index', self.gf('django.db.models.fields.IntegerField')(default=0)), - )) - db.send_create_signal('super_archives', ['MailingList']) - - # Adding model 'MailingListMembership' - db.create_table('super_archives_mailinglistmembership', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), - ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), - )) - db.send_create_signal('super_archives', ['MailingListMembership']) - - # Adding model 'Thread' - db.create_table('super_archives_thread', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('subject_token', self.gf('django.db.models.fields.CharField')(max_length=512)), - ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), - ('latest_message', self.gf('django.db.models.fields.related.OneToOneField')(related_name='+', unique=True, null=True, to=orm['super_archives.Message'])), - )) - db.send_create_signal('super_archives', ['Thread']) - - # Adding unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] - db.create_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) - - # Adding model 'Vote' - db.create_table('super_archives_vote', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), - ('message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), - )) - db.send_create_signal('super_archives', ['Vote']) - - # Adding unique constraint on 'Vote', fields ['user', 'message'] - db.create_unique('super_archives_vote', ['user_id', 'message_id']) - - # Adding model 'Message' - db.create_table('super_archives_message', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('from_address', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.EmailAddress'])), - ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), - ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Thread'], null=True)), - ('subject', self.gf('django.db.models.fields.CharField')(max_length=512)), - ('subject_clean', self.gf('django.db.models.fields.CharField')(max_length=512)), - ('body', self.gf('django.db.models.fields.TextField')(default='')), - ('received_time', self.gf('django.db.models.fields.DateTimeField')()), - ('message_id', self.gf('django.db.models.fields.CharField')(max_length=512)), - )) - db.send_create_signal('super_archives', ['Message']) - - # Adding model 'MessageMetadata' - db.create_table('super_archives_messagemetadata', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('Message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), - ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), - ('value', self.gf('django.db.models.fields.TextField')()), - )) - db.send_create_signal('super_archives', ['MessageMetadata']) - - - def backwards(self, orm): - - # Removing unique constraint on 'Vote', fields ['user', 'message'] - db.delete_unique('super_archives_vote', ['user_id', 'message_id']) - - # Removing unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] - db.delete_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) - - # Deleting model 'PageHit' - db.delete_table('super_archives_pagehit') - - # Deleting model 'EmailAddress' - db.delete_table('super_archives_emailaddress') - - # Deleting model 'UserProfile' - db.delete_table('super_archives_userprofile') - - # Deleting model 'MailingList' - db.delete_table('super_archives_mailinglist') - - # Deleting model 'MailingListMembership' - db.delete_table('super_archives_mailinglistmembership') - - # Deleting model 'Thread' - db.delete_table('super_archives_thread') - - # Deleting model 'Vote' - db.delete_table('super_archives_vote') - - # Deleting model 'Message' - db.delete_table('super_archives_message') - - # Deleting model 'MessageMetadata' - db.delete_table('super_archives_messagemetadata') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py b/colab/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py deleted file mode 100644 index a47db14..0000000 --- a/colab/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py +++ /dev/null @@ -1,133 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'UserProfile.verification_hash' - db.add_column('super_archives_userprofile', 'verification_hash', self.gf('django.db.models.fields.CharField')(max_length=32, null=True), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'UserProfile.verification_hash' - db.delete_column('super_archives_userprofile', 'verification_hash') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0003_auto__add_field_thread_score.py b/colab/super_archives/migrations/0003_auto__add_field_thread_score.py deleted file mode 100644 index afb9069..0000000 --- a/colab/super_archives/migrations/0003_auto__add_field_thread_score.py +++ /dev/null @@ -1,134 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'Thread.score' - db.add_column('super_archives_thread', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'Thread.score' - db.delete_column('super_archives_thread', 'score') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0004_auto__add_field_vote_created.py b/colab/super_archives/migrations/0004_auto__add_field_vote_created.py deleted file mode 100644 index 9be9e33..0000000 --- a/colab/super_archives/migrations/0004_auto__add_field_vote_created.py +++ /dev/null @@ -1,135 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'Vote.created' - db.add_column('super_archives_vote', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2012, 1, 19, 18, 8, 46, 813949), blank=True), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'Vote.created' - db.delete_column('super_archives_vote', 'created') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py b/colab/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py deleted file mode 100644 index 1fd669d..0000000 --- a/colab/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py +++ /dev/null @@ -1,143 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'Message.spam' - db.add_column('super_archives_message', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) - - # Adding field 'Thread.spam' - db.add_column('super_archives_thread', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'Message.spam' - db.delete_column('super_archives_message', 'spam') - - # Deleting field 'Thread.spam' - db.delete_column('super_archives_thread', 'spam') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0006_auto.py b/colab/super_archives/migrations/0006_auto.py deleted file mode 100644 index bfbad99..0000000 --- a/colab/super_archives/migrations/0006_auto.py +++ /dev/null @@ -1,143 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding index on 'Message', fields ['subject_clean'] - db.create_index('super_archives_message', ['subject_clean']) - - # Adding index on 'Message', fields ['subject'] - db.create_index('super_archives_message', ['subject']) - - - def backwards(self, orm): - - # Removing index on 'Message', fields ['subject'] - db.delete_index('super_archives_message', ['subject']) - - # Removing index on 'Message', fields ['subject_clean'] - db.delete_index('super_archives_message', ['subject_clean']) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0007_auto.py b/colab/super_archives/migrations/0007_auto.py deleted file mode 100644 index e8fedca..0000000 --- a/colab/super_archives/migrations/0007_auto.py +++ /dev/null @@ -1,137 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding index on 'EmailAddress', fields ['real_name'] - db.create_index('super_archives_emailaddress', ['real_name']) - - - def backwards(self, orm): - - # Removing index on 'EmailAddress', fields ['real_name'] - db.delete_index('super_archives_emailaddress', ['real_name']) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0008_add_mailinglist_name_to_url.py b/colab/super_archives/migrations/0008_add_mailinglist_name_to_url.py deleted file mode 100644 index a5193f4..0000000 --- a/colab/super_archives/migrations/0008_add_mailinglist_name_to_url.py +++ /dev/null @@ -1,142 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import DataMigration -from django.db import models - -class Migration(DataMigration): - - def forwards(self, orm): - page_hits = orm.PageHit.objects.all() - for page_hit in page_hits: - if page_hit.url_path.startswith('/archives/thread/'): - token = page_hit.url_path.split('/')[-1] - threads = orm.Thread.objects.filter(subject_token=token) - if not len(threads): continue - thread = threads[0] - new_url = '/archives/thread/%s/%s' % (thread.mailinglist.name, - thread.subject_token) - page_hit.url_path = new_url - page_hit.save() - - - def backwards(self, orm): - raise RuntimeError("Cannot reverse this migration.") - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py b/colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py deleted file mode 100644 index f68774e..0000000 --- a/colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py +++ /dev/null @@ -1,136 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Deleting field 'Message.mailinglist' - db.delete_column('super_archives_message', 'mailinglist_id') - - - def backwards(self, orm): - - # User chose to not deal with backwards NULL issues for 'Message.mailinglist' - raise RuntimeError("Cannot reverse this migration. 'Message.mailinglist' and its values cannot be restored.") - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py b/colab/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py deleted file mode 100644 index ef2efb4..0000000 --- a/colab/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py +++ /dev/null @@ -1,136 +0,0 @@ -# encoding: utf-8 -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding unique constraint on 'Message', fields ['message_id', 'thread'] - db.create_unique('super_archives_message', ['message_id', 'thread_id']) - - - def backwards(self, orm): - - # Removing unique constraint on 'Message', fields ['message_id', 'thread'] - db.delete_unique('super_archives_message', ['message_id', 'thread_id']) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'super_archives.emailaddress': { - 'Meta': {'object_name': 'EmailAddress'}, - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) - }, - 'super_archives.mailinglist': { - 'Meta': {'object_name': 'MailingList'}, - 'description': ('django.db.models.fields.TextField', [], {}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) - }, - 'super_archives.mailinglistmembership': { - 'Meta': {'object_name': 'MailingListMembership'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'super_archives.message': { - 'Meta': {'unique_together': "(('thread', 'message_id'),)", 'object_name': 'Message'}, - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) - }, - 'super_archives.messagemetadata': { - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'Meta': {'object_name': 'MessageMetadata'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'value': ('django.db.models.fields.TextField', [], {}) - }, - 'super_archives.pagehit': { - 'Meta': {'object_name': 'PageHit'}, - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) - }, - 'super_archives.thread': { - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) - }, - 'super_archives.userprofile': { - 'Meta': {'object_name': 'UserProfile'}, - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) - }, - 'super_archives.vote': { - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - } - } - - complete_apps = ['super_archives'] diff --git a/colab/super_archives/migrations/__init__.py b/colab/super_archives/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/super_archives/migrations/__init__.py +++ /dev/null diff --git a/colab/super_archives/models.py b/colab/super_archives/models.py deleted file mode 100644 index 3b0448b..0000000 --- a/colab/super_archives/models.py +++ /dev/null @@ -1,279 +0,0 @@ -# -*- coding: utf-8 -*- - -import datetime -from hashlib import md5 - -from django.db import models -from django.conf import settings -from django.contrib.auth.models import User -from django.core.urlresolvers import reverse, NoReverseMatch -from django.utils.translation import ugettext_lazy as _ - - -class NotSpamManager(models.Manager): - """Only return objects which are not marked as spam.""" - - def get_query_set(self): - return super(NotSpamManager, self).get_query_set().exclude(spam=True) - - -class PageHit(models.Model): - url_path = models.CharField(max_length=2048, unique=True, db_index=True) - hit_count = models.IntegerField(default=0) - - -class EmailAddress(models.Model): - user = models.ForeignKey(User, null=True, related_name='emails') - address = models.EmailField(unique=True) - real_name = models.CharField(max_length=64, blank=True, db_index=True) - md5 = models.CharField(max_length=32, null=True) - - def save(self, *args, **kwargs): - self.md5 = md5(self.address).hexdigest() - super(EmailAddress, self).save(*args, **kwargs) - - def get_full_name(self): - if self.user and self.user.get_full_name(): - return self.user.get_full_name() - elif self.user and self.username: - return self.username - elif self.real_name: - return self.real_name - - def get_profile_link(self): - if self.user: - return reverse('user_profile', args=[self.user.username]) - else: - return reverse('colab.views.userprofile.by_emailhash', - args=[self.md5]) - - def __unicode__(self): - return '"%s" <%s>' % (self.get_full_name(), self.address) - - -class UserProfile(models.Model): - - user = models.OneToOneField(User, unique=True) - institution = models.CharField(max_length=128, null=True) - role = models.CharField(max_length=128, null=True) - twitter = models.CharField(max_length=128, null=True) - facebook = models.CharField(max_length=128, null=True) - google_talk = models.EmailField(null=True) - webpage = models.CharField(max_length=256) - verification_hash = models.CharField(max_length=32, null=True) - - class Meta: - verbose_name = _(u"User Profile") - verbose_name_plural = _(u"Users Profiles") - - def __unicode__(self): - return '%s (%s)' % (self.user.get_full_name(), self.user.username) - -# This does the same the same than related_name argument but it also creates -# a profile in the case it doesn't exist yet. -User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0]) - - -class MailingList(models.Model): - name = models.CharField(max_length=80) - email = models.EmailField() - description = models.TextField() - logo = models.FileField(upload_to='list_logo') #TODO - last_imported_index = models.IntegerField(default=0) - - def __unicode__(self): - return self.name - - -class MailingListMembership(models.Model): - user = models.ForeignKey(User) - mailinglist = models.ForeignKey(MailingList) - - def __unicode__(self): - return '%s on %s' % (self.user.username, self.mailinglist.name) - - -class Thread(models.Model): - - subject_token = models.CharField(max_length=512) - mailinglist = models.ForeignKey(MailingList, - verbose_name=_(u"Mailing List"), - help_text=_(u"The Mailing List where is the thread")) - latest_message = models.OneToOneField('Message', null=True, - related_name='+', - verbose_name=_(u"Latest message"), - help_text=_(u"Latest message posted")) - score = models.IntegerField(default=0, verbose_name=_(u"Score"), help_text=_(u"Thread score")) - spam = models.BooleanField(default=False) - - all_objects = models.Manager() - objects = NotSpamManager() - - class Meta: - verbose_name = _(u"Thread") - verbose_name_plural = _(u"Threads") - unique_together = ('subject_token', 'mailinglist') - - def __unicode__(self): - return '%s - %s (%s)' % (self.id, - self.subject_token, - self.message_set.count()) - - def update_score(self): - """Update the relevance score for this thread. - - The score is calculated with the following variables: - - * vote_weight: 100 - (minus) 1 for each 3 days since - voted with minimum of 5. - * replies_weight: 300 - (minus) 1 for each 3 days since - replied with minimum of 5. - * page_view_weight: 10. - - * vote_score: sum(vote_weight) - * replies_score: sum(replies_weight) - * page_view_score: sum(page_view_weight) - - * score = (vote_score + replies_score + page_view_score) // 10 - with minimum of 0 and maximum of 5000 - - """ - - if not self.subject_token: - return - - # Save this pseudo now to avoid calling the - # function N times in the loops below - now = datetime.datetime.now() - days_ago = lambda date: (now - date).days - get_score = lambda weight, created: \ - max(weight - (days_ago(created) // 3), 5) - - vote_score = 0 - replies_score = 0 - for msg in self.message_set.all(): - # Calculate replies_score - replies_score += get_score(300, msg.received_time) - - # Calculate vote_score - for vote in msg.vote_set.all(): - vote_score += get_score(100, vote.created) - - # Calculate page_view_score - try: - url = reverse('thread_view', args=[self.mailinglist.name, - self.subject_token]) - pagehit = PageHit.objects.get(url_path=url) - page_view_score = pagehit.hit_count * 10 - except (NoReverseMatch, PageHit.DoesNotExist): - page_view_score = 0 - - self.score = (page_view_score + vote_score + replies_score) // 10 - self.save() - - -class Vote(models.Model): - user = models.ForeignKey(User) - message = models.ForeignKey('Message') - created = models.DateTimeField(auto_now_add=True) - - class Meta: - unique_together = ('user', 'message') - - def __unicode__(self): - return 'Vote on %s by %s' % (self.Message.id, - self.user.username) - - -class Message(models.Model): - - from_address = models.ForeignKey(EmailAddress, db_index=True) - thread = models.ForeignKey(Thread, null=True, db_index=True) - # RFC 2822 recommends to use 78 chars + CRLF (so 80 chars) for - # the max_length of a subject but most of implementations - # goes for 256. We use 512 just in case. - subject = models.CharField(max_length=512, db_index=True, - verbose_name=_(u"Subject"), - help_text=_(u"Please enter a message subject")) - subject_clean = models.CharField(max_length=512, db_index=True) - body = models.TextField(default='', - verbose_name=_(u"Message body"), - help_text=_(u"Please enter a message body")) - received_time = models.DateTimeField() - message_id = models.CharField(max_length=512) - spam = models.BooleanField(default=False) - - all_objects = models.Manager() - objects = NotSpamManager() - - class Meta: - verbose_name = _(u"Message") - verbose_name_plural = _(u"Messages") - unique_together = ('thread', 'message_id') - - def __unicode__(self): - return '(%s) %s: %s' % (self.id, - self.from_address.get_full_name(), - self.subject_clean) - - @property - def mailinglist(self): - if not self.thread or not self.thread.mailinglist: - return None - - return self.thread.mailinglist - - - def vote_list(self): - """Return a list of user that voted in this message.""" - - return [vote.user for vote in self.vote_set.all()] - - def votes_count(self): - return len(self.vote_list()) - - def vote(self, user): - Vote.objects.create( - message=self, - user=user - ) - - def unvote(self, user): - Vote.objects.get( - message=self, - user=user - ).delete() - - @property - def url(self): - """Shortcut to get thread url""" - return reverse('thread_view', args=[self.mailinglist.name, - self.thread.subject_token]) - - @property - def Description(self): - """Alias to self.body""" - return self.body - - @property - def Title(self): - """Alias to self.subject_clean""" - return self.subject_clean - - @property - def modified(self): - """Alias to self.modified""" - return self.received_time - - -class MessageMetadata(models.Model): - Message = models.ForeignKey(Message) - # Same problem here than on subjects. Read comment above - # on Message.subject - name = models.CharField(max_length=512) - value = models.TextField() - - def __unicode__(self): - return 'Email Message Id: %s - %s: %s' % (self.Message.id, - self.name, self.value) - diff --git a/colab/super_archives/queries.py b/colab/super_archives/queries.py deleted file mode 100644 index 2ef00ff..0000000 --- a/colab/super_archives/queries.py +++ /dev/null @@ -1,54 +0,0 @@ - -from django.core.exceptions import ObjectDoesNotExist -from colab.super_archives.models import Thread, Vote, Message, PageHit - - -def get_messages_by_date(): - return Message.objects.order_by('received_time') - - -def get_messages_by_voted(): - """Query for the most voted messages sorting by the sum of - voted and after by date.""" - - sql = """ - SELECT - count(sav.id) - FROM - super_archives_vote AS sav - WHERE - super_archives_message.id = sav.message_id - """ - messages = Message.objects.extra( - select={ - 'vote_count': sql, - } - ) - return messages.order_by('-vote_count', 'received_time') - - -def get_first_message_in_thread(mailinglist, thread_token): - query = get_messages_by_date() - query = query.filter(thread__mailinglist__name=mailinglist) - try: - query = query.filter(thread__subject_token=thread_token)[0] - except IndexError: - raise ObjectDoesNotExist - return query - - -def get_latest_threads(): - return Thread.objects.order_by('-latest_message__received_time') - - -def get_hottest_threads(): - return Thread.objects.order_by('-score', '-latest_message__received_time') - - -def get_page_hits(path_info): - pagehit = PageHit.objects.filter(url_path=path_info) - - if pagehit: - return pagehit[0].hit_count - return 0 - diff --git a/colab/super_archives/templates/message-list.html b/colab/super_archives/templates/message-list.html deleted file mode 100644 index 7e4ce4c..0000000 --- a/colab/super_archives/templates/message-list.html +++ /dev/null @@ -1,68 +0,0 @@ -{% extends "base.html" %} -{% load i18n %} -{% load append_to_get %} -{% block main-content %} -
-

{% trans "Discussions" %}

-
- -
-

{% trans "Filters" %}

- -

{% trans "Sort by" %}

- - -
- -

{% trans "Lists" %}

- -
- -
-
    - {% for thread in threads.object_list %} - {% include "message-preview.html" with doc=thread.latest_message %} - {% empty %} -

    - - {% trans "No discussion found" %} - - {% endfor %} -
-
- - {% if n_results %} - - {% endif %} - -
-
- -{% endblock %} diff --git a/colab/super_archives/templates/message-preview.html b/colab/super_archives/templates/message-preview.html deleted file mode 100644 index 1010519..0000000 --- a/colab/super_archives/templates/message-preview.html +++ /dev/null @@ -1,51 +0,0 @@ -{% load i18n %} - -{% if doc.Title %} -
  • - {% if doc.Type %} - {{ doc.Type }} - {% else %} - thread - {% endif %} - - {% if doc.mailinglist %} - - {{ doc.mailinglist }} - - {% endif %} - - - - {{ doc.Title }} - - - - - - {{ doc.Description|striptags }} - - -
    - - {% trans "by" %} - {% if doc.from_address.get_full_name %} - - {{ doc.from_address.get_full_name }} - - {% else %} - {% firstof doc.last_author doc.Creator _("anônimo") %} - {% endif %} - - - - {{ doc.modified|timesince }} - {% trans "back" %} - -
    -
  • -{% endif %} diff --git a/colab/super_archives/templates/message-thread.html b/colab/super_archives/templates/message-thread.html deleted file mode 100644 index e9ee583..0000000 --- a/colab/super_archives/templates/message-thread.html +++ /dev/null @@ -1,77 +0,0 @@ -{% extends "base.html" %} -{% load i18n %} -{% load append_to_get %} -{% block main-content %} -
    - -

    {{ first_msg.subject_clean }}

    -
    -
    - -
    -
    -

    {% trans "Order by" %}:

    - - -
    - -

    {% trans "Statistics:" %}

    - -
      -
    • {% trans "started at" %} -

      {{ first_msg.received_time|timesince }} {% trans "back" %}

      -
    • -
    • {% trans "viewed" %} -

      {{ pagehits }} {% trans "times" %}

      -
    • -
    • {% trans "answered" %} -

      {{ emails|length }} {% trans "times" %}

      -
    • -
    • {% trans "voted" %} -

      {{ total_votes }} {% trans "times" %}

      -
    • -
    - -
    - - - -{% endblock %} diff --git a/colab/super_archives/templatetags/__init__.py b/colab/super_archives/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/colab/super_archives/templatetags/__init__.py +++ /dev/null diff --git a/colab/super_archives/templatetags/append_to_get.py b/colab/super_archives/templatetags/append_to_get.py deleted file mode 100644 index 7dfbcb4..0000000 --- a/colab/super_archives/templatetags/append_to_get.py +++ /dev/null @@ -1,56 +0,0 @@ - -import urllib -from django import template - -register = template.Library() - -""" -Decorator to facilitate template tag creation -""" -def easy_tag(func): - """deal with the repetitive parts of parsing template tags""" - def inner(parser, token): - #print token - try: - return func(*token.split_contents()) - except TypeError: - raise template.TemplateSyntaxError('Bad arguments for tag "%s"' % - token.split_contents()[0]) - inner.__name__ = func.__name__ - inner.__doc__ = inner.__doc__ - return inner - - -class AppendGetNode(template.Node): - def __init__(self, dict): - self.dict_pairs = {} - for pair in dict.split(','): - pair = pair.split('=') - self.dict_pairs[pair[0]] = template.Variable(pair[1]) - - def render(self, context): - get = context['request'].GET.copy() - - for key in self.dict_pairs: - get[key] = self.dict_pairs[key].resolve(context) - - path = context['request'].META['PATH_INFO'] - - if len(get): - # Convert all unicode objects in the get dict to - # str (utf-8 encoded) - get_utf_encoded = {} - for (key, value) in get.items(): - if isinstance(value, unicode): - value = value.encode('utf-8') - get_utf_encoded.update({key: value}) - get_utf_encoded = dict(get_utf_encoded) - - path = '?' + urllib.urlencode(get_utf_encoded) - - return path - -@register.tag() -@easy_tag -def append_to_get(_tag_name, dict): - return AppendGetNode(dict) diff --git a/colab/super_archives/templatetags/form_field.py b/colab/super_archives/templatetags/form_field.py deleted file mode 100644 index e71dbd7..0000000 --- a/colab/super_archives/templatetags/form_field.py +++ /dev/null @@ -1,64 +0,0 @@ -from django import template -from django import forms - -def render_form_field(parser, token): - variables = token.split_contents() - - if len(variables) == 2: - tag_name, form_field = variables - default_value = 'None' - elif len(variables) == 3: - tag_name, form_field, default_value = variables - else: - raise template.TemplateSyntaxError - - return RenderFormField(form_field, default_value) - - -class RenderFormField(template.Node): - - def __init__(self, form_field, default_value): - self.form_field_nocontext = template.Variable(form_field) - self.default_value_nocontext = template.Variable(default_value) - - def render(self, context): - editable = context.get('editable', True) - - class_ = u'' - errors = u'' - form_field_tag = u'' - try: - form_field = self.form_field_nocontext.resolve(context) - except template.VariableDoesNotExist: - return u'' - - if form_field.errors: - class_ += u'error' - if form_field.field.required: - class_ += u' required' - if form_field.errors: - errors = u'
    ' + form_field.errors.as_text() - - try: - default_value = self.default_value_nocontext.resolve(context) - except template.VariableDoesNotExist: - default_value = u'' - - if editable: - form_field_tag = u'
    ' + unicode(form_field) - elif isinstance(form_field.field, forms.URLField): - form_field_tag = u"""%s""" % ( - default_value, default_value) - else: - form_field_tag = default_value - - return u"""

    %s: %s %s

    """ % ( - class_, - form_field.label_tag(), - form_field_tag, - errors - ) - - -register = template.Library() -register.tag('render_form_field', render_form_field) diff --git a/colab/super_archives/tests.py b/colab/super_archives/tests.py deleted file mode 100644 index 501deb7..0000000 --- a/colab/super_archives/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - -from django.test import TestCase - - -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) diff --git a/colab/super_archives/urls.py b/colab/super_archives/urls.py deleted file mode 100644 index 3676ac1..0000000 --- a/colab/super_archives/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.conf.urls.defaults import patterns, include, url - -urlpatterns = patterns('', -# url(r'thread/(?P\d+)/$', 'super_archives.views.thread', name='thread'), - url(r'thread/(?P[-\w]+)/(?P[-\w]+)$', - 'colab.super_archives.views.thread', name="thread_view"), - url(r'thread/$', - 'colab.super_archives.views.list_messages', name='thread_list') -) diff --git a/colab/super_archives/validators.py b/colab/super_archives/validators.py deleted file mode 100644 index 09049dc..0000000 --- a/colab/super_archives/validators.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- - -from django.core.exceptions import ValidationError - -class UniqueValidator(object): - - def __init__(self, model, field_name): - self.model = model - self.field_name = field_name - - def __call__(self, value): - result = self.model.objects.filter(**{self.field_name: value}) - if result: - msg = u'Já existente. Escolha outro.' - raise ValidationError(msg) diff --git a/colab/super_archives/views.py b/colab/super_archives/views.py deleted file mode 100644 index db169ef..0000000 --- a/colab/super_archives/views.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- - -from django.http import Http404 -from django.template import RequestContext -from django.core.paginator import Paginator -from django.core.exceptions import ObjectDoesNotExist -from django.shortcuts import render_to_response, get_list_or_404 - -from colab.super_archives import queries -from colab.super_archives.models import MailingList, Thread - - -def thread(request, mailinglist, thread_token): - - try: - first_message = queries.get_first_message_in_thread(mailinglist, thread_token) - except ObjectDoesNotExist: - raise Http404 - order_by = request.GET.get('order') - if order_by == 'voted': - msgs_query = queries.get_messages_by_voted() - else: - msgs_query = queries.get_messages_by_date() - - msgs_query = msgs_query.filter(thread__subject_token=thread_token) - msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist) - emails = msgs_query.exclude(id=first_message.id) - - total_votes = first_message.votes_count() - for email in emails: - total_votes += email.votes_count() - - # Update relevance score - query = Thread.objects.filter(mailinglist__name=mailinglist) - thread = query.get(subject_token=thread_token) - thread.update_score() - - template_data = { - 'first_msg': first_message, - 'emails': [first_message] + list(emails), - 'pagehits': queries.get_page_hits(request.path_info), - 'total_votes': total_votes, - } - - return render_to_response('message-thread.html', template_data, - RequestContext(request)) - - -def list_messages(request): - - selected_list = request.GET.get('list') - - order_by = request.GET.get('order') - if order_by == 'hottest': - threads = queries.get_hottest_threads() - else: - threads = queries.get_latest_threads() - - mail_list = request.GET.get('list') - if mail_list: - threads = threads.filter(mailinglist__name=mail_list) - - paginator = Paginator(threads, 16) - try: - page = int(request.GET.get('p', '1')) - except ValueError: - page = 1 - threads = paginator.page(page) - - lists = MailingList.objects.all() - - template_data = { - 'lists': lists, - 'n_results': paginator.count, - 'threads': threads, - 'selected_list': selected_list, - 'order_by': order_by, - } - return render_to_response('message-list.html', template_data, - RequestContext(request)) diff --git a/src/api/__init__.py b/src/api/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/api/__init__.py diff --git a/src/api/handlers.py b/src/api/handlers.py new file mode 100644 index 0000000..a1a02c4 --- /dev/null +++ b/src/api/handlers.py @@ -0,0 +1,103 @@ + +from django.core.cache import cache +from django.db import IntegrityError +from django.core.exceptions import ObjectDoesNotExist +from django.contrib.auth.decorators import login_required + +from piston.utils import rc +from piston.handler import BaseHandler + +from colab import solrutils +from colab.super_archives.models import Message, PageHit + + +class VoteHandler(BaseHandler): + allowed_methods = ('GET', 'POST', 'DELETE') + + def create(self, request, message_id): + if not request.user.is_authenticated(): + return rc.FORBIDDEN + + try: + Message.objects.get(id=message_id).vote(request.user) + except IntegrityError: + return rc.DUPLICATE_ENTRY + + return rc.CREATED + + def read(self, request, message_id): + return Message.objects.get(id=message_id).votes_count() + + def delete(self, request, message_id): + if not request.user.is_authenticated(): + return rc.FORBIDDEN + + try: + Message.objects.get(id=message_id).unvote(request.user) + except ObjectDoesNotExist: + return rc.NOT_HERE + + return rc.DELETED + + +class CountHandler(BaseHandler): + allowed_methods = ('POST') + + def create(self, request): + """Add one page view for the given url""" + + # If missing the path_info argument we can't do anything + path_info = request.POST.get('path_info') + if not path_info: + return rc.BAD_REQUEST + + # Here we cache the user's IP to ensure that the same + # IP won't hit the same page again for while + ip_addr = request.META.get('REMOTE_ADDR') + page_hits_cache = cache.get('page_hits', {}) + duplicate = page_hits_cache.get(path_info, {}).get(ip_addr) + + if duplicate: + return rc.DUPLICATE_ENTRY + else: + page_hits_cache.update({path_info: {ip_addr: True }}) + cache.set('page_hits', page_hits_cache) + + # Everything ok, so just increment the page count + page_hit = PageHit.objects.get_or_create(url_path=path_info)[0] + page_hit.hit_count += 1 + page_hit.save() + + return rc.CREATED + +class SearchHandler(BaseHandler): + allowed_methods = ('GET', ) + + def read(self, request): + query = request.GET.get('q') + page = request.GET.get('p', 1) + results_per_page = request.GET.get('n', 50) + order = request.GET.get('o') + + if not query: + return 'Query cannot be empty.' + else: + query = query.encode('utf-8') + + try: + n = int(results_per_page) + except ValueError: + n = 10 + + if 1 > n > 500: + n = 1 + + try: + page = int(page) + except ValueError: + page = 1 + + if page < 1: + page = 1 + + return solrutils.select(query, results_per_page, page, order) diff --git a/src/api/urls.py b/src/api/urls.py new file mode 100644 index 0000000..f89db6c --- /dev/null +++ b/src/api/urls.py @@ -0,0 +1,16 @@ +from django.conf.urls.defaults import patterns, include, url + +from piston.resource import Resource + +from colab.api.handlers import VoteHandler, CountHandler, SearchHandler + + +vote_handler = Resource(VoteHandler) +count_handler = Resource(CountHandler) +search_handler = Resource(SearchHandler) + +urlpatterns = patterns('', + url(r'message/(?P\d+)/vote$', vote_handler), + url(r'hit/$', count_handler), + url(r'search/$', search_handler), +) diff --git a/src/rss/__init__.py b/src/rss/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/rss/__init__.py diff --git a/src/rss/feeds.py b/src/rss/feeds.py new file mode 100644 index 0000000..36ba6d5 --- /dev/null +++ b/src/rss/feeds.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# encoding: utf-8 + +from django.contrib.syndication.views import Feed +from django.utils.translation import ugettext as _ + +from colab.super_archives.models import Thread +from colab.super_archives import queries +from colab import solrutils + +class LatestThreadsFeeds(Feed): + title = _(u'Latest Discussions') + link = '/rss/threads/latest/' + + def items(self): + return queries.get_latest_threads()[:20] + + def item_link(self, item): + return item.latest_message.url + + def item_title(self, item): + title = '[' + item.mailinglist.name + '] ' + title += item.latest_message.subject_clean + return title + + def item_description(self, item): + return item.latest_message.body + + +class HottestThreadsFeeds(Feed): + title = _(u'Discussions Most Relevance') + link = '/rss/threads/hottest/' + + def items(self): + return queries.get_hottest_threads()[:20] + + def item_link(self, item): + return item.latest_message.url + + def item_title(self, item): + title = '[' + item.mailinglist.name + '] ' + title += item.latest_message.subject_clean + return title + + def item_description(self, item): + return item.latest_message.body + + +class LatestColabFeeds(Feed): + title = _(u'Latest collaborations') + link = '/rss/colab/latest/' + + def items(self): + items = solrutils.get_latest_collaborations(20) + return items + + def item_title(self, item): + type_ = item.get('Type') + ': ' + mailinglist = item.get('mailinglist') + + if mailinglist: + prefix = type_ + mailinglist + ' - ' + else: + prefix = type_ + + return prefix + item.get('Title') + + def item_description(self, item): + return item.get('Description') + + def item_link(self, item): + if item.get('Type') != 'thread': + url = item.get('url') + else: + url = 'http://colab.interlegis.leg.br' + url += item.get('url') + return url + diff --git a/src/rss/urls.py b/src/rss/urls.py new file mode 100644 index 0000000..c995183 --- /dev/null +++ b/src/rss/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import patterns, url +import feeds + +urlpatterns = patterns('', + url(r'threads/latest/$', feeds.LatestThreadsFeeds(), name='rss_latest_threads'), + url(r'colab/latest/$', feeds.LatestColabFeeds(), name='rss_latest_colab'), + url(r'threads/hottest/$', feeds.HottestThreadsFeeds(), name='rss_hottest_threads'), +) + diff --git a/src/super_archives/__init__.py b/src/super_archives/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/super_archives/__init__.py diff --git a/src/super_archives/admin.py b/src/super_archives/admin.py new file mode 100644 index 0000000..12d9c15 --- /dev/null +++ b/src/super_archives/admin.py @@ -0,0 +1,54 @@ + +from django.contrib import admin +from colab.super_archives.models import Message, Thread, UserProfile + +class MessageAdmin(admin.ModelAdmin): + list_filter = ('spam', 'thread__mailinglist', 'received_time', ) + search_fields = ( + 'id', + 'subject', + 'subject_clean', + 'body', + 'from_address__real_name', + 'from_address__address', + 'from_address__user__first_name', + 'from_address__user__last_name', + 'from_address__user__username', + ) + readonly_fields = ('thread', 'from_address', 'mailinglist') + + +class ThreadAdmin(admin.ModelAdmin): + list_filter = ('spam', 'mailinglist', 'message__received_time',) + search_fields = ( + 'id', + 'subject_token', + 'message__subject', + 'message__subject_clean', + 'message__from_address__real_name', + 'message__from_address__address', + 'message__from_address__user__first_name', + 'message__from_address__user__last_name', + 'message__from_address__user__username', + ) + + readonly_fields = ( + 'mailinglist', + 'subject_token', + 'latest_message', + 'score', + ) + + fields = ( + 'mailinglist', + 'subject_token', + 'latest_message', + 'score', + 'spam', + ) + + +admin.site.register(UserProfile) +admin.site.register(Thread, ThreadAdmin) +admin.site.register(Message, MessageAdmin) + diff --git a/src/super_archives/fixtures/initial_data.json b/src/super_archives/fixtures/initial_data.json new file mode 100644 index 0000000..42c25fb --- /dev/null +++ b/src/super_archives/fixtures/initial_data.json @@ -0,0 +1,10 @@ +[ + { + "pk": 1, + "model": "auth.group", + "fields": { + "name": "developer", + "permissions": [] + } + } +] diff --git a/src/super_archives/forms.py b/src/super_archives/forms.py new file mode 100644 index 0000000..d061cda --- /dev/null +++ b/src/super_archives/forms.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +from django import forms +from django.core.exceptions import ValidationError +from django.contrib.auth.models import User +from django.contrib.auth.forms import UserCreationForm as UserCreationForm_ +from django.utils.translation import ugettext_lazy as _ + +from colab.super_archives.models import MailingList +from colab.super_archives.validators import UniqueValidator + +# XXX: I know that this code does not look nice AT ALL. +# probably it should be implemented using formsets instead of +# the hack below. Feel free to improve it! :) + +# User fields +username_field = UserCreationForm_().fields.get(u'username') +first_name_field = forms.CharField(max_length=30, label=_(u'Name')) +last_name_field = forms.CharField(max_length=30, label=_(u'Last name')) +email_field = forms.EmailField(validators=[UniqueValidator(User, 'email')]) + +# UserProfile fields +institution_field = forms.CharField(max_length=120, label=_(u'Institution'), + required=False) +role_field = forms.CharField(max_length=60, label=_(u'Function'), required=False) +twitter_field = forms.URLField(label=_(u'Twitter'), required=False) +facebook_field = forms.URLField(label=_(u'Facebook'), required=False) +google_talk_field = forms.EmailField(label=_(u'Google Talk'), required=False) +webpage_field = forms.URLField(label=_(u'Personal Website/Blog'), required=False) + +all_lists = MailingList.objects.all() +lists_names = [] +for list_ in all_lists: + choice = (list_.name, list_.name) + lists_names.append(choice) + +lists_field = forms.MultipleChoiceField( + label=u'Listas', + required=False, + widget=forms.CheckboxSelectMultiple, + choices=lists_names +) + + +class UserCreationForm(UserCreationForm_): + first_name = first_name_field + last_name = last_name_field + email = email_field + institution = institution_field + role = role_field + twitter = twitter_field + facebook = facebook_field + google_talk = google_talk_field + webpage = webpage_field + lists = lists_field + + +class UserUpdateForm(forms.Form): + username = username_field + username.required = False + institution = institution_field + role = role_field + twitter = twitter_field + facebook = facebook_field + google_talk = google_talk_field + webpage = webpage_field diff --git a/src/super_archives/management/__init__.py b/src/super_archives/management/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/super_archives/management/__init__.py diff --git a/src/super_archives/management/commands/__init__.py b/src/super_archives/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/super_archives/management/commands/__init__.py diff --git a/src/super_archives/management/commands/import_emails.py b/src/super_archives/management/commands/import_emails.py new file mode 100644 index 0000000..cfffb5a --- /dev/null +++ b/src/super_archives/management/commands/import_emails.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +"""Import emails from a mailman storage to the django database.""" + +import os +import re +import sys +import mailbox +from optparse import make_option + +from django.db import transaction +from django.template.defaultfilters import slugify +from django.core.management.base import BaseCommand, CommandError + +from colab.super_archives.models import MailingList, Message, \ + Thread, EmailAddress +from colab.super_archives.management.commands.message import Message as \ + CustomMessage + + +class Command(BaseCommand, object): + """Get emails from mailman archives and import them in the django db. """ + + help = __doc__ + + default_archives_path = '/var/lib/mailman/archives/private' + RE_SUBJECT_CLEAN = re.compile('((re|res|fw|fwd|en|enc):)|\[.*?\]', + re.IGNORECASE) + THREAD_CACHE = {} + EMAIL_ADDR_CACHE = {} + + # A new command line option to get the dump file to parse. + option_list = BaseCommand.option_list + ( + make_option('--archives_path', + dest='archives_path', + help='Path of email archives to be imported. (default: %s)' % + default_archives_path, + default=default_archives_path), + + make_option('--exclude-list', + dest='exclude_lists', + help=("Mailing list that won't be imported. It can be used many" + "times for more than one list."), + action='append', + default=None), + + make_option('--all', + dest='all', + help='Import all messages (default: False)', + action="store_true", + default=False), + ) + + def __init__(self, *args, **kwargs): + super(Command, self).__init__(*args, **kwargs) + + def log(self, msg, error=False): + """Log message helper.""" + output = self.stdout + if error: + output = self.stderr + + output.write(msg) + output.write('\n') + + def parse_emails(self, email_filename, index=0): + """Generator function that parse and extract emails from the file + `email_filename` starting from the position `index`. + + Yield: An instance of `mailbox.mboxMessage` for each email in the + file. + + """ + self.log("Parsing email dump: %s." % email_filename) + mbox = mailbox.mbox(email_filename, factory=CustomMessage) + + # Get each email from mbox file + # + # The following implementation was used because the object + # mbox does not support slicing. Converting the object to a + # tuple (as represented in the code down here) was a valid + # option but its performance was too poor. + # + #for message in tuple(mbox)[index:]: + # yield message + # + key = index + while mbox.has_key(key): + key += 1 + yield key-1, mbox[key-1] + + def get_emails(self, mailinglist_dir, all, exclude_lists): + """Generator function that get the emails from each mailing + list dump dirctory. If `all` is set to True all the emails in the + mbox will be imported if not it will just resume from the last + message previously imported. The lists set in `exclude_lists` + won't be imported. + + Yield: A tuple in the form: (mailing list name, email message). + + """ + self.log("Getting emails dumps from: %s" % mailinglist_dir) + + # Get the list of directories ending with .mbox + mailing_lists_mboxes = (mbox for mbox in os.listdir(mailinglist_dir) + if mbox.endswith('.mbox')) + + # Get messages from each mbox + for mbox in mailing_lists_mboxes: + mbox_path = os.path.join(mailinglist_dir, mbox, mbox) + mailinglist_name = mbox.split('.')[0] + + # Check if the mailinglist is set not to be imported + if exclude_lists and mailinglist_name in exclude_lists: + continue + + # Find the index of the last imported message + if all: + n_msgs = 0 + else: + try: + mailinglist = MailingList.objects.get( + name=mailinglist_name) + n_msgs = mailinglist.last_imported_index + except MailingList.DoesNotExist: + n_msgs = 0 + + for index, msg in self.parse_emails(mbox_path, n_msgs): + yield mailinglist_name, msg, index + + def get_thread(self, email, mailinglist): + """Group messages by thread looking for similar subjects""" + + subject_slug = slugify(email.subject_clean) + thread = self.THREAD_CACHE.get(subject_slug, {}).get(mailinglist.id) + if thread is None: + thread = Thread.objects.get_or_create( + mailinglist=mailinglist, + subject_token=subject_slug + )[0] + + if self.THREAD_CACHE.get(subject_slug) is None: + self.THREAD_CACHE[subject_slug] = dict() + self.THREAD_CACHE[subject_slug][mailinglist.id] = thread + + thread.latest_message = email + thread.save() + return thread + + def save_email(self, list_name, email_msg, index): + """Save email message into the database.""" + + # Update last imported message into the DB + mailinglist, created = MailingList.objects.get_or_create(name=list_name) + mailinglist.last_imported_index = index + + if created: + # if the mailinglist is newly created it's sure that the message + # is not in the DB yet. + self.create_email(mailinglist, email_msg) + + else: + # If the message is already at the database don't do anything + try: + messages = Message.objects.get( + message_id=email_msg.get('Message-ID'), + thread__mailinglist=mailinglist + ) + + except Message.DoesNotExist: + self.create_email(mailinglist, email_msg) + + mailinglist.save() + + def create_email(self, mailinglist, email_msg): + + real_name, from_ = email_msg.get_from_addr() + + email_addr = self.EMAIL_ADDR_CACHE.get(from_) + if email_addr is None: + email_addr = EmailAddress.objects.get_or_create( + address=from_)[0] + self.EMAIL_ADDR_CACHE[from_] = email_addr + + if not email_addr.real_name and real_name: + email_addr.real_name = real_name[:64] + email_addr.save() + + subject = email_msg.get_subject() + + email = Message.objects.create( + message_id=email_msg.get('Message-ID'), + from_address=email_addr, + subject=subject, + subject_clean=self.RE_SUBJECT_CLEAN.sub('', subject).strip(), + body=email_msg.get_body(), + received_time=email_msg.get_received_datetime(), + ) + email.thread = self.get_thread(email, mailinglist) + email.save() + + @transaction.commit_manually + def import_emails(self, archives_path, all, exclude_lists=None): + """Get emails from the filesystem from the `archives_path` + and store them into the database. If `all` is set to True all + the filesystem storage will be imported otherwise the + importation will resume from the last message previously + imported. The lists set in `exclude_lists` won't be imported. + + """ + + count = 0 + email_generator = self.get_emails(archives_path, all, exclude_lists) + for mailinglist_name, msg, index in email_generator: + try: + self.save_email(mailinglist_name, msg, index) + except: + # This anti-pattern is needed to avoid the transations to + # get stuck in case of errors. + transaction.rollback() + raise + + count += 1 + if count % 1000 == 0: + transaction.commit() + + transaction.commit() + + def handle(self, *args, **options): + """Main command method.""" + + lock_file = '/var/lock/colab/import_emails.lock' + + # Already running, so quit + if os.path.exists(lock_file): + self.log(("This script is already running. (If your are sure it's " + "not please delete the lock file in %s')") % lock_file) + sys.exit(0) + + if not os.path.exists(os.path.dirname(lock_file)): + os.mkdir(os.path.dirname(lock_file), 0755) + + run_lock = file(lock_file, 'w') + run_lock.close() + + archives_path = options.get('archives_path') + self.log('Using archives_path `%s`' % self.default_archives_path) + + if not os.path.exists(archives_path): + raise CommandError('archives_path (%s) does not exist' % + archives_path) + + self.import_emails(archives_path, + options.get('all'), options.get('exclude_lists')) + + os.remove(lock_file) + diff --git a/src/super_archives/management/commands/message.py b/src/super_archives/management/commands/message.py new file mode 100644 index 0000000..dc3b48a --- /dev/null +++ b/src/super_archives/management/commands/message.py @@ -0,0 +1,101 @@ + +import re +import pytz +import email +import codecs +import mailbox +import datetime +from email.iterators import typed_subpart_iterator + +import chardet + + +def get_charset(message, default='ASCII'): + """Get the message charset""" + + charset = message.get_content_charset() + + if not charset: + charset = message.get_charset() + + if not charset: + charset = default + + try: + codecs.lookup(charset) + except LookupError: + charset = default + + return charset + + +class Message(mailbox.mboxMessage): + + RECEIVED_DELIMITER = re.compile('\n|;') + + def get_subject(self): + subject = email.header.decode_header(self['Subject']) + + if isinstance(subject, list): + new_subject = u'' + for text_part, encoding in subject: + if not encoding: + encoding = get_charset(self) + + try: + new_subject += unicode(text_part, encoding) + except (UnicodeDecodeError, LookupError): + try: + new_subject += unicode(text_part, get_charset(self)) + except (UnicodeDecodeError, LookupError): + encoding = chardet.detect(text_part)['encoding'] + new_subject += unicode(text_part, encoding) + + return ''.join(new_subject) + + def get_body(self): + """Get the body of the email message""" + + if self.is_multipart(): + #get the plain text version only + text_parts = [part + for part in typed_subpart_iterator(self, + 'text', + 'plain')] + body = [] + for part in text_parts: + charset = get_charset(part, get_charset(self)) + body.append(unicode(part.get_payload(decode=True), + charset, + "replace")) + + return u"\n".join(body).strip() + + else: # if it is not multipart, the payload will be a string + # representing the message body + body = unicode(self.get_payload(decode=True), + get_charset(self), + "replace") + return body.strip() + + def get_received_datetime(self): + # The time received should always be the last element + # in the `Received` attribute from the message headers + received_header = self.RECEIVED_DELIMITER.split(self['Received']) + received_time_header = received_header[-1].strip() + + date_tuple = email.utils.parsedate_tz(received_time_header) + utc_timestamp = email.utils.mktime_tz(date_tuple) + utc_datetime = datetime.datetime.fromtimestamp(utc_timestamp, + pytz.utc) + + return utc_datetime + + def get_from_addr(self): + real_name_raw, from_ = email.utils.parseaddr(self['From']) + real_name_str, encoding = email.header.decode_header(real_name_raw)[0] + if not encoding: + encoding = 'ascii' + + real_name = unicode(real_name_str, encoding, errors='replace') + return real_name, from_ diff --git a/src/super_archives/migrations/0001_initial.py b/src/super_archives/migrations/0001_initial.py new file mode 100644 index 0000000..cbf3c99 --- /dev/null +++ b/src/super_archives/migrations/0001_initial.py @@ -0,0 +1,255 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding model 'PageHit' + db.create_table('super_archives_pagehit', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('url_path', self.gf('django.db.models.fields.CharField')(unique=True, max_length=2048, db_index=True)), + ('hit_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + )) + db.send_create_signal('super_archives', ['PageHit']) + + # Adding model 'EmailAddress' + db.create_table('super_archives_emailaddress', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='emails', null=True, to=orm['auth.User'])), + ('address', self.gf('django.db.models.fields.EmailField')(unique=True, max_length=75)), + ('real_name', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)), + ('md5', self.gf('django.db.models.fields.CharField')(max_length=32, null=True)), + )) + db.send_create_signal('super_archives', ['EmailAddress']) + + # Adding model 'UserProfile' + db.create_table('super_archives_userprofile', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)), + ('institution', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), + ('role', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), + ('twitter', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), + ('facebook', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), + ('google_talk', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True)), + ('webpage', self.gf('django.db.models.fields.CharField')(max_length=256)), + )) + db.send_create_signal('super_archives', ['UserProfile']) + + # Adding model 'MailingList' + db.create_table('super_archives_mailinglist', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=80)), + ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)), + ('description', self.gf('django.db.models.fields.TextField')()), + ('logo', self.gf('django.db.models.fields.files.FileField')(max_length=100)), + ('last_imported_index', self.gf('django.db.models.fields.IntegerField')(default=0)), + )) + db.send_create_signal('super_archives', ['MailingList']) + + # Adding model 'MailingListMembership' + db.create_table('super_archives_mailinglistmembership', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), + )) + db.send_create_signal('super_archives', ['MailingListMembership']) + + # Adding model 'Thread' + db.create_table('super_archives_thread', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('subject_token', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), + ('latest_message', self.gf('django.db.models.fields.related.OneToOneField')(related_name='+', unique=True, null=True, to=orm['super_archives.Message'])), + )) + db.send_create_signal('super_archives', ['Thread']) + + # Adding unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] + db.create_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) + + # Adding model 'Vote' + db.create_table('super_archives_vote', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), + )) + db.send_create_signal('super_archives', ['Vote']) + + # Adding unique constraint on 'Vote', fields ['user', 'message'] + db.create_unique('super_archives_vote', ['user_id', 'message_id']) + + # Adding model 'Message' + db.create_table('super_archives_message', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('from_address', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.EmailAddress'])), + ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), + ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Thread'], null=True)), + ('subject', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('subject_clean', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('body', self.gf('django.db.models.fields.TextField')(default='')), + ('received_time', self.gf('django.db.models.fields.DateTimeField')()), + ('message_id', self.gf('django.db.models.fields.CharField')(max_length=512)), + )) + db.send_create_signal('super_archives', ['Message']) + + # Adding model 'MessageMetadata' + db.create_table('super_archives_messagemetadata', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('Message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('value', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal('super_archives', ['MessageMetadata']) + + + def backwards(self, orm): + + # Removing unique constraint on 'Vote', fields ['user', 'message'] + db.delete_unique('super_archives_vote', ['user_id', 'message_id']) + + # Removing unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] + db.delete_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) + + # Deleting model 'PageHit' + db.delete_table('super_archives_pagehit') + + # Deleting model 'EmailAddress' + db.delete_table('super_archives_emailaddress') + + # Deleting model 'UserProfile' + db.delete_table('super_archives_userprofile') + + # Deleting model 'MailingList' + db.delete_table('super_archives_mailinglist') + + # Deleting model 'MailingListMembership' + db.delete_table('super_archives_mailinglistmembership') + + # Deleting model 'Thread' + db.delete_table('super_archives_thread') + + # Deleting model 'Vote' + db.delete_table('super_archives_vote') + + # Deleting model 'Message' + db.delete_table('super_archives_message') + + # Deleting model 'MessageMetadata' + db.delete_table('super_archives_messagemetadata') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py b/src/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py new file mode 100644 index 0000000..a47db14 --- /dev/null +++ b/src/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py @@ -0,0 +1,133 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'UserProfile.verification_hash' + db.add_column('super_archives_userprofile', 'verification_hash', self.gf('django.db.models.fields.CharField')(max_length=32, null=True), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'UserProfile.verification_hash' + db.delete_column('super_archives_userprofile', 'verification_hash') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0003_auto__add_field_thread_score.py b/src/super_archives/migrations/0003_auto__add_field_thread_score.py new file mode 100644 index 0000000..afb9069 --- /dev/null +++ b/src/super_archives/migrations/0003_auto__add_field_thread_score.py @@ -0,0 +1,134 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Thread.score' + db.add_column('super_archives_thread', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Thread.score' + db.delete_column('super_archives_thread', 'score') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0004_auto__add_field_vote_created.py b/src/super_archives/migrations/0004_auto__add_field_vote_created.py new file mode 100644 index 0000000..9be9e33 --- /dev/null +++ b/src/super_archives/migrations/0004_auto__add_field_vote_created.py @@ -0,0 +1,135 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Vote.created' + db.add_column('super_archives_vote', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2012, 1, 19, 18, 8, 46, 813949), blank=True), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Vote.created' + db.delete_column('super_archives_vote', 'created') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py b/src/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py new file mode 100644 index 0000000..1fd669d --- /dev/null +++ b/src/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py @@ -0,0 +1,143 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Message.spam' + db.add_column('super_archives_message', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Thread.spam' + db.add_column('super_archives_thread', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Message.spam' + db.delete_column('super_archives_message', 'spam') + + # Deleting field 'Thread.spam' + db.delete_column('super_archives_thread', 'spam') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0006_auto.py b/src/super_archives/migrations/0006_auto.py new file mode 100644 index 0000000..bfbad99 --- /dev/null +++ b/src/super_archives/migrations/0006_auto.py @@ -0,0 +1,143 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding index on 'Message', fields ['subject_clean'] + db.create_index('super_archives_message', ['subject_clean']) + + # Adding index on 'Message', fields ['subject'] + db.create_index('super_archives_message', ['subject']) + + + def backwards(self, orm): + + # Removing index on 'Message', fields ['subject'] + db.delete_index('super_archives_message', ['subject']) + + # Removing index on 'Message', fields ['subject_clean'] + db.delete_index('super_archives_message', ['subject_clean']) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0007_auto.py b/src/super_archives/migrations/0007_auto.py new file mode 100644 index 0000000..e8fedca --- /dev/null +++ b/src/super_archives/migrations/0007_auto.py @@ -0,0 +1,137 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding index on 'EmailAddress', fields ['real_name'] + db.create_index('super_archives_emailaddress', ['real_name']) + + + def backwards(self, orm): + + # Removing index on 'EmailAddress', fields ['real_name'] + db.delete_index('super_archives_emailaddress', ['real_name']) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0008_add_mailinglist_name_to_url.py b/src/super_archives/migrations/0008_add_mailinglist_name_to_url.py new file mode 100644 index 0000000..a5193f4 --- /dev/null +++ b/src/super_archives/migrations/0008_add_mailinglist_name_to_url.py @@ -0,0 +1,142 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + page_hits = orm.PageHit.objects.all() + for page_hit in page_hits: + if page_hit.url_path.startswith('/archives/thread/'): + token = page_hit.url_path.split('/')[-1] + threads = orm.Thread.objects.filter(subject_token=token) + if not len(threads): continue + thread = threads[0] + new_url = '/archives/thread/%s/%s' % (thread.mailinglist.name, + thread.subject_token) + page_hit.url_path = new_url + page_hit.save() + + + def backwards(self, orm): + raise RuntimeError("Cannot reverse this migration.") + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0009_auto__del_field_message_mailinglist.py b/src/super_archives/migrations/0009_auto__del_field_message_mailinglist.py new file mode 100644 index 0000000..f68774e --- /dev/null +++ b/src/super_archives/migrations/0009_auto__del_field_message_mailinglist.py @@ -0,0 +1,136 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Deleting field 'Message.mailinglist' + db.delete_column('super_archives_message', 'mailinglist_id') + + + def backwards(self, orm): + + # User chose to not deal with backwards NULL issues for 'Message.mailinglist' + raise RuntimeError("Cannot reverse this migration. 'Message.mailinglist' and its values cannot be restored.") + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py b/src/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py new file mode 100644 index 0000000..ef2efb4 --- /dev/null +++ b/src/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py @@ -0,0 +1,136 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding unique constraint on 'Message', fields ['message_id', 'thread'] + db.create_unique('super_archives_message', ['message_id', 'thread_id']) + + + def backwards(self, orm): + + # Removing unique constraint on 'Message', fields ['message_id', 'thread'] + db.delete_unique('super_archives_message', ['message_id', 'thread_id']) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'super_archives.emailaddress': { + 'Meta': {'object_name': 'EmailAddress'}, + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'super_archives.mailinglist': { + 'Meta': {'object_name': 'MailingList'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'super_archives.mailinglistmembership': { + 'Meta': {'object_name': 'MailingListMembership'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'super_archives.message': { + 'Meta': {'unique_together': "(('thread', 'message_id'),)", 'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) + }, + 'super_archives.messagemetadata': { + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'Meta': {'object_name': 'MessageMetadata'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'super_archives.pagehit': { + 'Meta': {'object_name': 'PageHit'}, + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) + }, + 'super_archives.thread': { + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'super_archives.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'super_archives.vote': { + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + } + } + + complete_apps = ['super_archives'] diff --git a/src/super_archives/migrations/__init__.py b/src/super_archives/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/super_archives/migrations/__init__.py diff --git a/src/super_archives/models.py b/src/super_archives/models.py new file mode 100644 index 0000000..3b0448b --- /dev/null +++ b/src/super_archives/models.py @@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- + +import datetime +from hashlib import md5 + +from django.db import models +from django.conf import settings +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse, NoReverseMatch +from django.utils.translation import ugettext_lazy as _ + + +class NotSpamManager(models.Manager): + """Only return objects which are not marked as spam.""" + + def get_query_set(self): + return super(NotSpamManager, self).get_query_set().exclude(spam=True) + + +class PageHit(models.Model): + url_path = models.CharField(max_length=2048, unique=True, db_index=True) + hit_count = models.IntegerField(default=0) + + +class EmailAddress(models.Model): + user = models.ForeignKey(User, null=True, related_name='emails') + address = models.EmailField(unique=True) + real_name = models.CharField(max_length=64, blank=True, db_index=True) + md5 = models.CharField(max_length=32, null=True) + + def save(self, *args, **kwargs): + self.md5 = md5(self.address).hexdigest() + super(EmailAddress, self).save(*args, **kwargs) + + def get_full_name(self): + if self.user and self.user.get_full_name(): + return self.user.get_full_name() + elif self.user and self.username: + return self.username + elif self.real_name: + return self.real_name + + def get_profile_link(self): + if self.user: + return reverse('user_profile', args=[self.user.username]) + else: + return reverse('colab.views.userprofile.by_emailhash', + args=[self.md5]) + + def __unicode__(self): + return '"%s" <%s>' % (self.get_full_name(), self.address) + + +class UserProfile(models.Model): + + user = models.OneToOneField(User, unique=True) + institution = models.CharField(max_length=128, null=True) + role = models.CharField(max_length=128, null=True) + twitter = models.CharField(max_length=128, null=True) + facebook = models.CharField(max_length=128, null=True) + google_talk = models.EmailField(null=True) + webpage = models.CharField(max_length=256) + verification_hash = models.CharField(max_length=32, null=True) + + class Meta: + verbose_name = _(u"User Profile") + verbose_name_plural = _(u"Users Profiles") + + def __unicode__(self): + return '%s (%s)' % (self.user.get_full_name(), self.user.username) + +# This does the same the same than related_name argument but it also creates +# a profile in the case it doesn't exist yet. +User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0]) + + +class MailingList(models.Model): + name = models.CharField(max_length=80) + email = models.EmailField() + description = models.TextField() + logo = models.FileField(upload_to='list_logo') #TODO + last_imported_index = models.IntegerField(default=0) + + def __unicode__(self): + return self.name + + +class MailingListMembership(models.Model): + user = models.ForeignKey(User) + mailinglist = models.ForeignKey(MailingList) + + def __unicode__(self): + return '%s on %s' % (self.user.username, self.mailinglist.name) + + +class Thread(models.Model): + + subject_token = models.CharField(max_length=512) + mailinglist = models.ForeignKey(MailingList, + verbose_name=_(u"Mailing List"), + help_text=_(u"The Mailing List where is the thread")) + latest_message = models.OneToOneField('Message', null=True, + related_name='+', + verbose_name=_(u"Latest message"), + help_text=_(u"Latest message posted")) + score = models.IntegerField(default=0, verbose_name=_(u"Score"), help_text=_(u"Thread score")) + spam = models.BooleanField(default=False) + + all_objects = models.Manager() + objects = NotSpamManager() + + class Meta: + verbose_name = _(u"Thread") + verbose_name_plural = _(u"Threads") + unique_together = ('subject_token', 'mailinglist') + + def __unicode__(self): + return '%s - %s (%s)' % (self.id, + self.subject_token, + self.message_set.count()) + + def update_score(self): + """Update the relevance score for this thread. + + The score is calculated with the following variables: + + * vote_weight: 100 - (minus) 1 for each 3 days since + voted with minimum of 5. + * replies_weight: 300 - (minus) 1 for each 3 days since + replied with minimum of 5. + * page_view_weight: 10. + + * vote_score: sum(vote_weight) + * replies_score: sum(replies_weight) + * page_view_score: sum(page_view_weight) + + * score = (vote_score + replies_score + page_view_score) // 10 + with minimum of 0 and maximum of 5000 + + """ + + if not self.subject_token: + return + + # Save this pseudo now to avoid calling the + # function N times in the loops below + now = datetime.datetime.now() + days_ago = lambda date: (now - date).days + get_score = lambda weight, created: \ + max(weight - (days_ago(created) // 3), 5) + + vote_score = 0 + replies_score = 0 + for msg in self.message_set.all(): + # Calculate replies_score + replies_score += get_score(300, msg.received_time) + + # Calculate vote_score + for vote in msg.vote_set.all(): + vote_score += get_score(100, vote.created) + + # Calculate page_view_score + try: + url = reverse('thread_view', args=[self.mailinglist.name, + self.subject_token]) + pagehit = PageHit.objects.get(url_path=url) + page_view_score = pagehit.hit_count * 10 + except (NoReverseMatch, PageHit.DoesNotExist): + page_view_score = 0 + + self.score = (page_view_score + vote_score + replies_score) // 10 + self.save() + + +class Vote(models.Model): + user = models.ForeignKey(User) + message = models.ForeignKey('Message') + created = models.DateTimeField(auto_now_add=True) + + class Meta: + unique_together = ('user', 'message') + + def __unicode__(self): + return 'Vote on %s by %s' % (self.Message.id, + self.user.username) + + +class Message(models.Model): + + from_address = models.ForeignKey(EmailAddress, db_index=True) + thread = models.ForeignKey(Thread, null=True, db_index=True) + # RFC 2822 recommends to use 78 chars + CRLF (so 80 chars) for + # the max_length of a subject but most of implementations + # goes for 256. We use 512 just in case. + subject = models.CharField(max_length=512, db_index=True, + verbose_name=_(u"Subject"), + help_text=_(u"Please enter a message subject")) + subject_clean = models.CharField(max_length=512, db_index=True) + body = models.TextField(default='', + verbose_name=_(u"Message body"), + help_text=_(u"Please enter a message body")) + received_time = models.DateTimeField() + message_id = models.CharField(max_length=512) + spam = models.BooleanField(default=False) + + all_objects = models.Manager() + objects = NotSpamManager() + + class Meta: + verbose_name = _(u"Message") + verbose_name_plural = _(u"Messages") + unique_together = ('thread', 'message_id') + + def __unicode__(self): + return '(%s) %s: %s' % (self.id, + self.from_address.get_full_name(), + self.subject_clean) + + @property + def mailinglist(self): + if not self.thread or not self.thread.mailinglist: + return None + + return self.thread.mailinglist + + + def vote_list(self): + """Return a list of user that voted in this message.""" + + return [vote.user for vote in self.vote_set.all()] + + def votes_count(self): + return len(self.vote_list()) + + def vote(self, user): + Vote.objects.create( + message=self, + user=user + ) + + def unvote(self, user): + Vote.objects.get( + message=self, + user=user + ).delete() + + @property + def url(self): + """Shortcut to get thread url""" + return reverse('thread_view', args=[self.mailinglist.name, + self.thread.subject_token]) + + @property + def Description(self): + """Alias to self.body""" + return self.body + + @property + def Title(self): + """Alias to self.subject_clean""" + return self.subject_clean + + @property + def modified(self): + """Alias to self.modified""" + return self.received_time + + +class MessageMetadata(models.Model): + Message = models.ForeignKey(Message) + # Same problem here than on subjects. Read comment above + # on Message.subject + name = models.CharField(max_length=512) + value = models.TextField() + + def __unicode__(self): + return 'Email Message Id: %s - %s: %s' % (self.Message.id, + self.name, self.value) + diff --git a/src/super_archives/queries.py b/src/super_archives/queries.py new file mode 100644 index 0000000..2ef00ff --- /dev/null +++ b/src/super_archives/queries.py @@ -0,0 +1,54 @@ + +from django.core.exceptions import ObjectDoesNotExist +from colab.super_archives.models import Thread, Vote, Message, PageHit + + +def get_messages_by_date(): + return Message.objects.order_by('received_time') + + +def get_messages_by_voted(): + """Query for the most voted messages sorting by the sum of + voted and after by date.""" + + sql = """ + SELECT + count(sav.id) + FROM + super_archives_vote AS sav + WHERE + super_archives_message.id = sav.message_id + """ + messages = Message.objects.extra( + select={ + 'vote_count': sql, + } + ) + return messages.order_by('-vote_count', 'received_time') + + +def get_first_message_in_thread(mailinglist, thread_token): + query = get_messages_by_date() + query = query.filter(thread__mailinglist__name=mailinglist) + try: + query = query.filter(thread__subject_token=thread_token)[0] + except IndexError: + raise ObjectDoesNotExist + return query + + +def get_latest_threads(): + return Thread.objects.order_by('-latest_message__received_time') + + +def get_hottest_threads(): + return Thread.objects.order_by('-score', '-latest_message__received_time') + + +def get_page_hits(path_info): + pagehit = PageHit.objects.filter(url_path=path_info) + + if pagehit: + return pagehit[0].hit_count + return 0 + diff --git a/src/super_archives/templates/message-list.html b/src/super_archives/templates/message-list.html new file mode 100644 index 0000000..7e4ce4c --- /dev/null +++ b/src/super_archives/templates/message-list.html @@ -0,0 +1,68 @@ +{% extends "base.html" %} +{% load i18n %} +{% load append_to_get %} +{% block main-content %} +
    +

    {% trans "Discussions" %}

    +
    + +
    +

    {% trans "Filters" %}

    + +

    {% trans "Sort by" %}

    + + +
    + +

    {% trans "Lists" %}

    + +
    + +
    +
      + {% for thread in threads.object_list %} + {% include "message-preview.html" with doc=thread.latest_message %} + {% empty %} +

      + + {% trans "No discussion found" %} + + {% endfor %} +
    +
    + + {% if n_results %} + + {% endif %} + +
    +
    + +{% endblock %} diff --git a/src/super_archives/templates/message-preview.html b/src/super_archives/templates/message-preview.html new file mode 100644 index 0000000..1010519 --- /dev/null +++ b/src/super_archives/templates/message-preview.html @@ -0,0 +1,51 @@ +{% load i18n %} + +{% if doc.Title %} +
  • + {% if doc.Type %} + {{ doc.Type }} + {% else %} + thread + {% endif %} + + {% if doc.mailinglist %} + + {{ doc.mailinglist }} + + {% endif %} + + + + {{ doc.Title }} + + + + - + {{ doc.Description|striptags }} + + +
    + + {% trans "by" %} + {% if doc.from_address.get_full_name %} + + {{ doc.from_address.get_full_name }} + + {% else %} + {% firstof doc.last_author doc.Creator _("anônimo") %} + {% endif %} + + + + {{ doc.modified|timesince }} + {% trans "back" %} + +
    +
  • +{% endif %} diff --git a/src/super_archives/templates/message-thread.html b/src/super_archives/templates/message-thread.html new file mode 100644 index 0000000..e9ee583 --- /dev/null +++ b/src/super_archives/templates/message-thread.html @@ -0,0 +1,77 @@ +{% extends "base.html" %} +{% load i18n %} +{% load append_to_get %} +{% block main-content %} +
    + +

    {{ first_msg.subject_clean }}

    +
    +
    + +
    +
    +

    {% trans "Order by" %}:

    + + +
    + +

    {% trans "Statistics:" %}

    + +
      +
    • {% trans "started at" %} +

      {{ first_msg.received_time|timesince }} {% trans "back" %}

      +
    • +
    • {% trans "viewed" %} +

      {{ pagehits }} {% trans "times" %}

      +
    • +
    • {% trans "answered" %} +

      {{ emails|length }} {% trans "times" %}

      +
    • +
    • {% trans "voted" %} +

      {{ total_votes }} {% trans "times" %}

      +
    • +
    + +
    + + + +{% endblock %} diff --git a/src/super_archives/templatetags/__init__.py b/src/super_archives/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/super_archives/templatetags/__init__.py diff --git a/src/super_archives/templatetags/append_to_get.py b/src/super_archives/templatetags/append_to_get.py new file mode 100644 index 0000000..7dfbcb4 --- /dev/null +++ b/src/super_archives/templatetags/append_to_get.py @@ -0,0 +1,56 @@ + +import urllib +from django import template + +register = template.Library() + +""" +Decorator to facilitate template tag creation +""" +def easy_tag(func): + """deal with the repetitive parts of parsing template tags""" + def inner(parser, token): + #print token + try: + return func(*token.split_contents()) + except TypeError: + raise template.TemplateSyntaxError('Bad arguments for tag "%s"' % + token.split_contents()[0]) + inner.__name__ = func.__name__ + inner.__doc__ = inner.__doc__ + return inner + + +class AppendGetNode(template.Node): + def __init__(self, dict): + self.dict_pairs = {} + for pair in dict.split(','): + pair = pair.split('=') + self.dict_pairs[pair[0]] = template.Variable(pair[1]) + + def render(self, context): + get = context['request'].GET.copy() + + for key in self.dict_pairs: + get[key] = self.dict_pairs[key].resolve(context) + + path = context['request'].META['PATH_INFO'] + + if len(get): + # Convert all unicode objects in the get dict to + # str (utf-8 encoded) + get_utf_encoded = {} + for (key, value) in get.items(): + if isinstance(value, unicode): + value = value.encode('utf-8') + get_utf_encoded.update({key: value}) + get_utf_encoded = dict(get_utf_encoded) + + path = '?' + urllib.urlencode(get_utf_encoded) + + return path + +@register.tag() +@easy_tag +def append_to_get(_tag_name, dict): + return AppendGetNode(dict) diff --git a/src/super_archives/templatetags/form_field.py b/src/super_archives/templatetags/form_field.py new file mode 100644 index 0000000..e71dbd7 --- /dev/null +++ b/src/super_archives/templatetags/form_field.py @@ -0,0 +1,64 @@ +from django import template +from django import forms + +def render_form_field(parser, token): + variables = token.split_contents() + + if len(variables) == 2: + tag_name, form_field = variables + default_value = 'None' + elif len(variables) == 3: + tag_name, form_field, default_value = variables + else: + raise template.TemplateSyntaxError + + return RenderFormField(form_field, default_value) + + +class RenderFormField(template.Node): + + def __init__(self, form_field, default_value): + self.form_field_nocontext = template.Variable(form_field) + self.default_value_nocontext = template.Variable(default_value) + + def render(self, context): + editable = context.get('editable', True) + + class_ = u'' + errors = u'' + form_field_tag = u'' + try: + form_field = self.form_field_nocontext.resolve(context) + except template.VariableDoesNotExist: + return u'' + + if form_field.errors: + class_ += u'error' + if form_field.field.required: + class_ += u' required' + if form_field.errors: + errors = u'
    ' + form_field.errors.as_text() + + try: + default_value = self.default_value_nocontext.resolve(context) + except template.VariableDoesNotExist: + default_value = u'' + + if editable: + form_field_tag = u'
    ' + unicode(form_field) + elif isinstance(form_field.field, forms.URLField): + form_field_tag = u"""%s""" % ( + default_value, default_value) + else: + form_field_tag = default_value + + return u"""

    %s: %s %s

    """ % ( + class_, + form_field.label_tag(), + form_field_tag, + errors + ) + + +register = template.Library() +register.tag('render_form_field', render_form_field) diff --git a/src/super_archives/tests.py b/src/super_archives/tests.py new file mode 100644 index 0000000..501deb7 --- /dev/null +++ b/src/super_archives/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/src/super_archives/urls.py b/src/super_archives/urls.py new file mode 100644 index 0000000..3676ac1 --- /dev/null +++ b/src/super_archives/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import patterns, include, url + +urlpatterns = patterns('', +# url(r'thread/(?P\d+)/$', 'super_archives.views.thread', name='thread'), + url(r'thread/(?P[-\w]+)/(?P[-\w]+)$', + 'colab.super_archives.views.thread', name="thread_view"), + url(r'thread/$', + 'colab.super_archives.views.list_messages', name='thread_list') +) diff --git a/src/super_archives/validators.py b/src/super_archives/validators.py new file mode 100644 index 0000000..09049dc --- /dev/null +++ b/src/super_archives/validators.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +from django.core.exceptions import ValidationError + +class UniqueValidator(object): + + def __init__(self, model, field_name): + self.model = model + self.field_name = field_name + + def __call__(self, value): + result = self.model.objects.filter(**{self.field_name: value}) + if result: + msg = u'Já existente. Escolha outro.' + raise ValidationError(msg) diff --git a/src/super_archives/views.py b/src/super_archives/views.py new file mode 100644 index 0000000..db169ef --- /dev/null +++ b/src/super_archives/views.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +from django.http import Http404 +from django.template import RequestContext +from django.core.paginator import Paginator +from django.core.exceptions import ObjectDoesNotExist +from django.shortcuts import render_to_response, get_list_or_404 + +from colab.super_archives import queries +from colab.super_archives.models import MailingList, Thread + + +def thread(request, mailinglist, thread_token): + + try: + first_message = queries.get_first_message_in_thread(mailinglist, thread_token) + except ObjectDoesNotExist: + raise Http404 + order_by = request.GET.get('order') + if order_by == 'voted': + msgs_query = queries.get_messages_by_voted() + else: + msgs_query = queries.get_messages_by_date() + + msgs_query = msgs_query.filter(thread__subject_token=thread_token) + msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist) + emails = msgs_query.exclude(id=first_message.id) + + total_votes = first_message.votes_count() + for email in emails: + total_votes += email.votes_count() + + # Update relevance score + query = Thread.objects.filter(mailinglist__name=mailinglist) + thread = query.get(subject_token=thread_token) + thread.update_score() + + template_data = { + 'first_msg': first_message, + 'emails': [first_message] + list(emails), + 'pagehits': queries.get_page_hits(request.path_info), + 'total_votes': total_votes, + } + + return render_to_response('message-thread.html', template_data, + RequestContext(request)) + + +def list_messages(request): + + selected_list = request.GET.get('list') + + order_by = request.GET.get('order') + if order_by == 'hottest': + threads = queries.get_hottest_threads() + else: + threads = queries.get_latest_threads() + + mail_list = request.GET.get('list') + if mail_list: + threads = threads.filter(mailinglist__name=mail_list) + + paginator = Paginator(threads, 16) + try: + page = int(request.GET.get('p', '1')) + except ValueError: + page = 1 + threads = paginator.page(page) + + lists = MailingList.objects.all() + + template_data = { + 'lists': lists, + 'n_results': paginator.count, + 'threads': threads, + 'selected_list': selected_list, + 'order_by': order_by, + } + return render_to_response('message-list.html', template_data, + RequestContext(request)) -- libgit2 0.21.2