diff --git a/db.py b/db.py index bb3996fb199be9d34e2f4822104926c2fa88460a..a79326df3f9779ebbcd8eb6545df41a195e69fb8 100644 --- a/db.py +++ b/db.py @@ -1,5 +1,4 @@ from server import * - if config['DB_ENGINE'] == 'sqlite': import sqlite3 diff --git a/db_schema.sql b/db_schema.sql index ae064216eb3debe2adc69bfd81f3a518ea130289..e3e3efac87fa91e8378feed9a0cb76730d071b15 100644 --- a/db_schema.sql +++ b/db_schema.sql @@ -16,6 +16,13 @@ CREATE TABLE IF NOT EXISTS `areas` ( `rank` INTEGER DEFAULT NULL, `coordinates` varchar(30) NOT NULL ); +CREATE TABLE IF NOT EXISTS `tokens` ( + `token` varchar(20) NOT NULL PRIMARY KEY, + `valid_until` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `created_by` INTEGER NOT NULL, + `created_for` varchar(255) NOT NULL, + `lecture_id` INTEGER NOT NULL +); CREATE TABLE IF NOT EXISTS `changelog` ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `when` datetime NOT NULL, diff --git a/edit.py b/edit.py index c04b7917db3a6d6790c9c95dee51a961a904b26e..f0cc639b08c5968f533fb939281dfce31d180305 100644 --- a/edit.py +++ b/edit.py @@ -184,17 +184,23 @@ def edit(prefix='', ignore=[]): @mod_required @csrf_protect def create(table): + args = request.values.items() + if (request.method == 'POST') and (request.get_json()): + args = request.get_json().items() + id = internal_create(table, args, session["user"]["dbid"]) + if 'ref' in request.values: + return redirect(request.values['ref']) + return str(id), 200 + +def internal_create(table, args, user_dbid): assert table in editable_tables - defaults = {'created_by': session['user']['dbid'], 'time_created': datetime.now(), 'time_updated': datetime.now()} + defaults = {'created_by': user_dbid, 'time_created': datetime.now(), 'time_updated': datetime.now()} columns = [] values = [] for column, val in defaults.items(): if column in editable_tables[table]['creationtime_fields']: columns.append(column) values.append(val) - args = request.values.items() - if (request.method == 'POST') and (request.get_json()): - args = request.get_json().items() for column, val in args: if (column == 'ref') or (column == '_csrf_token'): continue @@ -205,10 +211,8 @@ def create(table): id = modify('INSERT INTO %s (%s) VALUES (%s)'%(editable_tables[table]['table'], ','.join(columns), ','.join(['?']*len(values))), *values) if table == 'courses': - set_responsible(id, session['user']['dbid'], 1) - if 'ref' in request.values: - return redirect(request.values['ref']) - return str(id), 200 + set_responsible(id, user_dbid, 1) + return id @app.route('/internal/changelog') @register_navbar('Changelog', icon='book', group='weitere') diff --git a/server.py b/server.py index 6e969ee95f51423e13f3a72c5273be5f54d68902..503edc207535fad1738f358bae8284453e608cf1 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,6 @@ from flask import Flask, g, request, url_for, redirect, session, render_template, flash, Response, make_response from werkzeug.routing import Rule +from werkzeug.utils import secure_filename from functools import wraps from datetime import date, timedelta, datetime, time, MINYEAR import os @@ -508,10 +509,85 @@ def dbstatus(): clusters[cluster].append(host) return render_template('dbstatus.html', clusters=clusters, statuses=status, vars=variables), 200 +def allowed_file(filename): + return '.' in filename and filename.split(".")[-1].lower() in ["mkv", "mp4", "webm", "mov", "avi", "wmv"] + +""" +CREATE TABLE IF NOT EXISTS `tokens` ( + `token` varchar(20) NOT NULL PRIMARY KEY, + `valid_until` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `created_by` INTEGER NOT NULL, + `created_for` varchar(255) NOT NULL, + `lecture_id` INTEGER NOT NULL, +); +""" + +def get_token(token): + res = query('select * from tokens where (token = ?)',token) + if res: + return res[0] + return None + +UPLOAD_FOLDER = "/mnt/IntenseShit/sciebo/code/videoag-website/" + +@app.route('/upload', methods=['GET', 'POST']) +def upload(): + if request.method == 'GET': + return render_template("upload.html"), 200 + elif request.method == 'POST': + if not "uploadtoken" in request.values: + return "Token missing", 403 + tokenobj = get_token(request.values["uploadtoken"]) + if not tokenobj: + return "Token invalid!", 403 + print(tokenobj["valid_until"]) + print(datetime.now()) + if tokenobj["valid_until"] <= datetime.now(): + return "Token ist nicht mehr valide!", 403 + user_dbid = -1 # create one for each token? + videos = [] + i = 0 + while f"time[{i}]" in request.values: + if not all(key in request.values for key in [f"time[{i}]", f"title[{i}]", f"speaker[{i}]", f"duration[{i}]", f"place[{i}]"]): + return "Es fehlt ein Argument!"+str([k for k in request.values.keys()]), 403 + if f'videofile[{i}]' not in request.files: + return "Keine Datei übertragen!", 403 + if request.files[f'videofile[{i}]'] == '': + return "Dateiname ist leer!", 403 + if not allowed_file(request.files[f'videofile[{i}]'].filename): + return f'Dateityp {request.files[f"videofile[{i}]"].filename.split(".")[-1]} nicht erlaubt!', 403 + videos.append(({"time": request.values[f"time[{i}]"], + "title": request.values[f"title[{i}]"], + "speaker": request.values[f"speaker[{i}]"], + "duration": request.values[f"duration[{i}]"], + "place": request.values[f"place[{i}]"], + "comment": request.values[f"comment[{i}]"] if f"comment[{i}]" in request.values else "", + "internal": "Uploaded with the token from "+str(tokenobj["created_for"]), + "course_id": tokenobj["lecture_id"], + "ref": "/80", + "visible": False},request.files[f'videofile[{i}]'])) + i += 1 + for vid in videos: + lec_id = internal_create("lectures", vid[0].items(), user_dbid) + lecturehandle = query('select * from courses_data where (id = ?)',tokenobj["lecture_id"])[0]["handle"] + datestring = vid[0]["time"].split(" ")[0].replace("-","") + fileformat = vid[1].filename.split(".")[-1] + filename = f"{lecturehandle}-{datestring}.{fileformat}" + path = os.path.join(UPLOAD_FOLDER, filename) + if os.path.exists(path): + timestring = vid[0]["time"].split(" ")[1].replace(":","") + filename = f"{lecturehandle}-{datestring}-{timestring}.{fileformat}" + path = os.path.join(UPLOAD_FOLDER, filename) + if os.path.exists(path): + return f"Eine Vorlesung existiert bereits am {datestring}!", 403 + vid[1].save(path) + sorter.sort_autoencode_internal(filename) + return redirect(f"{request.base_url}/{lecturehandle}") + def date_json_handler(obj): return obj.isoformat() if hasattr(obj, 'isoformat') else obj -from edit import edit_handler +from edit import edit_handler, internal_create from jobmanagement import job_handler, job_handler_handle, job_set_state, schedule_job, cancel_job, restart_job import feeds import importer diff --git a/sorter.py b/sorter.py index 3da37e4f34bb3d9a208aa846e1478bc697a6289d..bbdee4ad961f4426c9d96247710d3d7969b59dd0 100644 --- a/sorter.py +++ b/sorter.py @@ -201,6 +201,10 @@ def sort_encoded(filename): @sort_api_token_required def sort_autoencode(): filename = request.values['path'] + sort_autoencode_internal(filename) + return 'OK', 200 + +def sort_autoencode_internal(filename): path = 'autoencode/'+filename matches, fmt = sort_file(filename) if len(matches) != 1: @@ -208,7 +212,6 @@ def sort_autoencode(): return "Could not match filename", 400 lecture = matches[0] schedule_job('probe-raw', {'path': path, 'lecture_id': lecture['id'], 'import-chapters': True}) - return 'OK', 200 @job_handler('publish_video') def handle_published_video(jobid, jobtype, data, state, status): diff --git a/templates/upload.html b/templates/upload.html new file mode 100644 index 0000000000000000000000000000000000000000..965a18d0391827bf3dd95354b6e8dbe1e6d3e6b8 --- /dev/null +++ b/templates/upload.html @@ -0,0 +1,54 @@ +{% extends "base.html" %} +{% block content %} +<div class="panel-group"> + <div class="panel panel-default"> + <div class="panel-heading"> + <h1 class="panel-title">Video Upload</h1> + </div> + <div class="panel-body"> + <form method="post" enctype="multipart/form-data"> + <label for="uploadtoken">Ihr Uploadtoken</label> + <input type="text" name="uploadtoken" id="uploadtoken" required></br></br> + <table class="table table-bordered" id="item_table"> + <tr> + <th>Videodatei</th> + <th>Video-Titel</th> + <th>Gehalten von...</th> + <th>Datum/Uhrzeit der Vorlesung</th> + <th>Ort der Vorlesung</th> + <th>Dauer (in Minuten)</th> + <th>Kommentar</th> + <th><button type="button" onclick=addItem() name="add">X</button></th> + </tr> + </table> + <input type="submit" name="submit" value="Submit videos" /> + </form> + </div> + </div> +</div> +<script type="text/javascript"> + var videonumber = 0; + function getCurrentDate() { + return (new Date()).toISOString().replace(/(\d{4})\-(\d{2})\-(\d{2})T(\d{2}):(\d{2}):(\d{2}).*/, '$1-$2-$3 $4:$5:$6'); + } + function removeItem(item) { + item.closest("tr").remove(); + videonumber -= 1; + } + function addItem() { + var html = ''; + html += '<tr>'; + html += '<td><input type="file" name="videofile['+videonumber+']" class="form-control videofile" required/></td>'; + html += '<td><input type="text" value="Vorlesung/Übung" name="title['+videonumber+']" class="form-control title" required/></td>'; + html += '<td><input type="text" value="Prof. Mustermann" name="speaker['+videonumber+']" class="form-control speaker" required/></td>'; + html += '<td><input type="text" value="'+getCurrentDate()+'" name="time['+videonumber+']" class="form-control time" required/></td>'; + html += '<td><input type="text" value="H01" name="place['+videonumber+']" class="form-control place" required/></td>'; + html += '<td><input type="text" value="60" name="duration['+videonumber+']" class="form-control duration" required/></td>'; + html += '<td><input type="text" value="" name="comment['+videonumber+']" class="form-control comment" /></td>'; + html += '<td><button type="button" name="remove" class="btn btn-danger btn-sm remove" onclick=removeItem($(this))>X</button></td></tr>'; + videonumber += 1; + $('#item_table').append(html); + } + addItem(); +</script> +{% endblock %} \ No newline at end of file