支持api获取状态

This commit is contained in:
Jerry Yan 2019-04-07 15:30:57 +08:00 committed by JerryYan
parent f8d4be5385
commit b9b0994f4c
6 changed files with 300 additions and 106 deletions

170
Common.py Normal file
View File

@ -0,0 +1,170 @@
import queue
from datetime import datetime
from api import XiGuaLiveApi
import json
_config_fp = open("config.json","r",encoding="utf8")
config = json.load(_config_fp)
dt_format="%Y/%m/%d %H:%M:%S"
broadcaster = ""
streamUrl = ""
isBroadcasting = False
updateTime = ""
uploadQueue = queue.Queue()
encodeQueue = queue.Queue()
uploadStatus = []
downloadStatus = []
encodeStatus = []
errors = []
def appendUploadStatus(obj):
global uploadStatus
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
uploadStatus.append(obj)
else:
uploadStatus.append({
"datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj)
})
uploadStatus = uploadStatus[-10:]
def modifyLastUploadStatus(obj):
global uploadStatus
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
uploadStatus[-1] = obj
else:
uploadStatus[-1]["message"] = str(obj)
uploadStatus[-1]["datetime"] = datetime.strftime(datetime.now(), dt_format)
def appendEncodeStatus(obj):
global encodeStatus
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
encodeStatus.append(obj)
else:
encodeStatus.append({
"datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj)
})
encodeStatus = encodeStatus[-10:]
def modifyLastEncodeStatus(obj):
global encodeStatus
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
encodeStatus[-1] = obj
else:
encodeStatus[-1]["message"] = str(obj)
encodeStatus[-1]["datetime"] = datetime.strftime(datetime.now(), dt_format)
def appendDownloadStatus(obj):
global downloadStatus
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
downloadStatus.append(obj)
else:
downloadStatus.append({
"datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj)
})
downloadStatus = downloadStatus[-10:]
def modifyLastDownloadStatus(obj):
global downloadStatus
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
downloadStatus[-1] = obj
else:
downloadStatus[-1]["message"] = str(obj)
downloadStatus[-1]["datetime"] = datetime.strftime(datetime.now(), dt_format)
def appendError(obj):
global errors
if isinstance(obj, dict):
if "datetime" not in obj:
obj["datetime"] = datetime.strftime(datetime.now(), dt_format)
errors.append(obj)
else:
errors.append({
"datetime": datetime.strftime(datetime.now(), dt_format),
"message": str(obj)
})
errors = errors[-10:]
class downloader(XiGuaLiveApi):
files = []
playlist: str = None
def updRoomInfo(self):
global broadcaster, isBroadcasting, updateTime
super(downloader, self).updRoomInfo()
updateTime = datetime.strftime(datetime.now(), dt_format)
broadcaster = self.roomLiver
isBroadcasting = self.isLive
if self.isLive:
self.updPlayList()
else:
self.files = []
def updPlayList(self):
global streamUrl
if self.isLive:
if "stream_url" in self._rawRoomInfo:
if self.playlist is None:
self.playlist = False
else:
self.playlist = self._rawRoomInfo["stream_url"]["flv_pull_url"]
self.playlist = self.playlist.replace("_uhd", "").replace("_sd", "").replace("_ld", "")
streamUrl = self.playlist
def onLike(self, user):
pass
def onAd(self, i):
pass
def onChat(self, chat):
pass
def onEnter(self, msg):
pass
def onJoin(self, user):
pass
def onLeave(self, json):
self.updRoomInfo()
def onMessage(self, msg):
pass
def onPresent(self, gift):
pass
def onPresentEnd(self, gift):
pass
def onSubscribe(self, user):
pass

8
Model/DataBase.py Normal file
View File

@ -0,0 +1,8 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URL"] = "sqlite://data.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)

10
Model/Files.py Normal file
View File

