631 lines
22 KiB
Python
631 lines
22 KiB
Python
import uuid
|
|
import os
|
|
import shutil
|
|
|
|
from flask import Flask, request, send_from_directory
|
|
from dynaconf import FlaskDynaconf
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
from flask_security import Security, SQLAlchemyUserDatastore, auth_required, hash_password, current_user, login_user, verify_password, roles_accepted, logout_user
|
|
from flask_security.models import fsqla_v3 as fsqla
|
|
from flask_socketio import SocketIO, join_room, leave_room, emit
|
|
from flask_wtf import CSRFProtect
|
|
|
|
import gettext
|
|
import warnings
|
|
import signal
|
|
import sys
|
|
import pickle
|
|
|
|
from MusicQueue import MusicQueue
|
|
from Music import Music
|
|
import MusicManager
|
|
import Stardust
|
|
import LyricFormatter
|
|
|
|
from Extensions.Netease import NeteaseSession
|
|
# from Extensions.QQMusic import QQMusicSession
|
|
# from Extensions.Bilibili import BilibiliSession
|
|
from Extensions.Provider import SongStatus, AccountType, SessionProvider
|
|
|
|
app = Fla325-576-113sk("GalaxyMusicHall")
|
|
|
|
socketio = SocketIO(app, cors_allowed_origins='*')
|
|
|
|
# 启用配置文件读取
|
|
FlaskDynaconf(app, settings_files=[
|
|
"instance/config.toml", "instance/.secrets.toml"], environments=True)
|
|
|
|
# 喵化输出
|
|
if app.config["meowlize"]:
|
|
os.environ["LANGUAGE"] = "meow"
|
|
|
|
# 初始化gettext
|
|
gettext.install('main', localedir='./locales')
|
|
|
|
db = SQLAlchemy(app)
|
|
fsqla.FsModels.set_db_info(db)
|
|
|
|
# 初始化扩展会话
|
|
ncmSession = NeteaseSession()
|
|
|
|
|
|
class Role(db.Model, fsqla.FsRoleMixin):
|
|
pass
|
|
|
|
|
|
class User(db.Model, fsqla.FsUserMixin):
|
|
pass
|
|
|
|
|
|
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
|
|
CSRFProtect(app)
|
|
app.security = Security(app, user_datastore)
|
|
|
|
queue = MusicQueue()
|
|
current = Music()
|
|
|
|
providerList = [ncmSession]
|
|
|
|
SOCKETIO_UPDATE_RESPONSE = {"status": 101, "msg": "该API使用SocketIO接口"}, 200
|
|
|
|
|
|
def unauthenticated(mechanisms=None, headers=None):
|
|
return {"status": 401, "msg": _("Not authenticated!")}, 401
|
|
|
|
|
|
def denied(mechanisms=None, headers=None):
|
|
return {"status": 403, "msg": _("Permission denied!")}, 403
|
|
|
|
|
|
app.security.unauthn_handler(unauthenticated)
|
|
app.security.unauthz_handler(denied)
|
|
|
|
|
|
def sigint_handler(signal, frame):
|
|
print(_("Quitting..."))
|
|
saveSession()
|
|
sys.exit(0)
|
|
|
|
|
|
signal.signal(signal.SIGINT, sigint_handler)
|
|
|
|
|
|
@app.route("/")
|
|
def test():
|
|
return {"status": 200, "msg": _("Hello, this is the API testing page of galaxy music hall."), "debug": app.debug}
|
|
|
|
|
|
@app.route("/ping", methods=["GET"])
|
|
def ping():
|
|
return {"message": _("Server is running"),
|
|
"instanceName": app.config.get("INSTANCE_NAME")}, 200
|
|
|
|
|
|
@app.route("/config", methods=["GET"])
|
|
@auth_required()
|
|
def getConfig():
|
|
return {"allowPlayerNeteaseLogin": app.config.get("ALLOW_PLAYER_NETEASE_LOGIN")}, 200
|
|
|
|
|
|
@app.route("/user/login", methods=["POST"])
|
|
def userLogin(): # SocketIO似乎不能写cookies
|
|
username = request.form.get("username")
|
|
if username is None:
|
|
return {"status": 403, "msg": _("Incorrect user or password!")}, 403
|
|
password = request.form.get("password")
|
|
try:
|
|
status = verify_password(
|
|
password, user_datastore.find_user(username=username).password)
|
|
if status is False:
|
|
return {"status": 403, "msg": _("Incorrect user or password!")}, 403
|
|
status = login_user(user_datastore.find_user(username=username), remember=True,
|
|
authn_via="password")
|
|
if status:
|
|
return {"status": 200, "msg": _("Login success.")}, 200
|
|
else:
|
|
return {"status": 400, "msg": _("Login failed, unknown exception.")}, 400
|
|
except AttributeError:
|
|
return {"status": 403, "msg": _("Incorrect user or password!")}, 403
|
|
except Exception as e:
|
|
print(e)
|
|
return {"status": 500, "msg": _("Login failed, internal server error.")}, 500
|
|
|
|
|
|
@app.route("/user/logout", methods=["POST"])
|
|
def userLogout():
|
|
try:
|
|
logout_user()
|
|
return {"status": 200, "msg": _("Logout success.")}
|
|
except:
|
|
return {"status": 500, "msg": _("Logout failed, internal server error.")}, 500
|
|
|
|
|
|
@socketio.on("userStatus")
|
|
def userStatus():
|
|
try:
|
|
stardust, nextCost = Stardust.smartread(
|
|
current_user.username, app.config["INITIAL_STARDUST"], app.config["INITIAL_STARDUST_COST"])
|
|
return {"status": current_user.is_authenticated,
|
|
"username": current_user.username,
|
|
"role": current_user.roles[0].name,
|
|
"stardust": stardust,
|
|
"nextCost": nextCost}
|
|
except Exception as e:
|
|
return {"status": False,
|
|
"username": None,
|
|
"role": None,
|
|
"stardust": -1,
|
|
"nextCost": 65536}
|
|
|
|
return SOCKETIO_UPDATE_RESPONSE
|
|
|
|
|
|
@app.route("/music/current", methods=["GET"])
|
|
@auth_required()
|
|
def getCurrentMusic():
|
|
return current.dict(), 200
|
|
|
|
|
|
@socketio.on("nextMusic")
|
|
def nextMusic():
|
|
global current
|
|
try:
|
|
current = queue.front()
|
|
if current.uuid == "KOBEBRYANT":
|
|
return
|
|
queue.pop()
|
|
updateQueue()
|
|
return {"status": 200}, 200
|
|
except:
|
|
current = Music()
|
|
updateQueue()
|
|
return {"status": 204, "msg": _("No music in queue.")}, 204
|
|
|
|
# @app.route("/music/queue", methods=["GET"])
|
|
|
|
|
|
@socketio.on("getQueue") # TODO: 设置未登录用户可见性
|
|
def getQueue():
|
|
socketio.emit("updateQueue", {
|
|
"current": current.dict(), "queue": queue.dict()})
|
|
|
|
|
|
def updateQueue():
|
|
emit("updateQueue", {"current": current.dict(),
|
|
"queue": queue.dict()}, broadcast=True, namespace="/")
|
|
saveSession()
|
|
|
|
|
|
def pushLimitCheck():
|
|
if app.config["ENABLE_PUSH"] is False:
|
|
return {"status": 403, "msg": _("Push is disabled!")}, 403
|
|
username = current_user.username
|
|
if not "admin" in current_user.roles:
|
|
count = queue.count(Music(owner=username))
|
|
if count >= app.config["USER_PUSHLIMIT"]:
|
|
return {"status": 420, "msg": _("You have reached the push limit!")}, 420
|
|
count = queue.size()
|
|
if count >= app.config["TOTAL_PUSHLIMIT"]:
|
|
return {"status": 429, "msg": _("The push queue is full!")}, 429
|
|
|
|
|
|
@socketio.on("pushMusic")
|
|
@auth_required()
|
|
def pushMusic(providerString, content): # TODO: 将下载改为异步API,允许查看进度 TODO: 修改musicURL逻辑
|
|
# 推送速率限制
|
|
if status := pushLimitCheck():
|
|
return status
|
|
# 阻止角色为"admin", "user"以外的用户推送
|
|
# SocketIO似乎不支持auth_required
|
|
if "admin" not in current_user.roles and "user" not in current_user.roles:
|
|
return {"status": 403, "msg": _("Permission denied!")}, 403
|
|
# 处理音乐提供者
|
|
if content is None:
|
|
return {"status": 400, "msg": _("Push parameter is empty!")}, 400
|
|
provider = MusicManager.judgeProvider(
|
|
providerString, content, providerList)
|
|
if provider is None:
|
|
return {"status": 400, "msg": _("Unknown source, please specify!")}, 400
|
|
# 由提供者提供服务
|
|
musicID = provider.parseURL(content)
|
|
musicStatus = provider.checkSong(musicID)
|
|
if musicStatus == SongStatus.SONG_NOTEXIST:
|
|
return {"status": 404, "msg": _("The music does not exist!")}, 404
|
|
if musicStatus == SongStatus.SONG_NOTAVAIL:
|
|
return {"status": 403, "msg": _("The music is not available!")}, 403
|
|
if musicStatus == SongStatus.SONG_ISVIP and provider.accountType != AccountType.ACCOUNT_VIP:
|
|
return {"status": 412, "msg": _("The music is VIP only, please contact administrator to login VIP account!")}, 403
|
|
musicName = provider.getSongName(musicID)
|
|
|
|
music = Music(owner=current_user.username, uuid=None, name=provider.getSongName(musicID), source=provider.providerName, imageURL=provider.getSongImage(
|
|
musicID), musicURL=provider.getSongURL(musicID), lyric=LyricFormatter.lrcFormat(provider.getSongLyric(musicID)))
|
|
# 检查是否已存在
|
|
if (not app.config["ALLOW_DUPLICATE_PUSH"]) and queue.find(Music(name=musicName)):
|
|
return {"status": 201, "msg": _("The music is already in the queue!")}, 201
|
|
# 下载歌曲
|
|
MusicManager.downloadMusic(music, app.config["CACHE_PATH"])
|
|
# 推送至队列
|
|
queue.push(music)
|
|
if not current.uuid:
|
|
nextMusic()
|
|
else:
|
|
updateQueue()
|
|
return {"status": 200, "msg": _("Successfully pushed the music.")}, 200
|
|
|
|
|
|
@socketio.on("deleteMusic")
|
|
@auth_required()
|
|
def deleteMusic(musicUUID):
|
|
# musicUUID = request.form.get("uuid")
|
|
if musicUUID == "KOBEBRYANT":
|
|
return {"status": 400, "msg": "Manba out!"}
|
|
music = queue.find(Music(uuid=musicUUID))
|
|
if not "admin" in current_user.roles:
|
|
# 用户删除部分
|
|
if music is None:
|
|
return {"status": 404, "msg": _("The music is not in the queue!")}, 404
|
|
if music.owner != current_user.username:
|
|
return {"status": 403, "msg": _("You are not the owner of the music!")}, 403
|
|
queue.delete(music)
|
|
updateQueue()
|
|
return {"status": 200, "msg": _("Successfully deleted the music.")}, 200
|
|
else:
|
|
# 管理员删除部分
|
|
if music is None:
|
|
return {"status": 404, "msg": _("The music is not in the queue!")}, 404
|
|
queue.delete(music)
|
|
updateQueue()
|
|
return {"status": 200, "msg": _("Successfully deleted the music.")}, 200
|
|
|
|
|
|
@socketio.on("elevateMusic")
|
|
@auth_required()
|
|
def elevateMusic(musicUUID):
|
|
# musicUUID = request.form.get("uuid")
|
|
music = queue.find(Music(uuid=musicUUID))
|
|
if musicUUID == "KOBEBRYANT":
|
|
return {"status": 400, "msg": "What can I say?"}
|
|
if not "admin" in current_user.roles:
|
|
# 用户提升部分
|
|
if music is None:
|
|
return {"status": 404, "msg": _("The music is not in the queue!")}, 404
|
|
if music.owner != current_user.username:
|
|
return {"status": 403, "msg": _("You are not the owner of the music!")}, 403
|
|
stardust, nextCost = Stardust.smartread(
|
|
current_user.username, app.config["INITIAL_STARDUST"], app.config["INITIAL_STARDUST_COST"])
|
|
if stardust < nextCost:
|
|
return {"status": 403, "msg": _("You do not have enough stardust to elevate the music!")}, 403
|
|
queue.elevate(music)
|
|
Stardust.update(current_user.username, stardust-nextCost,
|
|
nextCost+app.config["STARDUST_COST_INCREASE"])
|
|
updateQueue()
|
|
emit("updateUserStatus", userStatus())
|
|
return {"status": 200, "msg": _("Successfully elevated the music.")}, 200
|
|
else:
|
|
# 管理员提升部分
|
|
if music is None:
|
|
return {"status": 404, "msg": _("The music is not in the queue!")}, 404
|
|
queue.elevate(music)
|
|
updateQueue()
|
|
return {"status": 200, "msg": _("Successfully elevated the music.")}, 200
|
|
|
|
|
|
@app.route("/play/<url>")
|
|
@auth_required()
|
|
@roles_accepted("player")
|
|
def playMusic(url):
|
|
for i in app.config["ALLOWED_UPLOAD_MUSIC"]:
|
|
try:
|
|
os.stat(app.config["CACHE_PATH"]+"/"+url+"."+i)
|
|
return send_from_directory(app.config["CACHE_PATH"], url + "." + i)
|
|
except Exception as e:
|
|
pass
|
|
return {"data": None}
|
|
|
|
|
|
@app.route("/image/<url>")
|
|
@auth_required()
|
|
def getImage(url):
|
|
for i in ("jpg", "png"):
|
|
try:
|
|
os.stat(app.config["CACHE_PATH"]+"/"+url+"."+i)
|
|
return send_from_directory(app.config["CACHE_PATH"], url + "." + i)
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
return "No such file or directory!", 404
|
|
|
|
|
|
@app.route("/lyric/<url>")
|
|
@auth_required()
|
|
def getLyric(url):
|
|
return send_from_directory(app.config["CACHE_PATH"], url+".lrc")
|
|
|
|
|
|
@app.route("/download")
|
|
def downloadMusic():
|
|
url = request.args.get("uuid")
|
|
if url == "flag":
|
|
return "用户拿flag,用户坏!", 400
|
|
for i in app.config["ALLOWED_UPLOAD_MUSIC"]:
|
|
try:
|
|
os.stat(app.config["CACHE_PATH"] + url + "." + i)
|
|
return send_from_directory(app.config["CACHE_PATH"], url + "." + i)
|
|
except:
|
|
pass
|
|
path = app.config["CACHE_PATH"] + "/" + url
|
|
try:
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
data = f.read()
|
|
if "flag" in data:
|
|
return "flag{****REDACTED****}"
|
|
else:
|
|
return data
|
|
except Exception as e:
|
|
print(e)
|
|
return "无法下载此音乐!", 400
|
|
|
|
|
|
@socketio.on("adminResetQueue")
|
|
@auth_required()
|
|
def adminResetQueue():
|
|
global current
|
|
return {"status": 403, "msg": "已禁用此功能!"}, 403
|
|
if not "admin" in current_user.roles:
|
|
return {"status": 403, "msg": _("Permission denied!")}, 403
|
|
queue.clear()
|
|
current = Music()
|
|
updateQueue()
|
|
return {"status": 200, "msg": _("Reset success!")}
|
|
|
|
|
|
@app.route("/upload", methods=["GET", "POST"])
|
|
@roles_accepted("user", "admin")
|
|
def uploadMusic(): # TODO: 修改musicURL逻辑
|
|
# 推送速率限制
|
|
if status := pushLimitCheck():
|
|
return status
|
|
# 上传处理
|
|
file = request.files.get("file")
|
|
if file is None or file.filename == "":
|
|
# TODO: 空文件判断
|
|
return
|
|
if ".php" in file.filename:
|
|
return {"status": 200, "msg": "我觉得银河音乐厅不是个php应用..."}
|
|
# 是音乐文件
|
|
if file.filename.endswith(tuple(app.config["ALLOWED_UPLOAD_MUSIC"])):
|
|
suffix = file.filename.split(".")[-1]
|
|
if queue.find(Music(name=file.filename)):
|
|
return {"status": 201, "msg": _("The music is already in the queue!")}, 201
|
|
musicUUID = str(uuid.uuid4())
|
|
uploadFile = os.path.join(
|
|
app.config["CACHE_PATH"], musicUUID+"."+suffix)
|
|
uploadAlbum = app.config["UPLOAD_MUSIC_IMAGE"]
|
|
try:
|
|
file.save(uploadFile)
|
|
except Exception as e:
|
|
return {"status": 500, "msg": _("Failed to save the file!")}, 500
|
|
try:
|
|
album = MusicManager.imagePayload(uploadFile)
|
|
if album is not None:
|
|
albumFileName = os.path.join(
|
|
app.config["CACHE_PATH"], musicUUID+".jpg")
|
|
with open(albumFileName, "wb") as albumFile:
|
|
albumFile.write(album)
|
|
uploadAlbum = "/api/image/" + musicUUID
|
|
except Exception as e:
|
|
print(e)
|
|
warnings.warn(_("Failed to read the album image!"))
|
|
music = Music(owner=current_user.username, uuid=musicUUID, name=file.filename, source="Upload",
|
|
imageURL=uploadAlbum, musicURL=uploadFile, lyric=LyricFormatter.lrcFormat(None))
|
|
# TODO: 为上传的音乐添加歌词
|
|
queue.push(music)
|
|
if not current.uuid:
|
|
nextMusic()
|
|
else:
|
|
updateQueue()
|
|
return {"status": 200, "msg": _("Successfully uploaded the music!")}, 200
|
|
# 是歌词文件
|
|
elif file.filename.endswith(tuple(app.config["ALLOWED_UPLOAD_LYRIC"])):
|
|
return {"status": 501, "msg": _("Lyric file is not supported yet!")}, 501
|
|
else:
|
|
return {"status": 400, "msg": _("Invalid file format!"), "allowed_format": app.config["ALLOWED_UPLOAD_MUSIC"]}, 400
|
|
|
|
|
|
@socketio.on("getBanner")
|
|
def getBanner():
|
|
return {"data": open(app.config["CACHE_PATH"]+"/banner.md").read()}
|
|
|
|
|
|
@socketio.on("adminPushMessage")
|
|
def broadcastMessage(message: str):
|
|
emit("broadcastMessage", {"title": "来自服务器的消息", "content": message,
|
|
"duration": 5000}, broadcast=True, namespace="/")
|
|
|
|
|
|
def loadBanner(reload=0, bannerfile=app.config["BANNER_FILE"]):
|
|
regenerateUUID()
|
|
try:
|
|
with open(bannerfile, encoding="utf-8") as bannerfile:
|
|
bannerContent = bannerfile.read()
|
|
bannerContent = str.replace(
|
|
bannerContent, r"{{instanceName}}", "InstanceName: "+app.config["INSTANCE_NAME"])
|
|
bannerContent = str.replace(
|
|
bannerContent, r"{{instanceUUID}}", "InstanceUUID: "+app.config["INSTANCE_UUID"])
|
|
with open(app.config["CACHE_PATH"]+"/banner.md", "w", encoding="utf-8") as banner:
|
|
banner.write(bannerContent)
|
|
if reload:
|
|
emit('updateBanner', getBanner(), broadcast=True)
|
|
return {"status": 200, "msg": _("Successfully reloaded the banner!")}, 200
|
|
except Exception as e:
|
|
print(e)
|
|
return {"status": 500, "msg": _("Failed to reload the banner!")}, 500
|
|
|
|
|
|
@socketio.on("adminUpdateBanner")
|
|
@app.route("/admin/updateBanner", methods=["POST"])
|
|
@roles_accepted("admin")
|
|
def updateBanner():
|
|
file = request.files.get("file")
|
|
file.save(app.config["CACHE_PATH"]+"/new_banner.md")
|
|
return loadBanner(reload=0, bannerfile=app.config["CACHE_PATH"]+"/new_banner.md")
|
|
|
|
|
|
@socketio.on("adminResetBanner")
|
|
def resetBanner():
|
|
return loadBanner(reload=0)
|
|
|
|
|
|
@socketio.on("adminDisablePush")
|
|
def disablePush():
|
|
if not "admin" in current_user.roles:
|
|
return {"status": 403, "msg": _("Permission denied!")}, 403
|
|
if app.config["ENABLE_PUSH"]:
|
|
app.config["ENABLE_PUSH"] = False
|
|
emit("updatePushStatus",
|
|
(app.config["ENABLE_PUSH"], 1), broadcast=True, namespace="/")
|
|
return {"status": 200, "msg": _("Push disabled.")}
|
|
else:
|
|
app.config["ENABLE_PUSH"] = True
|
|
emit("updatePushStatus",
|
|
(app.config["ENABLE_PUSH"], 1), broadcast=True, namespace="/")
|
|
return {"status": 200, "msg": _("Push enabled.")}
|
|
|
|
|
|
@socketio.on("extCredential")
|
|
def extCredential(providerString: str, content: str, key: str):
|
|
provider = MusicManager.judgeProvider(providerString, "", providerList)
|
|
if not provider:
|
|
return {"status": 400, "msg": _("Invalid provider!")}, 400
|
|
return provider.loginCredential(content, key)
|
|
|
|
|
|
@app.route("/ext/login", methods=["POST"])
|
|
@socketio.on("extLogin")
|
|
def extLogin(providerString: str) -> dict:
|
|
provider = MusicManager.judgeProvider(providerString, "", providerList)
|
|
if not provider:
|
|
return {"status": 400, "msg": _("Invalid provider!")}, 400
|
|
status = provider.login()
|
|
updateExtStatus()
|
|
return status
|
|
|
|
|
|
@socketio.on("extAnonymousLogin")
|
|
def extAnonymousLogin(providerString: str) -> dict:
|
|
provider = MusicManager.judgeProvider(providerString, "", providerList)
|
|
if not provider:
|
|
return {"status": 400, "msg": _("Invalid provider!")}, 400
|
|
status = provider.loginAnonymous()
|
|
updateExtStatus()
|
|
return status
|
|
|
|
|
|
@app.route("/ext/qrcode", methods=["GET"])
|
|
@socketio.on("extQRCode")
|
|
def getExtQRCode(providerString: str) -> dict:
|
|
provider = MusicManager.judgeProvider(providerString, "", providerList)
|
|
if not provider:
|
|
return {"status": 400, "msg": _("Invalid provider!")}, 400
|
|
qrcode = provider.qrcode()
|
|
return {"status": 200, "url": qrcode}
|
|
|
|
|
|
def getExtStatus(provider: SessionProvider):
|
|
if not provider:
|
|
return {"status": 400, "msg": _("Invalid provider!")}, 400
|
|
return provider.userStatus()
|
|
|
|
|
|
def updateExtStatus():
|
|
for i in providerList:
|
|
print(i.providerName, getExtStatus(i))
|
|
emit("updateExtStatus", (i.providerName, getExtStatus(i)))
|
|
|
|
|
|
@socketio.on("init")
|
|
def clientInit():
|
|
emit("updateBanner", getBanner())
|
|
emit("updatePushStatus", (app.config["ENABLE_PUSH"], 0))
|
|
if "admin" in current_user.roles:
|
|
updateExtStatus()
|
|
|
|
|
|
def regenerateUUID():
|
|
app.config["INSTANCE_UUID"] = str(uuid.uuid1())
|
|
|
|
|
|
def init():
|
|
with app.app_context():
|
|
# # 若不存在数据库就创建
|
|
print(_("Creating database if not present..."))
|
|
db.create_all()
|
|
db.session.commit()
|
|
regenerateUUID()
|
|
try:
|
|
if app.config["PRESERVE_CACHE"]:
|
|
os.stat(app.config["CACHE_PATH"])
|
|
else:
|
|
shutil.rmtree(app.config["CACHE_PATH"])
|
|
os.mkdir(app.config["CACHE_PATH"])
|
|
except FileNotFoundError:
|
|
os.mkdir(app.config["CACHE_PATH"])
|
|
except PermissionError:
|
|
raise Exception(_("Permission denied to access cache directory!"))
|
|
except:
|
|
raise Exception(_("Failed to rebuild the cache directory!"))
|
|
os.system("pwd")
|
|
shutil.copy("./resource/flag.lrc", app.config["CACHE_PATH"])
|
|
shutil.copy("./resource/flag.wav", app.config["CACHE_PATH"])
|
|
shutil.copy("./resource/flag.png", app.config["CACHE_PATH"])
|
|
shutil.copy("./resource/KOBEBRYANT.jpg", app.config["CACHE_PATH"])
|
|
if loadBanner(reload=0)[1] != 200:
|
|
raise Exception(_("Failed to reload the banner!"))
|
|
if app.config["SAVE_SESSION"]:
|
|
if app.config["PRESERVE_CACHE"]:
|
|
try:
|
|
for i in providerList:
|
|
with open(app.config["CACHE_PATH"]+"/"+i.providerName+".session", "r", encoding="utf-8") as sessionFile:
|
|
i.restoreSession(sessionFile.read())
|
|
with open(app.config["CACHE_PATH"]+"/queue.pickle", "rb") as queueFile:
|
|
queue.load(queueFile.read())
|
|
with open(app.config["CACHE_PATH"]+"/current.pickle", "rb") as currentFile:
|
|
current = pickle.loads(currentFile.read())
|
|
except FileNotFoundError:
|
|
warnings.warn(_("No session found, skipping..."))
|
|
except Exception as e:
|
|
print(e)
|
|
raise Exception(_("Failed to restore the session!"))
|
|
else:
|
|
warnings.warn(
|
|
_("SAVE_SESSION doesn't work without PRESERVE_CACHE!"))
|
|
print(_("Successfully initialized the application!"))
|
|
|
|
|
|
def saveSession():
|
|
if app.config["SAVE_SESSION"]:
|
|
if not app.config["PRESERVE_CACHE"]:
|
|
warnings.warn(
|
|
_("SAVE_SESSION doesn't work without PRESERVE_CACHE!"))
|
|
try:
|
|
# 保存音乐提供者session
|
|
for i in providerList:
|
|
sessionText = i.dumpSession()
|
|
with open(app.config["CACHE_PATH"]+"/"+i.providerName+".session", "w", encoding="utf-8") as sessionFile:
|
|
sessionFile.write(sessionText)
|
|
# 保存歌曲队列
|
|
with open(app.config["CACHE_PATH"]+"/queue.pickle", "wb") as queueFile:
|
|
queueFile.write(queue.dump())
|
|
# 保存当前播放
|
|
with open(app.config["CACHE_PATH"]+"/current.pickle", "wb") as currentFile:
|
|
currentFile.write(pickle.dumps(current))
|
|
except Exception as e:
|
|
print(e)
|
|
warnings.warn(_("Failed to save the session, operation aborted."))
|
|
|
|
|
|
init()
|
|
if __name__ == "__main__":
|
|
socketio.run(app, debug=app.config["DEBUG"],
|
|
host=app.config["HOST"], port=app.config["PORT"])
|