qmsk/irclogs/handlers.py
changeset 140 6db2527b67cf
parent 131 67f5d2fdca1d
child 141 65c98c9e1716
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/irclogs/handlers.py	Sun Sep 13 01:15:56 2009 +0300
@@ -0,0 +1,292 @@
+"""
+    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, page=1, max=1, type=None, t=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
+
+    # got a search query?
+    if q :
+        # attribute targets
+        targets = dict(('search_%s' % target, True) for target in t if target in ('msg', 'nick')) if t else {}
+
+        try :
+            # do search
+            lines = log_search.get_index().search_simple(channel, q, count, skip, **targets)
+
+            # update max?
+            if max and page > max :
+                max = page
+        
+        except log_search.NoResultsFound :
+            # no results
+            lines = None
+
+    else :
+        # just display the search form
+        lines = None
+ 
+    # 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_targets  = t,
+            count           = count,
+            page            = page,
+            skip            = skip,
+            max             = max,
+            lines           = lines,
+        )
+