qmsk/irclogs/handlers.py
author terom
Thu, 25 Sep 2014 11:36:23 +0300
changeset 151 6b8b6e056cdb
parent 141 65c98c9e1716
permissions -rw-r--r--
qmsk.irclogs: format html logline urls with <a rel='nofollow'>
"""
    Our URL action handlers
"""

import datetime, calendar, pytz

from qmsk.web import http, template

import urls, channels, helpers
import preferences as prefs
from preferences import preferences
import config, log_search

# load templates from here
templates = template.TemplateLoader("templates",
    _helper_class   = helpers.Helpers,
    urls            = urls,
    channel_list    = config.LOG_CHANNELS,
    config          = config,
)

# return a http.Response for the given text in the given format
def _render_type (request, channel, lines, type, full_timestamps=False) :
    """
        Render the given LogLines as a http.Response in the given format, which is one of:
            html    - XXX: not supported
            txt     - Plaintext
            png     - PNG image
            rss     - RSS feed
    """

    # load related preferences
    formatter = request.prefs['formatter']

    kwargs = dict(
        full_timestamps = full_timestamps
    )

    # we can render in various modes...
    if type in ('html', None) :
        xxx

    elif type == 'txt' :
        # plaintext
        lines = formatter.format_txt(lines, **kwargs)

        # build data
        data = '\n'.join(data for line, data in lines)

        return http.Response(data, 'text/plain')

    elif type == 'png' :
        # PNG image
        png_data = formatter.format_png(lines, **kwargs)

        return http.Response(png_data, 'image/png', charset=None)
    
    elif type == 'rss' :
        # RSS feed
        rss_data = formatter.format_rss(lines, **kwargs)
        
        # XXX: fix to render as unicode?
        return http.Response(rss_data, 'application/rss+xml', charset=None)

    else :
        raise http.ResponseError("Unrecognized type: %r" % (type, ))

def _render_date (request, channel, date, lines, type, count, page, max) :
    """
        Render the given LogLines as a http.Response for channel_date
    """

    # type?
    if type :
        # special type
        return _render_type(request, channel, lines, type)
    
    else :
        # format HTML
        lines = request.prefs['formatter'].format_html(lines)

        # render
        return templates.render_to_response("channel_date",
            req             = request,
            prefs           = request.prefs,
            channel         = channel,
            date            = date,
            count           = count,
            page            = page,
            max             = max,
            lines           = lines,
            
            # for prev/next date
            date_next       = channel.source.get_next_date(date),
            date_prev       = channel.source.get_prev_date(date),
        )

@preferences.handler()
def index (request) :
    """
        The topmost index page, display a list of available channels, perhaps some general stats
    """
    
    return templates.render_to_response("index",
        req             = request,
        prefs           = request.prefs,
    )

# XXX: fix this namespace crap
@preferences.handler()
def preferences_ (request) :
    """
        Preferences editor
    """

    # POST?
    if request.is_post() :
        # update any modified preferences
        for pref in preferences.pref_list :
            # get the POST'd value, default = None
            post_value = request.get_post(pref.name, None)

            # skip non-specified values
            # XXX: this is to not clobber timezone_offset to None
            if post_value is None :
                continue

            # parse the POST'd value, None -> default
            new_value = request.prefs.parse(pref, post_value)

            # update if given and changed
            if new_value != request.prefs[pref] :
                request.prefs.set(pref.name, new_value)

    # render
    return templates.render_to_response("preferences",
        req             = request,
        prefs           = request.prefs,
        preferences     = prefs,
    )

def channel_select (request, channel) :
    """
        Redirect to the appropriate channel_view
    """
   
    return http.Redirect(urls.channel.build(request, channel=channel))

@preferences.handler(prefs.formatter)
def channel_last (request, channel, count, formatter, type=None) :
    """
        The main channel view page, displaying the most recent lines
    """

    # get latest events
    lines = channel.source.get_latest(count)
   
    # type?
    if type :
        # other format
        return _render_type(request, channel, lines, type)

    else :
        # format HTML
        lines = formatter.format_html(lines)

        # render page
        return templates.render_to_response("channel_last",
            req             = request,
            prefs           = request.prefs,
            channel         = channel,
            count           = count,
            lines           = lines,
        )

@preferences.handler(prefs.formatter, prefs.timezone, prefs.count)
def channel_link (request, channel, timestamp, formatter, timezone, count, type=None) :
    """
        Display channel_date for specific UTC timestamp
    """

    # convert timestamp to user's timezone
    timestamp = timestamp.astimezone(timezone)

    # get correct day's correct page of lines
    page, max, lines = channel.source.get_date_paged(timestamp, count)
    
    # render channel_date
    return _render_date (request, channel, timestamp, lines, type, count, page, max)

@preferences.handler(prefs.timezone)
def channel_calendar (request, channel, year, month, timezone) :
    """
        Display a list of avilable logs for some month
    """

    # current date as default
    now = timezone.localize(datetime.datetime.now())

    # target year/month
    target = timezone.localize(datetime.datetime(
        year    = year if year else now.year,
        month   = month if month else now.month,
        day     = 1
    ))

    # display calendar
    return templates.render_to_response("channel_calendar",
        req             = request,
        prefs           = request.prefs,
        channel         = channel,
        month           = target,
    )

@preferences.handler(prefs.count, prefs.timezone)
def channel_date (request, channel, date, count, timezone, page=1, type=None) :
    """
        Display all log data for the given date
    """
    
    # convert date to user's timezone
    date = timezone.localize(date)

#    print
#    print "channel_date: date=%s" % date

    # get that day's events, either paged or not
    if page :
        page, max, lines = channel.source.get_date_paged(date, count, page)
        
    else :
        lines = channel.source.get_date(date)
        max = None
   
    # render channel_date
    return _render_date (request, channel, date, lines, type, count, page, max)

@preferences.handler(prefs.formatter, prefs.count)
def channel_search (request, channel, formatter, count, q=None, nick=None, page=1, max=1, type=None) :
    """
        Display the search form for the channel for GET, or do the search for POST.
    """

    # calculate skip offset from page/count
    skip = (page - 1) * count


    if q or nick :
        # search
        try :
            lines = log_search.get_index().search_advanced(channel, q, nick, count, skip)

        except log_search.NoResultsFound :
            # no results
            lines = None

    else :
        # just display the search form
        lines = None
       

    # max?
    if max and page > max :
        max = page


    # type?
    if type and lines :
        # special type
        return _render_type(request, channel, lines, type, full_timestamps=True)
    
    else :
        # format lines to HTML if any
        if lines :
            # format
            lines = formatter.format_html(lines, full_timestamps=True)

        # render page
        return templates.render_to_response("channel_search",
            req             = request,
            prefs           = request.prefs,
            channel         = channel,
            search_query    = q,
            search_nick     = nick,
            show_results    = (q or nick),
            count           = count,
            page            = page,
            skip            = skip,
            max             = max,
            lines           = lines,
        )