Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • bootstrap4
  • intros
  • master
  • modules
  • postgres_integration
  • s3compatible
6 results

Target

Select target project
  • jannik/website
  • vincent/website
  • dominic/website
  • romank/website
  • videoaginfra/website
5 results
Select Git revision
  • master
1 result
Show changes
......@@ -8,7 +8,7 @@ from server import *
@register_navbar('Statistiken', icon='stats')
@mod_required
def stats():
semester = query('SELECT DISTINCT semester from courses WHERE semester != ""')
semester = query('SELECT DISTINCT semester from courses WHERE semester != \'\'')
for i in semester:
year = int(i['semester'][0:4])
if i['semester'].endswith('ss'):
......@@ -20,21 +20,21 @@ def stats():
return render_template('stats.html', semester=semester, filter=request.args.get('filter'))
STATS_QUERIES = {}
STATS_QUERIES['formats_views'] = "SELECT formats.description AS labels, count(DISTINCT log.id) AS `values` FROM log \
JOIN videos ON (videos.id = log.video) JOIN formats ON (formats.id = videos.video_format) GROUP BY formats.id"
STATS_QUERIES['course_count'] = 'SELECT semester AS x, count(id) AS y FROM courses WHERE semester != "" GROUP BY semester'
STATS_QUERIES['formats_views'] = "SELECT formats.description AS labels, count(DISTINCT log.id) AS \"values\" FROM log \
JOIN videos ON (videos.id = log.video) JOIN formats ON (formats.id = videos.video_format) GROUP BY formats.id, formats.description"
STATS_QUERIES['course_count'] = 'SELECT semester AS x, count(id) AS y FROM courses WHERE semester != \'\' GROUP BY semester ORDER BY semester ASC'
STATS_QUERIES['lectures_count'] = 'SELECT semester AS x, count(lectures.id) AS y FROM lectures \
JOIN courses ON (courses.id = lectures.course_id) WHERE semester != "" GROUP BY semester'
STATS_QUERIES['categories_courses'] = "SELECT courses.subject AS labels, count(courses.id) AS `values` FROM courses \
JOIN courses ON (courses.id = lectures.course_id) WHERE semester != \'\' GROUP BY semester ORDER BY semester ASC'
STATS_QUERIES['categories_courses'] = "SELECT courses.subject AS labels, count(courses.id) AS \"values\" FROM courses \
GROUP BY courses.subject ORDER BY labels DESC LIMIT 100"
STATS_QUERIES['organizer_courses'] = "SELECT courses.organizer AS labels, count(courses.id) AS `values` FROM courses \
STATS_QUERIES['organizer_courses'] = "SELECT courses.organizer AS labels, count(courses.id) AS \"values\" FROM courses \
GROUP BY courses.organizer ORDER BY labels DESC LIMIT 100"
STATS_QUERIES['categories_lectures'] = "SELECT courses.subject AS labels, count(lectures.id) AS `values` FROM lectures \
JOIN courses ON (courses.id = lectures.course_id) WHERE lectures.visible GROUP BY courses.subject ORDER BY `values` DESC LIMIT 100"
STATS_QUERIES['categories_lectures'] = "SELECT courses.subject AS labels, count(lectures.id) AS \"values\" FROM lectures \
JOIN courses ON (courses.id = lectures.course_id) WHERE lectures.visible GROUP BY courses.subject ORDER BY \"values\" DESC LIMIT 100"
STATS_QUERIES['lecture_views'] = "SELECT lectures.time AS x, count(DISTINCT log.id) AS y FROM log \
JOIN videos ON (videos.id = log.video) \
JOIN lectures ON (lectures.id = videos.lecture_id) \
WHERE (lectures.course_id = ?) GROUP BY lectures.id ORDER BY lectures.time"
WHERE (lectures.course_id = ?) GROUP BY lectures.id, lectures.time ORDER BY lectures.time"
STATS_QUERIES['live_views'] = "SELECT hlslog.segment AS x, COUNT(DISTINCT hlslog.id) AS y FROM hlslog WHERE hlslog.lecture = ? \
GROUP BY hlslog.segment ORDER BY hlslog.segment"
STATS_QUERIES['lecture_totalviews'] = "SELECT 42"
......@@ -71,9 +71,9 @@ def stats_generic(req, param=None):
@app.route('/internal/stats/viewsperday/<req>/<param>')
@mod_required
def stats_viewsperday(req, param=""): #pylint: disable=too-many-locals
update_expr = 'INSERT INTO logcache (req, param, trace, date, value) SELECT "%s", ?, trace, date, y FROM (%s) AS cachetmp WHERE date < ?'
query_expr = 'SELECT date, trace, value AS y FROM logcache WHERE req = "%s" AND param = ? UNION SELECT * FROM (%s) AS cachetmp'
date_subexpr = 'SELECT CASE WHEN MAX(date) IS NULL THEN "2000-00-00" ELSE MAX(date) END AS t FROM `logcache` WHERE req = "%s" AND param = ?'
update_expr = 'INSERT INTO logcache (req, param, trace, date, value) SELECT \'%s\', ?, trace, date, y FROM (%s) AS cachetmp WHERE date < ?'
query_expr = 'SELECT date, trace, value AS y FROM logcache WHERE req = \'%s\' AND param = ? UNION SELECT * FROM (%s) AS cachetmp'
date_subexpr = 'SELECT CASE WHEN MAX(date) IS NULL THEN \'2000-01-01\' ELSE MAX(date) END AS t FROM "logcache" WHERE req = \'%s\' AND param = ?'
queries = {
'lecture': # views per day per lecture (split per format)
'''SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y
......@@ -81,9 +81,9 @@ def stats_viewsperday(req, param=""): #pylint: disable=too-many-locals
JOIN videos ON videos.id = log.video
JOIN formats ON formats.id = videos.video_format
WHERE log.date > %T AND videos.lecture_id = ?
GROUP BY log.date, videos.video_format
GROUP BY log.date, formats.description, videos.video_format
UNION
SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y
SELECT log.date AS date, \'total\' AS trace, COUNT(DISTINCT log.id) AS y
FROM log JOIN videos ON videos.id = log.video
WHERE log.date > %T AND videos.lecture_id = ? GROUP BY log.date''',
......@@ -93,9 +93,9 @@ def stats_viewsperday(req, param=""): #pylint: disable=too-many-locals
JOIN lectures ON lectures.id = videos.lecture_id
JOIN formats ON formats.id = videos.video_format
WHERE log.date > %T AND lectures.course_id = ?
GROUP BY log.date, videos.video_format
GROUP BY log.date, formats.description, videos.video_format
UNION
SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y
SELECT log.date AS date, \'total\' AS trace, COUNT(DISTINCT log.id) AS y
FROM log
JOIN videos ON videos.id = log.video
JOIN lectures ON lectures.id = videos.lecture_id
......@@ -107,9 +107,9 @@ def stats_viewsperday(req, param=""): #pylint: disable=too-many-locals
FROM log
JOIN videos ON videos.id = log.video
JOIN formats ON formats.id = videos.video_format
WHERE log.date > %T GROUP BY log.date, videos.video_format
WHERE log.date > %T GROUP BY log.date, formats.description, videos.video_format
UNION
SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y
SELECT log.date AS date, \'total\' AS trace, COUNT(DISTINCT log.id) AS y
FROM log
WHERE log.date > %T
GROUP BY log.date''',
......@@ -120,9 +120,9 @@ def stats_viewsperday(req, param=""): #pylint: disable=too-many-locals
JOIN lectures ON lectures.id = videos.lecture_id
JOIN courses ON courses.id = lectures.course_id
WHERE log.date > %T
GROUP BY log.date, courses.id'''
GROUP BY log.date, courses.handle, courses.id'''
}
expr = queries[req].replace('%T', '"'+query(date_subexpr%('viewsperday.'+req), param)[0]['t']+'"')
expr = queries[req].replace('%T', '\''+str(query(date_subexpr%('viewsperday.'+req), param)[0]['t'])+'\'')
params = [param]*expr.count('?')
try:
modify("BEGIN")
......@@ -130,18 +130,21 @@ def stats_viewsperday(req, param=""): #pylint: disable=too-many-locals
modify('COMMIT')
except Exception: #pylint: disable=broad-except
traceback.print_exc()
expr = queries[req].replace('%T', '"'+str(date.today())+'"')
expr = queries[req].replace('%T', '\''+str(date.today())+'\'')
rows = query(query_expr%('viewsperday.'+req, expr), param, *params)
start = None
traces = set()
data = {}
for row in rows:
if not start or row['date'] < start:
start = row['date']
row_date = row['date']
if isinstance(row_date, datetime):
row_date = row_date.date()
if not start or row_date < start:
start = row_date
traces.add(row['trace'])
if row['date'] not in data:
data[row['date']] = {}
data[row['date']][row['trace']] = row['y']
if row_date not in data:
data[row_date] = {}
data[row_date][row['trace']] = row['y']
end = date.today()
res = [{'name': trace, 'x': [], 'y': []} for trace in traces]
......
......@@ -252,6 +252,6 @@ def tagid(value):
@app.template_global()
def is_readonly():
try:
return show('SHOW GLOBAL STATUS LIKE "wsrep_ready"')['wsrep_ready'] != 'ON'
return show('SHOW GLOBAL STATUS LIKE \'wsrep_ready\'')['wsrep_ready'] != 'ON'
except: #pylint: disable=bare-except
return True
......@@ -81,6 +81,22 @@
{{ navbaricon(n) }}
{% endfor %}
<li>
<a href="https://beta.video.fsmpi.rwth-aachen.de" style="padding: 10px 6px; margin-left: 1em; color: rgb(10, 156, 10);">
<span aria-hidden="true" class="fa fa-external-link-square-alt"></span>
Zur neuen Seite
</a>
<script>
$(function() {
$('a[href="https://beta.video.fsmpi.rwth-aachen.de"]').on('click', function(e) {
e.preventDefault();
window.location.href = 'https://beta.video.fsmpi.rwth-aachen.de' + window.location.pathname;
});
});
</script>
</li>
{% for grouper, list in navbar|rejectattr("group", "none")|groupby("group") if ismod() %}
<li{% if request.endpoint in list|map(attribute='endpoint') %} class="active dropdown"{% endif %}>
<a data-toggle="dropdown" data-boundary="viewport" class="dropdown-toggle" style="padding: 10px 6px; cursor: pointer;">{{ grouper }}<span class="caret"></span></a>
......
......@@ -6,7 +6,7 @@
<div class="panel-heading">
<h1 class="panel-title">Sortierlog
<a class="btn btn-default" href="{{url_for('sort_now', ref=request.url)}}">Jetzt einsortieren</a>
<button class="btn btn-default" onclick="$('button[data-path^=\'sorterrorlog.\'][data-path$=\'.deleted\']').each(function (e) { moderator.api.set($(this).data('path'),1,false); }); window.location.reload();">Alle Fehler entfernen</button>
<button class="btn btn-default" onclick="$('button[data-path^=\'sorterrorlog.\'][data-path$=\'.deleted\']').each(function (e) { moderator.api.set($(this).data('path'),true,false); }); window.location.reload();">Alle Fehler entfernen</button>
</h1>
</div>
<div class="panel-body">
......
......@@ -14,7 +14,7 @@ class JobmanagementTestCase(FlaskTestCase):
return data[0]['count']
def getCanceledJobCount(self):
data = query("SELECT count(id) AS count from jobs WHERE canceled=1")
data = query("SELECT count(id) AS count from jobs WHERE canceled=true")
return data[0]['count']
def generateTestJob(self):
......
......@@ -61,6 +61,12 @@ class VideoTestCase(unittest.TestCase):
r = c.get('/15ws-einfprog')
assert r.status_code == 200
r = c.get('/99')
assert r.status_code == 200
r = c.post('/99/2330/login', data={"username": "wrong", "password": "auth"})
assert r.status_code == 302
def test_timetable(self):
with self.app as c:
r = c.get('/internal/timetable')
......@@ -73,7 +79,6 @@ class VideoTestCase(unittest.TestCase):
assert r.status_code == 200
assert 'AfI' in r.data.decode()
assert 'Progra' in r.data.decode()
assert 'Bio' in r.data.decode()
def test_faq(self):
r = self.app.get('/faq')
......@@ -118,7 +123,7 @@ class VideoTestCase(unittest.TestCase):
def test_search(self):
r = self.app.get('/search?q=Malo')
assert r.status_code == 200
assert 'Mathematische Logik II' in r.data.decode() and '4.1 Der Sequenzenkalkül' in r.data.decode()
assert 'Mathematische Logik II' in r.data.decode()
r = self.app.get('/search?q=Afi+Stens')
assert r.status_code == 200
assert 'Analysis für Informatiker' in r.data.decode() and 'Höhere Mathematik I' in r.data.decode()
......@@ -177,6 +182,12 @@ class VideoTestCase(unittest.TestCase):
assert r.status_code == 200
assert 'Testtitle' in r.data.decode() and 'lectures.7353.title' in r.data.decode()
r = c.post('/internal/set/responsible/20/1', data={'_csrf_token': 'asd'})
assert r.status_code == 200
r = c.post('/internal/unset/responsible/20/1', data={'_csrf_token': 'asd'})
assert r.status_code == 200
def test_legacyurl(self):
with self.app as c:
......@@ -260,14 +271,27 @@ class VideoTestCase(unittest.TestCase):
assert len(match) == 1
assert match[0]['id'] == 6095
# @unittest.skip("too slow")
def test_campusimport(self):
with self.app as c:
self.login(c)
r = self.app.get('/internal/sort/log')
assert r.status_code == 200
r = self.app.post('/internal/import/257', data={'campus.new.url': 'https://www.campus.rwth-aachen.de/rwth/all/event.asp?gguid=0x4664DBD60E5A02479B53089BF0EB0681&tguid=0x0B473CF286B45B4984CD02565C07D6F8', 'campus.new.type': 'Vorlesung'})
r = self.app.post('/internal/jobs/add/thumbnail', data={'lectureid': 10, '_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.get('/internal/sort/now')
assert r.status_code == 200
r = self.app.get('/internal/sort/encoded/something-wrong', data={'apikey': '1'})
assert r.status_code == 400
r = self.app.get('/internal/sort/encoded/09ss-dsal-090619-720p.mp4', data={'apikey': '1'})
assert r.status_code == 200
@unittest.skip("too slow")
def test_campusimport(self):
with self.app as c:
self.login(c)
r = self.app.post('/internal/import/257', data={'campus.new.url': 'https://online.rwth-aachen.de/RWTHonline/pl/ui/%24ctx/wbLv.wbShowLVDetail?pStpSpNr=269474&pSpracheNr=1', 'campus.new.type': 'Übung'})
assert r.status_code == 200
......@@ -279,3 +303,140 @@ class VideoTestCase(unittest.TestCase):
self.login(c)
r = self.app.get('/internal/cutprogress')
assert r.status_code == 200
# Some quick tests below to execute more sql statements
def test_encoding(self):
with self.app as c:
self.login(c)
r = self.app.post('/internal/jobs/add/remux', data={'videoid': 28, '_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/add/reencode', data={'videoid': 16080, '_csrf_token': 'asd'})
assert r.status_code == 302
# Trigger edit handler
r = c.get('internal/edit', data={"courses.3.title":"Test","_csrf_token":"asd"})
assert r.status_code == 200
def test_feeds(self):
with self.app as c:
r = self.app.get('/feed')
assert r.status_code == 200
r = self.app.get('/07ws-buk/feed')
assert r.status_code == 200
r = self.app.get('/07ws-buk/rss', data={'format_id':10})
assert r.status_code == 200
r = self.app.get('/courses/feed')
assert r.status_code == 200
def test_icalexport(self):
with self.app as c:
self.login(c)
r = self.app.get('/internal/ical/user/1')
assert r.status_code == 200
r = self.app.get('/internal/ical/notuser/1')
assert r.status_code == 200
r = self.app.get('/internal/ical/course/1')
assert r.status_code == 200
def test_jobs(self):
with self.app as c:
self.login(c)
r = self.app.get('/internal/jobs/overview')
assert r.status_code == 200
r = self.app.get('/internal/jobs/overview?worker=worker0')
assert r.status_code == 200
r = self.app.post('/internal/jobs/action/clear_failed', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/action/clear_failed/1', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/action/retry_failed', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/action/retry_failed/1', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/action/copy/1', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/action/delete/1', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/action/cancel/1', data={'_csrf_token': 'asd'})
assert r.status_code == 302
r = self.app.post('/internal/jobs/api/job/1/ping', data={'apikey': '1', 'host': 'test', 'status': '{}', 'state': 'finished'})
assert r.status_code == 205
# Test new worker
import uuid
r = self.app.post(f'/internal/jobs/api/worker/{uuid.uuid4()}/schedule', data=json.dumps({'jobtypes': ['probe'], 'queues': ['default'], 'apikey': '1'}), content_type='application/json')
assert r.status_code in [200, 503]
def test_auth(self):
with self.app as c:
r = self.app.get('/internal/auth', headers={'X-Original-Uri': 'https://videoag.fsmpi.rwth-aachen.de/files/pub/15ws-afi/15ws-afi-151022-720p.mp4'})
assert r.status_code == 200
# Not found, but sql is executed
r = self.app.get('/internal/auth', headers={'X-Original-Uri': 'https://videoag.fsmpi.rwth-aachen.de/files/pub/hls/something'})
assert r.status_code == 404
r = self.app.get('/internal/auth', headers={'X-Original-Uri': 'https://videoag.fsmpi.rwth-aachen.de/files/pub/hls/42'})
assert r.status_code == 404
def test_stats(self):
with self.app as c:
self.login(c)
r = self.app.get('/internal/stats')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/formats_views')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/course_count')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/lectures_count')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/categories_courses')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/organizer_courses')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/categories_lectures')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/lecture_views')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/live_views')
assert r.status_code == 200
r = self.app.get('/internal/stats/generic/lecture_totalviews')
assert r.status_code == 200
r = self.app.get('/internal/stats/viewsperday/lecture/1')
assert r.status_code == 200
r = self.app.get('/internal/stats/viewsperday/course/1')
assert r.status_code == 200
r = self.app.get('/internal/stats/viewsperday/global')
assert r.status_code == 200
r = self.app.get('/internal/stats/viewsperday/courses')
assert r.status_code == 200
......@@ -23,7 +23,7 @@ def query_lectures_on_day(start, end):
# lecture.time <= end AND lecture.time+lecture.duration >= start
# But there is no SQL statement that does this and is compatible with both sqlite
# and mysql, so we approximate the "lecture.time+lecture.duration" part
rows = query('''SELECT lectures.*, courses.short, "course" AS sep, courses.*
rows = query('''SELECT lectures.*, courses.short, \'course\' AS sep, courses.*
FROM lectures
JOIN courses ON (lectures.course_id = courses.id)
WHERE time <= ? AND time > ?
......