@ -0,0 +1,10 @@
from datetime import datetime
from sqlalchemy import func
from .DataBase import db
class Files(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
filename = db.Column(db.String(50))
is_upload = db.Column(db.Integer(1), server_default=0, default=0)
create_time = db.Column(db.TIMESTAMP, server_default=func.now(), default=datetime.now())

68
WebMain.py Normal file
View File

@ -0,0 +1,68 @@
from flask import Flask, jsonify, request
import Common
import threading
from liveDownloader import run as RUN
app = Flask("liveStatus")
app.config['JSON_AS_ASCII'] = False
@app.route("/config", methods=["GET"])
def readConfig():
config = Common.config.copy()
config.pop("b_p")
config.pop("mtd")
config.pop("del")
config.pop("mv")
return jsonify(config)
@app.route("/config", methods=["POST"])
def writeConfig():
# TODO : 完善
return jsonify({"message":"ok","code":200,"status":0,"data":request.form})
@app.route("/stats", methods=["GET"])
def getAllStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{
"download":Common.downloadStatus,
"encode": Common.encodeStatus,
"upload": Common.uploadStatus,
"error": Common.errors,
"broadcast": {
"broadcaster": Common.broadcaster.__str__(),
"isBroadcasting": Common.isBroadcasting,
"streamUrl": Common.streamUrl,
"updateTime": Common.updateTime
}
}})
@app.route("/stats/download", methods=["GET"])
def geDownloadStats():
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,
}})
@app.route("/stats/upload", methods=["GET"])
def getUploadStats():
return jsonify({"message":"ok","code":200,"status":0,"data":{
"upload": Common.uploadStatus,
}})
t = threading.Thread(target=RUN, args=(Common.config['l_u'],))
t.setDaemon(True)
if __name__ == "__main__":
t.start()
app.run()

View File

@ -4,7 +4,7 @@ import os
import re import re
import json as JSON import json as JSON
from datetime import datetime from datetime import datetime
from Common import appendUploadStatus, modifyLastUploadStatus
import rsa import rsa
import math import math
import base64 import base64
@ -195,7 +195,6 @@ class Bilibili:
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)] :param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
:type parts: VideoPart or list<VideoPart> :type parts: VideoPart or list<VideoPart>
""" """
self.session.headers['Content-Type'] = 'application/json; charset=utf-8' self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
if not isinstance(parts, list): if not isinstance(parts, list):
parts = [parts] parts = [parts]
@ -238,7 +237,7 @@ class Bilibili:
# {"upload_id":"72eb747b9650b8c7995fdb0efbdc2bb6","key":"\/i181012ws2wg1tb7tjzswk2voxrwlk1u.mp4","OK":1,"bucket":"ugc"} # {"upload_id":"72eb747b9650b8c7995fdb0efbdc2bb6","key":"\/i181012ws2wg1tb7tjzswk2voxrwlk1u.mp4","OK":1,"bucket":"ugc"}
json = r.json() json = r.json()
upload_id = json['upload_id'] upload_id = json['upload_id']
appendUploadStatus("Upload >{}< Started".format(filepath))
with open(filepath, 'rb') as f: with open(filepath, 'rb') as f:
chunks_num = math.ceil(filesize / chunk_size) chunks_num = math.ceil(filesize / chunk_size)
chunks_index = 0 chunks_index = 0
@ -263,10 +262,9 @@ class Bilibili:
) )
if r.status_code != 200: if r.status_code != 200:
continue continue
print('{} : UPLOAD {}/{}'.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), chunks_index,
chunks_num), r.text)
chunks_data = f.read(chunk_size) chunks_data = f.read(chunk_size)
chunks_index += 1 # start with 0 chunks_index += 1 # start with 0
modifyLastUploadStatus("Uploading >{}< @ {:.2f}%".format(filepath, 100.0*chunks_index/chunks_num))
# NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769 # NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769
self.session.post('https:{endpoint}/{upos_uri}?' self.session.post('https:{endpoint}/{upos_uri}?'
@ -282,6 +280,7 @@ class Bilibili:
self.videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0], self.videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0],
'title': part.title, 'title': part.title,
'desc': part.desc}) 'desc': part.desc})
modifyLastUploadStatus("Upload >{}< Finished".format(filepath))
__f = open("uploaded.json","w") __f = open("uploaded.json","w")
JSON.dump(self.videos, __f) JSON.dump(self.videos, __f)
@ -330,21 +329,21 @@ class Bilibili:
"order_id": 0, "order_id": 0,
"videos": self.videos} "videos": self.videos}
) )
print(r.text) appendUploadStatus(">{}< Published | Result : {}".format(title, r.text))
def reloadFromPrevious(self): def reloadFromPrevious(self):
if os.path.exists("uploaded.json"): if os.path.exists("uploaded.json"):
__f = open("uploaded.json", "r") __f = open("uploaded.json", "r")
try: try:
self.videos = JSON.load(__f) self.videos = JSON.load(__f)
print("RELOAD Success") appendUploadStatus("RELOAD SUCCESS")
except: except:
print("RELOAD Failed") appendUploadStatus("RELOAD Failed")
self.videos = [] self.videos = []
__f.close() __f.close()
os.remove("uploaded.json") os.remove("uploaded.json")
else: else:
print("RELOAD Failed") appendUploadStatus("RELOAD Failed")
self.videos = [] self.videos = []
def clear(self): def clear(self):

