Source

trac-userscriptservernotes-plugin / src / usernotes / notes_info.py

Full commit
import re, sys
import datetime, string
import collections

from trac.core import Component, implements, ExtensionPoint
from trac.util import Markup #, format_datetime

from trac.web import IRequestHandler
from trac.perm import IPermissionRequestor
from trac.web.chrome import INavigationContributor, ITemplateProvider
from trac.config import Option, ListOption, PathOption, BoolOption
from trac.web.chrome import add_stylesheet, add_script
from trac.util.presentation import Paginator
from trac.util import Markup, format_datetime
from trac.util.datefmt import localtz

from trac.util.translation import domain_functions
_, tag_, N_, ngettext, add_domain = domain_functions('usernotes',
    '_', 'tag_', 'N_', 'ngettext', 'add_domain')

import cgi
import logging
import string
from time import strftime, localtime
import os.path

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import create_session
from sqlalchemy.sql import desc
import sqlalchemy.sql.functions as by

from db.session import context
from db.model import NotesInfo, NotesFields

import web_nav

PACKAGE = "usernotes"
TITLE = "Userscript ServerNotes Info"

import os.path

def strU(text):
    try:
        return unicode(text)
    except:
        return unicode(str(text), "utf-8")
def str8_(text):
    if isinstance(text, unicode):
        return text.encode("utf-8")
    else:
        return str(text)
def str8(text):
    return str(text)

def esc(text):
    if not text: return u""
    return cgi.escape(strU(text))

