import os from glob import glob from time import sleep from flask_cors import CORS from flask import Flask, jsonify, request, redirect, render_template, Response import Common import threading from liveDownloader import run as RUN app = Flask(__name__) app.config['JSON_AS_ASCII'] = False CORS(app, supports_credentials=True) @app.route("/") def index(): return render_template("index.html") @app.route("/config", methods=["GET"]) def readConfig(): config = Common.config.copy() config.pop("b_p") config.pop("mv") return jsonify(config) @app.route("/config", methods=["POST"]) def writeConfig(): # TODO : 完善 Common.appendOperation("更新配置") Common.reloadConfig() return jsonify({"message":"ok","code":200,"status":0,"data":request.form}) @app.route("/force/not/upload", methods=["POST"]) def toggleForceNotUpload(): Common.forceNotUpload = not Common.forceNotUpload Common.appendOperation("将强制不上传的值改为:{}".format(Common.forceNotUpload)) return jsonify({"message":"ok","code":200,"status":0,"data":{ "forceNotUpload": Common.forceNotUpload, }}) @app.route("/force/not/encode", methods=["POST"]) def toggleForceNotEncode(): Common.forceNotEncode = not Common.forceNotEncode Common.appendOperation("将强制不编码的值改为:{}".format(Common.forceNotEncode)) return jsonify({"message":"ok","code":200,"status":0,"data":{ "forceNotEncode": Common.forceNotEncode, }}) @app.route("/force/not/download", methods=["POST"]) def toggleForceNotDownload(): Common.forceNotDownload = not Common.forceNotDownload Common.appendOperation("将强制不下载的值改为:{}".format(Common.forceNotDownload)) return jsonify({"message":"ok","code":200,"status":0,"data":{ "forceNotDownload": Common.forceNotDownload, }}) @app.route("/force/not/broadcast", methods=["POST"]) def toggleForceNotBroadcast(): Common.forceNotBroadcasting = not Common.forceNotBroadcasting return jsonify({"message":"ok","code":200,"status":0,"data":{ "forceNotBroadcasting": Common.forceNotBroadcasting, }}) @app.route("/force/start/encode", methods=["POST"]) def toggleForceStartEncodeThread(): Common.forceStartEncodeThread = True Common.appendOperation("强制运行编码线程") return jsonify({"message":"ok","code":200,"status":0,"data":{ }}) @app.route("/force/start/upload", methods=["POST"]) def toggleForceStartUploadThread(): Common.forceStartUploadThread = True Common.appendOperation("强制运行上传线程") return jsonify({"message":"ok","code":200,"status":0,"data":{ }}) @app.route("/force/start/clean", methods=["POST"]) def startForceCleanDisk(): Common.doClean(True) Common.appendOperation("强制执行清理程序") return jsonify({"message":"ok","code":200,"status":0,"data":{ }}) @app.route("/encode/insert", methods=["POST"]) def insertEncode(): if "filename" in request.form and os.path.exists(request.form["filename"]): Common.appendOperation("添加编码文件:{}".format(request.form["filename"])) Common.encodeQueue.put(request.form["filename"]) return jsonify({"message":"ok","code":200,"status":0}) else: return jsonify({"message":"no filename specific","code":400,"status":1}) @app.route("/upload/insert", methods=["POST"]) def insertUpload(): if "filename" in request.form and os.path.exists(request.form["filename"]): Common.appendOperation("添加上传文件:{}".format(request.form["filename"])) Common.uploadQueue.put(request.form["filename"]) return jsonify({"message":"ok","code":200,"status":0}) else: return jsonify({"message":"no filename specific","code":400,"status":1}) @app.route("/upload/finish", methods=["POST"]) def finishUpload(): Common.appendOperation("设置当前已完成上传") Common.uploadQueue.put(True) return jsonify({"message":"ok","code":200,"status":0}) @app.route("/stats", methods=["GET"]) def getAllStats(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "download":Common.downloadStatus, "encode": Common.encodeStatus, "encodeQueueSize": Common.encodeQueue.qsize(), "upload": Common.uploadStatus, "uploadQueueSize": Common.uploadQueue.qsize(), "error": Common.errors, "operation": Common.operations, "broadcast": { "broadcaster": Common.broadcaster.__str__(), "isBroadcasting": Common.isBroadcasting, "streamUrl": Common.streamUrl, "updateTime": Common.updateTime, "delayTime": Common.delay }, "config": { "forceNotBroadcasting": Common.forceNotBroadcasting, "forceNotDownload": Common.forceNotDownload, "forceNotUpload": Common.forceNotUpload, "forceNotEncode": Common.forceNotEncode, "downloadOnly": Common.config['dlO'], }, }}) @app.route("/stats/device", methods=["GET"]) def getDeviceStatus(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "status": Common.getCurrentStatus(), }}) @app.route("/stats/broadcast", methods=["GET"]) def getBroadcastStats(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "broadcast": { "broadcaster": Common.broadcaster.__str__(), "isBroadcasting": Common.isBroadcasting, "streamUrl": Common.streamUrl, "updateTime": Common.updateTime, "delayTime": Common.delay } }}) @app.route("/stats/config", methods=["GET"]) def getConfigStats(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "config": { "forceNotBroadcasting": Common.forceNotBroadcasting, "forceNotDownload": Common.forceNotDownload, "forceNotUpload": Common.forceNotUpload, "forceNotEncode": Common.forceNotEncode, "downloadOnly": Common.config['dlO'], } }}) @app.route("/stats/download", methods=["GET"]) def getDownloadStats(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "download":Common.downloadStatus, }}) @app.route("/stats/encode", methods=["GET"]) def getEncodeStats(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "encode": Common.encodeStatus, "encodeQueueSize": Common.encodeQueue.qsize(), }}) @app.route("/stats/upload", methods=["GET"]) def getUploadStats(): return jsonify({"message":"ok","code":200,"status":0,"data":{ "upload": Common.uploadStatus, "uploadQueueSize": Common.uploadQueue.qsize(), }}) @app.route("/account/reLogin", methods=["GET"]) def accountRelogin(): Common.loginBilibili() return jsonify({"message":"ok","code":200,"status":0,"data":{}}) @app.route("/files/", methods=["GET"]) def fileIndex(): a = [] if not os.path.isdir("/var/lib/openmediavault/rrd"): OMV_RRD_PATH = False else: OMV_RRD_PATH = True for i in (glob("*.mp4") + glob("*.flv")): a.append({ "name": i, "size": Common.parseSize(os.path.getsize(i)) }) return render_template("files.html",files=a, show=OMV_RRD_PATH) @app.route("/files/download/", methods=["GET"]) def fileDownload(path): def generate(file, offset=0): with open(file, "rb") as f: f.seek(offset) for row in f: yield row if os.path.exists(path): if "RANGE" in request.headers: offset = int(request.headers["RANGE"].replace("=","-").split("-")[1].strip()) code = 206 else: offset = 0 code = 200 return Response(generate(path, offset), status=code, mimetype='application/octet-stream', headers={ "Content-Length": os.path.getsize(path), "Content-Range": "bytes {}-{}/{}".format(offset,os.path.getsize(path)-1,os.path.getsize(path)), "Accept-Ranges": "bytes", "Range": "bytes", }) else: return Response(status=404) @app.route("/images/rrd/") def rrdGraphGet(filename): OMV_RRD_PATH = "/var/lib/openmediavault/rrd" def generate(file): with open(file, "rb") as f: for row in f: yield row if os.path.isdir(OMV_RRD_PATH): if os.path.exists(os.path.join(OMV_RRD_PATH, filename)): return Response(generate(os.path.join(OMV_RRD_PATH, filename)), mimetype='application/octet-stream') return Response(status=404) def SubThread(): t = threading.Thread(target=RUN, args=()) t.setDaemon(True) t.start() while True: if t.is_alive(): sleep(240) else: t = threading.Thread(target=RUN, args=()) t.setDaemon(True) t.start() if not app.debug: p = threading.Thread(target=SubThread) p.setDaemon(True) p.start() if __name__ == "__main__": app.run()