view trac_plugin/MailmanPlugin.py @ 1:76549bed2e2f default tip

Started next feature, to be completed
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 10 Aug 2010 16:05:06 +0900
parents 559393b8973f
children
line wrap: on
line source

from trac.core import *
from trac.search import ISearchSource, shorten_result
from trac.mimeview.api import Mimeview
from datetime import datetime
import pytz
import SwishE

""" Mailing-list search plugin for Trac
  This plugin relies on a working swish-e index for mailing-list.
  See for example:
  http://svn.rot13.org/index.cgi/swish/view/trunk/mailman/index_mailman.pl
  (assuming the archives are generated by pipermail)
  
  It also requires the swish-e python wrapper from 
  http://py-swish-e.berlios.de/
  
  The configuration is static in this file for now, it might be moved to 
  configuration file or an admin panel later. Each mailing-list is defined by:
  ( short name, index file, label ).
"""

MailmanConfig=( 
    ( 'help', '/var/swish/indexes/help.index', 'help@freediameter.net'),
    ( 'dev',  '/var/swish/indexes/dev.index',  'dev@freediameter.net')
  )
	     
class MailmanPlugin(Component):
    """ Search mailing-list archives. """
    implements(ISearchSource, ITimelineEventProvider)

    # ISearchSource methods
    def get_search_filters(self, req):
        for MLShort, MLIndex, MLLabel in MailmanConfig:
	   yield ('ML-' + MLShort, MLLabel)

    def get_search_results(self, req, terms, filters):
	# Prepare keywords
	query = ''
	for word in terms :
		query = query + word + ' '
	query.rstrip(' ')
	tokyo_tz = pytz.timezone('Asia/Tokyo') 
	
        for MLShort, MLIndex, MLLabel in MailmanConfig:
            if 'ML-' + MLShort in filters:
	        self.env.log.debug ('Searching "%s" in index %s' % (query, MLIndex) )
		# perform the search
		handle = SwishE.new( MLIndex )
		#handle.setSort('swishrank')
		for result in handle.query(query):
		   date = datetime.fromtimestamp(result.getproperty('sent'))
		   content = Mimeview(self.env).to_unicode(result.getproperty('swishdescription'))
		   #(href, title, date, author, excerpt).
		   yield(result.getproperty('swishdocpath'),
		      result.getproperty('swishtitle') ,
		      date.replace(tzinfo=tokyo_tz),
		      # result.getproperty('name') + ' <' + result.getproperty('email') + '> in ' + MLLabel,
		      result.getproperty('name') + ' <' + result.getproperty('email') + '>',
		      shorten_result(content, query))

    # ITimelineEventProvider methods
    def get_timeline_filters(req):
        for MLShort, MLIndex, MLLabel in MailmanConfig:
	   yield ('ML-' + MLShort, MLLabel)
	   
"""
Development to be continued.
Need some way to dig into the archives without being too much resource-consuming.
For example create an index like:
cat /var/lib/mailman/archives/public/help/*.txt | grep -E '(From|Date): ' | sed -r "s/From: ([^[:space:]]*) at ([^[:space:]]*) \(([^\]*)\)$/\3 <\1@\2>/"
And update in a cron job.
"""

    def get_timeline_events(req, start, stop, filters):
        """Return a list of events in the time range given by the `start` and
        `stop` parameters.

        The `filters` parameters is a list of the enabled filters, each item
        being the name of the tuples returned by `get_timeline_filters`.

        Since 0.11, the events are `(kind, date, author, data)` tuples,
        where `kind` is a string used for categorizing the event, `date`
        is a `datetime` object, `author` is a string and `data` is some
        private data that the component will reuse when rendering the event.

        When the event has been created indirectly by another module,
        like this happens when calling `AttachmentModule.get_timeline_events()`
        the tuple can also specify explicitly the provider by returning tuples
        of the following form: `(kind, date, author, data, provider)`.

        Before version 0.11,  the events returned by this function used to
        be tuples of the form `(kind, href, title, date, author, markup)`.
        This is still supported but less flexible, as `href`, `title` and
        `markup` are not context dependent.
        """

    def render_timeline_event(context, field, event):
        """Display the title of the event in the given context.

        :param context: the rendering `Context` object that can be used for
                        rendering
        :param field: what specific part information from the event should
                      be rendered: can be the 'title', the 'description' or
                      the 'url'
        :param event: the event tuple, as returned by `get_timeline_events`
        """

  
"Welcome to our mercurial repository"