View File

@ -2,71 +2,14 @@ import shutil
import sys import sys
import time import time
from datetime import datetime from datetime import datetime
import queue
import threading import threading
from config import config
from api import XiGuaLiveApi
from bilibili import * from bilibili import *
from Common import *
import os
import requests
q = queue.Queue()
base_uri = ""
isEncode = False isEncode = False
isDownload = False isDownload = False
uq = queue.Queue()
eq = queue.Queue()
class downloader(XiGuaLiveApi):
files = []
playlist: str = None
def updRoomInfo(self):
super(downloader, self).updRoomInfo()
if self.isLive:
self.updPlayList()
else:
print("未开播,等待开播")
self.files = []
def updPlayList(self):
if self.isLive:
if "stream_url" in self._rawRoomInfo:
if self.playlist is None:
self.apiChangedError("无法获取直播链接")
self.playlist = False
else:
self.playlist = self._rawRoomInfo["stream_url"]["flv_pull_url"]
self.playlist = self.playlist.replace("_uhd", "").replace("_sd", "").replace("_ld", "")
def onLike(self, user):
pass
def onAd(self, i):
pass
def onChat(self, chat):
pass
def onEnter(self, msg):
pass
def onJoin(self, user):
pass
def onLeave(self, json):
self.updRoomInfo()
def onMessage(self, msg):
pass
def onPresent(self, gift):
pass
def onPresentEnd(self, gift):
pass
def onSubscribe(self, user):
pass
def download(url): def download(url):
@ -74,38 +17,42 @@ def download(url):
path = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.flv") path = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.flv")
p = requests.get(url, stream=True) p = requests.get(url, stream=True)
if p.status_code != 200: if p.status_code != 200:
print("{} : Download Response 404 ,will stop looping".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) appendDownloadStatus("Download [{}] Response 404 ,will stop looping".format(url))
return True return True
isDownload = True isDownload = True
print("{} : Download {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), path)) appendDownloadStatus("Starting Download >{}<".format(path))
f = open(path, "wb") f = open(path, "wb")
try: try:
for t in p.iter_content(chunk_size=64 * 1024): for t in p.iter_content(chunk_size=64 * 1024):
if t: if t:
f.write(t) f.write(t)
if os.path.getsize(path) > 1024 * 1024 * 1024 * 1.5: _size = os.path.getsize(path)
modifyLastDownloadStatus("Download >{}< @ {:.2f}%".format(path, 100.0 * _size/config["size"]))
if _size > config["size"]:
break break
print("{} : Download Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) modifyLastDownloadStatus("Finished Download >{}<".format(path))
except Exception as e: except Exception as e:
print("{} : Download Quiting With Exception {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), appendError("Download >{}< With Exception {}".format(path, datetime.strftime(datetime.now(), "%y%m%d %H%M"),
e.__str__())) e.__str__()))
f.close() f.close()
isDownload = False isDownload = False
if os.path.getsize(path) == 0: if os.path.getsize(path) == 0:
os.remove(path) os.remove(path)
return False return False
eq.put(path) encodeQueue.put(path)
download(url) download(url)
def encode(): def encode():
global isEncode global isEncode
while True: while True:
i = eq.get() i = encodeQueue.get()
if os.path.exists(i): if os.path.exists(i):
isEncode = True isEncode = True
os.system("ffmpeg -i {} -c:v copy -c:a copy -f mp4 {}".format(i, i[:13] + ".mp4")) appendEncodeStatus("Start Encoding >{}<".format(i))
uq.put(i[:13] + ".mp4") os.system("ffmpeg -i {} -c:v copy -c:a copy -f mp4 {} -y".format(i, i[:13] + ".mp4"))
uploadQueue.put(i[:13] + ".mp4")
modifyLastEncodeStatus("Finished Encoding >{}<".format(i))
if config["mv"]: if config["mv"]:
shutil.move(i, config["mtd"]) shutil.move(i, config["mtd"])
elif config["del"]: elif config["del"]:
@ -114,51 +61,45 @@ def encode():
def upload(date=datetime.strftime(datetime.now(), "%Y_%m_%d")): def upload(date=datetime.strftime(datetime.now(), "%Y_%m_%d")):
print("{} : Upload Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) i = uploadQueue.get()
i = uq.get()
while True: while True:
if isinstance(i, bool): if isinstance(i, bool):
print("{} : Upload Daemon Receive Command {}"
.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
if i is True: if i is True:
print("自动投稿中,请稍后") appendUploadStatus("[{}]自动投稿中,请稍后".format(config["t_t"].format(date)))
b.finishUpload(config["t_t"].format(date), 17, config["tag"], config["des"], b.finishUpload(config["t_t"].format(date), 17, config["tag"], config["des"],
source=config["src"], no_reprint=0) source=config["src"], no_reprint=0)
b.clear() b.clear()
break break
print("{} : Upload {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
if not os.path.exists(i): if not os.path.exists(i):
print("{} : Upload File Not Exist {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i)) appendError("Upload File Not Exist {}".format(i))
i = uq.get() i = uploadQueue.get()
continue continue
try: try:
b.preUpload(VideoPart(i, os.path.basename(i))) b.preUpload(VideoPart(i, os.path.basename(i)))
except: except Exception as e:
continue appendError(e.__str__())
os.remove(i) os.remove(i)
i = uq.get() i = uploadQueue.get()
print("{} : Upload Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) appendUploadStatus("Upload Daemon Quiting")
b = Bilibili() b = Bilibili()
b.login(config["b_u"], config["b_p"]) b.login(config["b_u"], config["b_p"])
if __name__ == "__main__":
name = config["l_u"] def run(name):
print("西瓜直播录播助手 by JerryYan") global isEncode, isDownload
api = downloader(name) api = downloader(name)
print("进入", api.roomLiver, "的直播间")
if not api.isValidRoom:
input("房间不存在")
sys.exit()
print("=" * 30)
d = datetime.strftime(datetime.now(), "%Y_%m_%d")
t = threading.Thread(target=download)
ut = threading.Thread(target=upload, args=(d,))
et = threading.Thread(target=encode, args=()) et = threading.Thread(target=encode, args=())
et.setDaemon(True) et.setDaemon(True)
et.start() et.start()
if not api.isValidRoom:
appendError("[{}]房间不存在".format(name))
return
d = None
t = threading.Thread(target=download)
ut = threading.Thread(target=upload, args=(d,))
_count = 0 _count = 0
_count_error = 0 _count_error = 0
while True: while True:
@ -185,7 +126,7 @@ if __name__ == "__main__":
_count = 0 _count = 0
_count_error = 0 _count_error = 0
except Exception as e: except Exception as e:
print(e.__str__()) appendError(e.__str__())
time.sleep(20) time.sleep(20)
_count_error += 1 _count_error += 1
continue continue
@ -197,15 +138,13 @@ if __name__ == "__main__":
if d is not None: if d is not None:
d = None d = None
if not isEncode and not isDownload: if not isEncode and not isDownload:
uq.put(True) uploadQueue.put(True)
isEncode = True isEncode = True
isDownload = True isDownload = True
del config
from config import config
# print("主播未开播等待1分钟后重试") # print("主播未开播等待1分钟后重试")
time.sleep(60) time.sleep(60)
try: try:
api.updRoomInfo() api.updRoomInfo()
_count_error = 0 _count_error = 0
except Exception as e: except Exception as e:
print(e.__str__()) appendError(e.__str__())