#!/usr/bin/env python2.5
#
# This script will parse a bugs mailing list file for messages
# containing a string, sys.argv[1], in the description, body 
# of the email , of NEW bug messages.  It will then return the
# bug number and the name of the sourcepackage the bug was filed
# against.
#
# Example:
# ml-new-bug-description-search.py "notification" 2009-02
#
# Copyright 2009 Canonical, Ltd
# Author: Brian Murray <brian@ubuntu.com>
# Licensed under the GNU General Public License, version 3.

from mailbox import PortableUnixMailbox
from email import message_from_file
from email.errors import MessageParseError
from email.utils import parseaddr
from email.utils import getaddresses
from sys import argv, stderr
from operator import itemgetter
from re import search


MESSAGE_NOT_PARSEABLE = object()

def message_factory(fp):
    try:
        return message_from_file(fp)
    except MessageParseError:
        # Don't return None since that will stop the mailbox iterator.
        return MESSAGE_NOT_PARSEABLE


def show_progress(iterator, interval=100):
    """Show signs of progress."""
    for count, item in enumerate(iterator):
        if count % interval == 0:
            stderr.write('.')
        yield item


def scan_bugs(messages):
    for count, message in enumerate(messages):
        # Skip broken messages.
        if message is MESSAGE_NOT_PARSEABLE:
            continue

        # Skip replies.
        # Every message has as a reference in it for some reason
#        references = message['references']
#        if references is not None:
#            yield 'reply'
#            continue 

        # Check it's from a Launchpad bug.
        reply_to = message['reply-to']
        if reply_to is None:
            continue
        reply_name, reply_address = parseaddr(reply_to)
        reply_local_part, reply_domain = reply_address.split('@')
        if not (reply_domain == 'bugs.launchpad.net' and
                reply_local_part.isdigit()):
            continue
        bug_id = int(reply_local_part)

        subject = message.get('subject', '')
        xlpb = message.get('X-Launchpad-Bug', '')
        xlpb_list = xlpb.strip().replace("\n\t"," ").split('; ')
        xlpb_info = {}
        # this might get overwritten for each x-lp-b header
        for item in xlpb_list:
            if item:
                xlpb_info[item.split('=')[0]] = item.split('=')[1]

        if '[NEW]' in subject:
            payload = message.get_payload()
            if string in payload:
                try:
                    bugs[bug_id] = xlpb_info['sourcepackage']         
                except:
                    continue

if __name__ == '__main__':
    # Check if the amount of arguments is correct
    if len(argv) < 3 or argv[1] in ('help', '-h', '--help'):
        print 'Usage: %s <search_string> <bug_mailinglist_file> [<bug_mailinglist_file> ...]' % argv[0]
        exit(1)

    string = argv[1]

    for mailbox_file in argv[2:]:
        mailbox = PortableUnixMailbox(
            open(mailbox_file, 'rb'), message_factory)

        bugs = {}

        scan_bugs(show_progress(mailbox))
        
        for k in sorted(bugs, reverse=False):    
            print 'http://launchpad.net/bugs/%s: %s' % (k, bugs[k])
