"""
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,
)