class UserNotesInfo(Component):
    """ allows to store extra fields for a user on a remote site """
    
    implements(IRequestHandler)

    domainlist = ListOption(PACKAGE, "domain_list", "domain1, domain2",
          doc="The domains that you want to create databases for")
    
    def __init__(self):
        locale_dir = os.path.join(os.path.dirname(__file__), "locale")
        add_domain(self.env.path, locale_dir)
        
    
    """
      Determines if request should be handled by this plugin.
    """
    def match_request(self, req):
        m = re.match(r"/%s\b/%s\b(/.*)?" % (web_nav.URL, web_nav.INFO), req.path_info)
        if not m:
            return False
        domainpage = m.group(1)
        if not domainpage: domainpage = ""
        req.args["domainpage"] = domainpage
        return True

    """
      Handles display, append and delete requests on this plugin.
    """
    def process_request(self, req):
        req.perm.assert_permission(web_nav.VIEW)
        self.locale_dir = os.path.join(os.path.dirname(__file__), "locale")
        domainpage = req.args["domainpage"]
        if domainpage:
            return self.do_info(req, domainpage)
        return self.do_default(req, message="[%s]" % domainpage)

    def do_default(self, req, message=""):
        data = {}
        data["title"] = TITLE
        data["domains"] = self._domains(req)
        data["message"] = message
        data["ngettext"] = ngettext
        data["_"] = _
        add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
        add_script(req, 'common/js/trac.js')
        add_script(req, 'common/js/wikitoolbar.js')
        return ('usernotes_default.html', data, None)

    def home_url(self, req, domain): 
        return Markup(u'<div><a href="%s">[welcome]</a></div>' % self.base_url(req, domain))
    def base_url(self, req, domain):
        return req.href(web_nav.URL + "/" + web_nav.MAIL + "/" + domain)
    def do_info(self, req, path):
        username = req.authname
        m = re.match("^/([^/]+)(/.*)?", path)
        if m and username:
            add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
            add_script(req, 'common/js/trac.js')
            domain = m.group(1)
            render = m.group(2)
            base_url = self.base_url(req, domain)
            op = req.args.get("op", "")
            if not op: op = render
            # xx._scripts = _scripts
            if op == "showall":
                return self.do_showall(req, domain)
            elif op == "userlist":
                return self.do_userlist(req, domain)
            elif op == "search":
                return self.do_search(req, domain)
            elif op == "insert":
                return self.do_insert(req, domain)
            else:
                return self.do_welcome(req, domain)
        else:
            return self.do_default(req, path)
        
    def do_welcome(self, req, domain):
        data = {}
        data["domain"] = domain
        data["username"] = req.authname
        data["title"] = TITLE
        data["domains"] = self._domains(req)
        data["message"] = None
        data["ngettext"] = ngettext
        data["_"] = _
        add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
        add_script(req, 'common/js/trac.js')
        add_script(req, 'common/js/wikitoolbar.js')
        return "notes_info_index.html", data, None
        
    def _domains(self, req):
        return self.domainlist
    def do_import(self, req, sell):
        created = 0
        current_time = datetime.datetime.now()
        domain = sell._domain
        all2 = sell.all()
        session = context(self.env)
        try:
            for old in all2:
                item = NotesMail()
                item.created_by = req.authname
                item.created_on = current_time
                item.mail_domain = sell._domain 
                item.mail_from = self.to_unicode(old.mail_from)
                item.mail_user = self.to_unicode(old.mail_user)
                item.mail_date = self.to_datetime(old.mail_date)
                item.mail_date = item.mail_date + datetime.timedelta(milliseconds = created)
                item.mail_call = self.to_unicode(old.mail_call)
                item.mail_text = self.to_unicode(old.mail_text)
                item.mail_info = self.to_unicode(old.mail_info)
                item.mimetype = old.mimetype
                item.encrypted = old.encrypted
                session.add(item)
                created += 1
            session.flush()
            return self.do_default(req, "imported %s entries from %s" % (created, sell.database_name())) 
        except Exception, e:
            session.rollback()
            return self.do_default(req, "ERROR: %s" % e)
    def to_datetime(self, old):
        if not old or len(old) < 12 or old.startswith("("):
            now = datetime.datetime(2000,1,1,0,0, tzinfo = localtz) 
            return now 
        if old.startswith("1000"): 
            now = datetime.datetime(2000,1,1,0,0, tzinfo = localtz) 
            return now 
        if old[8] not in string.digits:
            old = old[0:8] + "0000"
        self.log.warning("OLD '%s'", old)
        _ = long(old)
        return datetime.datetime(int(old[0:4]),
                                     int(old[4:6]),
                                     int(old[6:8]),
                                     int(old[8:10]),
                                     int(old[10:12]), 
                                     tzinfo = localtz)
    def color_mail_user(self, mail_user):
        return u"#" + (((u"222" + strU(hash(mail_user)))[-3:]).replace(u"0", u"A").replace(u"1", u"B"))
    def do_userlist(self, req, domain):
        Item = collections.namedtuple("Item", ["mail_user", "mail_date"])
        session = context(self.env)
        q = session.query(NotesInfo.note_user, by.max(NotesInfo.modified_on))
        q = q.group_by(NotesInfo.note_user).order_by(desc(NotesInfo.modified_on))
        datalist = []
        for item in q.all():
            datalist.append(Item(*item))
        message = "found %s entries" % len(datalist)
        base_url = req.href(web_nav.URL + "/" + web_nav.MAIL + "/" + domain)
        data = {}
        data["base_url"] = base_url
        data["color_mail_user"] = self.color_mail_user
        data["localtz"] = localtz
        data["datalist"] = datalist
        data["domains"] = self._domains(req)
        data["title"] = TITLE
        data["domains"] = self._domains(req)
        data["message"] = message
        data["ngettext"] = ngettext
        data["_"] = _
        add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
        add_script(req, 'common/js/trac.js')
        add_script(req, 'common/js/wikitoolbar.js')
        return ('notes_info_userlist.html', data, None)
    def do_search(self, req, domain):
        mail_user = req.args.get("user", "")
        if not mail_user:
            self.log.info("no 'user' on search")
            req.send_response(400)
            return self.do_default(req, "no 'user' on search")
        data = {}
        data["home_url"] = self.home_url(req, domain)
        data["mail_user"] = mail_user
        session = context(self.env)
        q = session.query(NotesMail.mail_from, NotesMail.mail_user, NotesMail.mail_date,
                                NotesMail.mail_call, NotesMail.mail_text, NotesMail.mail_info,
                                NotesMail.mimetype, NotesMail.encrypted)
        q = q.filter_by(mail_user=mail_user)
        q = q.order_by(desc(NotesMail.mail_date))
        datalist = []
        for item in q.all():
            datalist.append(item)
        message = len(datalist)
        data["datalist"] = datalist
        data["markup_mail_info"] = self.markup_mail_info
        data["markup_mail_text"] = self.markup_mail_text
        data["domains"] = self._domains(req)
        data["title"] = TITLE
        data["domains"] = self._domains(req)
        data["message"] = message
        data["ngettext"] = ngettext
        data["_"] = _
        add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
        add_script(req, 'common/js/trac.js')
        add_script(req, 'common/js/wikitoolbar.js')
        return ('notes_mail_textlist.html', data, None)
    def do_showall(self, req, domain):
        data = {}
        data["home_url"] = self.home_url(req, domain)
        data["mail_user"] = "ALL"
        session = context(self.env)
        q = session.query(NotesMail.mail_from, NotesMail.mail_user, NotesMail.mail_date,
                                NotesMail.mail_call, NotesMail.mail_text, NotesMail.mail_info,
                                NotesMail.mimetype, NotesMail.encrypted)
        q = q.order_by(desc(NotesMail.mail_date))
        datalist = []
        for item in q.all():
            datalist.append(item)
        message = len(datalist)
        data["datalist"] = datalist
        data["markup_mail_info"] = self.markup_mail_info
        data["markup_mail_text"] = self.markup_mail_text
        data["domains"] = self._domains(req)
        data["title"] = TITLE
        data["domains"] = self._domains(req)
        data["message"] = message
        data["ngettext"] = ngettext
        data["_"] = _
        add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
        add_script(req, 'common/js/trac.js')
        add_script(req, 'common/js/wikitoolbar.js')
        return ('notes_mail_textlist.html', data, None)
    def markup_mail_info(self, mail_info):
        return Markup(self.span_mail_info(mail_info))
    def span_mail_info(self, mail_info):
        if not mail_info:
            return ""
        info = mail_info.strip()
        if info.startswith("w "):
            return u'<span style="color: red">%s</span>' % esc(info).replace(u"w ", u"w&nbsp;")
        elif info.startswith(u"m "):
            return u'<span style="color: blue">%s</span>' % esc(info).replace(u"m ", u"m&nbsp;")
        elif info.startswith("undefined"):
            return u'<span style="color: #DDD; font-size: xx-small">%s</span>' % esc(info)
        else:
            return '<span style="font-size: xx-small">%s</span>' % esc(info)
    def markup_mail_text(self, mail_text):
        return Markup(self.span_mail_text(mail_text))
    def span_mail_text(self, mail_text):
        if not mail_text:
            return ""
        return u"<p>" + esc(mail_text).strip().replace(u"\n\n", u"</p><p>").replace(u"\n", u"<br />") + u"</p>"
    def do_insert(self, req, domain):
        mail_from = req.args.get("from", "")
        mail_user = req.args.get("user", "")
        import parsedate
        mail_date = parsedate.parse_datetime(req.args.get("date", ""))
        mail_call = req.args.get("call", "")
        mail_text = req.args.get("text", "")
        mail_info = req.args.get("info", "")
        mail_body = req.args.get("body", "")
        mimetype = req.args.get("mimetype", "")
        encrypted = req.args.get("encrypted", "")
        if mail_body:
            mimetype = "text/html"
            mail_text = mail_body            
        if not mail_date:
            req.send_response(400)
            message = u"datetime %s text not understood" % (req.args.get("date", ""))
            self.log.info(message)
            return self.do_default(req, message)
        if not mail_user:
            req.send_response(400)
            message = u"no 'user' on insert %s " % mail_date
            self.log.info(message)
            return self.do_default(req, message)
        session = context(self.env)
        status = ""
        try:
            self.log.info("going to insert %s", mail_user)
            q = session.query(NotesMail)
            q = q.filter_by(mail_from=mail_from, mail_user=mail_user, mail_date=mail_date)
            result = q.count()
            if result > 0:
                self.log.info(u"entry does already exist for %s", strU(mail_user))
                status = u'<div class="status"><span class="statushead">OOPS EXISTS</span>: entry does already exist %s</div>' % esc(result)
            else:
                self.log.info("running sql for %s", mail_user)
                mail = NotesMail(mail_from=mail_from, mail_user=mail_user, mail_date=mail_date,
                                 mail_call=mail_call, mail_text=mail_text, mail_info=mail_info,
                                 mimetype=mimetype, encrypted=encrypted,
                                 mail_domain = domain, 
                                 created_by = req.authname,
                                 created_on = datetime.datetime.now())
                session.add(mail)
                status = u'<div class="status"><span class="statushead">OK SAVED</span>: entry was saved just fine</div>'
            session.flush()
            data = {}
            data["title"] = TITLE
            data["domains"] = self._domains(req)
            data["message"] = Markup(status)
            data["body"] = self.markup_mail_text(mail_text)
            data["ngettext"] = ngettext
            data["_"] = _
            add_stylesheet(req, PACKAGE + '/css/userscriptservernotes.css')
            add_script(req, 'common/js/trac.js')
            add_script(req, 'common/js/wikitoolbar.js')
            return ('notes_mail_insert.html', data, None)
        except Exception, e:
            import traceback
            message = u"FAIL:(12) " + strU(e) + " @ " + traceback.format_exc()
            self.log.error(u"OOPS " + strU(e) + " @ " + traceback.format_exc())
            return self.do_default(req, message)