Commit 4b27b72a authored by Julian Rother's avatar Julian Rother
Browse files

Implemented atom feeds

parent bff90c37
......@@ -25,7 +25,7 @@ def dict_factory(cursor, row):
return d
# From sqlite3 module, but with error catching
def sqlite_convert_timestamp(val):
def convert_timestamp(val):
datepart, timepart = val.split(b" ")
year, month, day = map(int, datepart.split(b"-"))
......@@ -36,12 +36,12 @@ def sqlite_convert_timestamp(val):
microseconds = 0
val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds)
except ValueError:
val = None
return val
sqlite3.register_converter('datetime', sqlite_convert_timestamp)
sqlite3.register_converter('timestamp', sqlite_convert_timestamp)
sqlite3.register_converter('datetime', convert_timestamp)
sqlite3.register_converter('timestamp', convert_timestamp)
def query(operation, *params):
if config['DB_ENGINE'] == 'mysql':
from server import *
def gen_atomid(s):
return 'urn:md5:'+hashlib.md5(s.encode('utf-8')).hexdigest().upper()
def fixdate(d):
if not isinstance(d, datetime):
return datetime(MINYEAR, 1, 1)
return d
@handle_errors(None, 'Diese Veranstaltung existiert nicht!', 400, IndexError)
def feed(handle=None):
id = None
course = {'id': None, 'title': 'Neueste Videos', 'time_created': None, 'time_updated': None}
course['atomid'] = gen_atomid('FROM videos SELECT *')
if handle:
course = query('SELECT * FROM courses WHERE handle = ? AND visible', handle)[0]
course['atomid'] = gen_atomid('Video AG, courses['+str(course['id'])+']: '+course['handle'])
id = course['id']
entries = query('''
SELECT lectures.*, videos.file_size, videos.path, AS video_id, videos.hash,
MAX(videos.time_created, videos.time_updated, lectures.time_created, lectures.time_updated) as updated,
courses.title AS course_title, courses.handle AS course_handle, courses.semester, courses.organizer AS course_organizer, courses.short as course_short,
formats.description AS format_description, formats.player_prio
FROM lectures
JOIN courses ON ( = lectures.course_id)
JOIN videos ON ( = videos.lecture_id)
JOIN formats ON ( = videos.video_format)
WHERE (? IS NULL) OR course_id = ? AND courses.visible AND lectures.visible AND videos.visible
ORDER BY time DESC, player_prio
LIMIT 100''',
course['id'], course['id'])
updated = max(course['time_updated'], course['time_created'], key=fixdate)
for entry in entries:
entry['updated'] = convert_timestamp(entry['updated'].encode('utf-8'))
if len(entry['hash']) != 32:
entry['atomid'] = gen_atomid('Video AG, videos['+str(entry['video_id'])+']')
entry['atomid'] = 'urn:md5:'+(entry['hash'].upper())
updated = max(updated, entry['updated'], key=fixdate)
course['updated'] = updated
return Response(render_template('feed.atom', course=course, entries=entries), 200, {'Content-Type': 'application/atom+xml'})
def feed_courses():
courses = query('SELECT *, MAX(time_created, time_updated) AS updated FROM courses WHERE visible AND listed ORDER BY time_created DESC LIMIT 100')
atomid = gen_atomid('Video AG, courses')
updated = None
for course in courses:
course['updated'] = convert_timestamp(course['updated'].encode('utf-8'))
course['atomid'] = gen_atomid('Video AG, courses['+str(course['id'])+']: '+course['handle'])
updated = max(updated, course['updated'], key=fixdate)
return Response(render_template('feed_courses.atom', updated=updated, atomid=atomid, courses=courses), 200, {'Content-Type': 'application/atom+xml'})
from flask import Flask, g, request, url_for, redirect, session, render_template, flash, Response
from werkzeug.routing import Rule
from functools import wraps
from datetime import date, timedelta, datetime, time
from datetime import date, timedelta, datetime, time, MINYEAR
import threading
import os
import hashlib
app = Flask(__name__)
......@@ -36,7 +37,7 @@ config.from_pyfile('', silent=True)
if config['DEBUG']:
app.jinja_env.auto_reload = True
from db import query, searchquery, ldapauth, ldapget
from db import query, searchquery, ldapauth, ldapget, convert_timestamp
mod_endpoints = []
......@@ -78,7 +79,10 @@ def handle_errors(endpoint, text, code, *errors, **epargs):
return func(*args, **kwargs)
except errors:
return render_endpoint(endpoint, text, **epargs), code
if endpoint:
return render_endpoint(endpoint, text, **epargs), code
return text, code
return decorator
return wrapper
......@@ -86,6 +90,18 @@ def handle_errors(endpoint, text, code, *errors, **epargs):
def handle_not_found(e):
return render_endpoint('index', 'Diese Seite existiert nicht!'), 404
def human_semester(s):
return s
def human_date(d):
return d.strftime('%x')
def rfc3339(d):
return d.strftime('%Y-%m-%dT%H:%M:%S+02:00')
@register_navbar('Home', icon='home')
def index():
......@@ -212,7 +228,6 @@ def edit():
return "OK", 200
def auth(): # For use with nginx auth_request
if 'X-Original-Uri' not in request.headers:
......@@ -346,3 +361,9 @@ def import_from(numid=None, source=None, id=None):
courses = query('SELECT * FROM courses WHERE handle = ?', id)[0]
lectures = query('SELECT * FROM lectures WHERE course_id = ?', courses['id'])
return render_template('import_campus.html', course=courses, lectures=lectures, campus=campus)
def files(filename):
return redirect(config['VIDEOPREFIX']+'/'+filename)
import feeds
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment