From f8b0126066f6f2dc2440fbdb6c2c536729758b40 Mon Sep 17 00:00:00 2001 From: helloplhm-qwq Date: Fri, 7 Jun 2024 15:46:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B9=85=E8=BF=9D=E7=9A=84=E6=9B=B4?= =?UTF-8?q?=E6=96=B0awa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/default_config.py | 9 +++++ common/gcsp.py | 86 ++++++++++++++++++++++++++++++++++++++++ common/utils.py | 2 +- main.py | 10 +++-- modules/__init__.py | 2 +- termux.py | 6 +++ 6 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 common/gcsp.py diff --git a/common/default_config.py b/common/default_config.py index 4ee3021..a8f1c7f 100644 --- a/common/default_config.py +++ b/common/default_config.py @@ -155,6 +155,15 @@ module: headers: User-Agent: okhttp/3.10.0 + gcsp: # 歌词适配后端配置 + # 请注意只允许私用,不要给原作者带来麻烦,谢谢 + enable: false # 是否启用歌词适配后端 + path: /client/cgi-bin/api.fcg # 后端接口地址 + enable_verify: false # 是否启用后端验证 + package_md5: "" # apk包的md5值,用于验证 + salt_1: "NDRjZGIzNzliNzEe" # 后端验证参数1 + salt_2: "6562653262383463363633646364306534333668" # 后端验证参数2 + cookiepool: kg: - userid: '0' diff --git a/common/gcsp.py b/common/gcsp.py new file mode 100644 index 0000000..d8ccde7 --- /dev/null +++ b/common/gcsp.py @@ -0,0 +1,86 @@ +# ---------------------------------------- +# - mode: python - +# - author: helloplhm-qwq - +# - name: gcsp.py - +# - project: moonsea_api(private) - +# - license: MIT - +# ---------------------------------------- +# This file is part of the "moonsea_api" project and featured for the "lx-music-api-server" project. + +import zlib +import binascii +import time +import ujson as json +import modules +from .utils import createMD5 as hashMd5 +from . import config +from aiohttp.web import Response + +PACKAGE = config.read_config("module.gcsp.package_md5") # pkg md5 +SALT_1 = config.read_config("module.gcsp.salt_1") # salt 1 +SALT_2 = config.read_config("module.gcsp.salt_2") # salt 2 +NEED_VERIFY = config.read_config("module.gcsp.enable_verify") # need verify + +qm = { + 'mp3': '128k', + 'hq': '320k', + 'sq': 'flac', + "hr": "flac24bit", + 'hires': 'flac24bit' +} + +pm = { + 'qq': 'tx', + 'wyy': 'wy', + 'kugou': 'kg', + "kuwo": "kw", + "mgu": "mg" +} + +internal_trans = { + "time": "请求检验失败,请检查系统时间是否为标准时间", + "sign": "请求检验失败,请检查应用是否被修改或更新到最新版本", +} + +def decode(indata): + return json.loads(binascii.unhexlify(zlib.decompress(indata))) + +def verify(data): + if (not NEED_VERIFY): + return "success" + sign_1 = hashMd5(PACKAGE + data["time"] + SALT_2) + sign_2 = hashMd5((json.dumps(data["text_1"]) + json.dumps(data["text_2"]) + sign_1 + data["time"] + SALT_1).replace("\\", "").replace("}\"", "}").replace("\"{", "{")) + + if (data["sign_1"] != sign_1 or data["sign_2"] != sign_2): + return "sign" + if int(time.time()) - int(data["time"]) > 10: + return "time" + return "success" + +async def handleGcspBody(body): + data = decode(body) + result = verify(data) + if (result != "success"): + return zlib.compress(json.dumps({"code": "403", "error_msg": internal_trans[result], "data": None}, ensure_ascii = False).encode("utf-8")), 200 + + data["te"] = json.loads(data["text_1"]) + + body = modules.url(pm[data["te"]["platform"]], data["te"]["t1"], qm[data["te"]["t2"]]) + + if (body["code"] == 0): + return zlib.compress(json.dumps({"code": "200", "error_msg": "success", "data": body["data"] if (pm[data["te"]["platform"]] != "kw") else {"bitrate": "123", "url": body["data"]}}, ensure_ascii = False).encode("utf-8")), 200 + else: + return zlib.compress(json.dumps({"code": "403", "error_msg": "内部系统错误,请稍后再试", "data": None}, ensure_ascii = False).encode("utf-8")), 200 + +async def handle_request(request): + if (request.method == "POST"): + body = await request.body() + return Response( + body = await handleGcspBody(body), + content_type = "application/octet-stream" + ) + else: + return Response( + body = "Method Not Allowed", + status = 405 + ) \ No newline at end of file diff --git a/common/utils.py b/common/utils.py index 81812ae..ff000a6 100644 --- a/common/utils.py +++ b/common/utils.py @@ -65,7 +65,7 @@ def filterFileName(filename): # 将不合法字符替换为下划线 return re.sub(illegal_chars, '_', filename) -def createMD5(s: (str, bytes)): +def createMD5(s: (str | bytes)): if (isinstance(s, str)): s = s.encode("utf-8") return hashlib.md5(s).hexdigest() diff --git a/main.py b/main.py index 6122651..4229ac3 100644 --- a/main.py +++ b/main.py @@ -15,7 +15,7 @@ import asyncio import traceback import threading import ujson as json -from aiohttp.web import Response, FileResponse, StreamResponse +from aiohttp.web import Response, FileResponse, StreamResponse, Application from io import TextIOWrapper import sys import os @@ -35,6 +35,7 @@ from common import Httpx from common import variable from common import scheduler from common import lx_script +from common import gcsp import modules def handleResult(dic, status=200) -> Response: @@ -209,7 +210,7 @@ async def handle_local(request): 'data': localMusic.checkLocalMusic(data['p']) } -app = aiohttp.web.Application(middlewares=[handle_before_request]) +app = Application(middlewares=[handle_before_request]) utils.setGlobal(app, "app") # mainpage @@ -223,6 +224,9 @@ app.router.add_get('/local/{type}', handle_local) if (config.read_config('common.allow_download_script')): app.router.add_get('/script', lx_script.generate_script_response) +if (config.read_config('module.gcsp.enable')): + app.router.add_route('*', config.read_config('module.gcsp.path'), gcsp.handle_gcsp) + # 404 app.router.add_route('*', '/{tail:.*}', handle_404) @@ -286,7 +290,7 @@ async def run_app_host(host): https_runner, host, port, ssl_context=ssl_context) await https_site.start() variable.running_ports.append(f'{host}_{port}') - logger.info(f"""监听 -> http://{ + logger.info(f"""监听 -> https://{ host if (':' not in host) else '[' + host + ']' }:{port}""") diff --git a/modules/__init__.py b/modules/__init__.py index 730b366..0aff336 100644 --- a/modules/__init__.py +++ b/modules/__init__.py @@ -47,7 +47,7 @@ sourceExpirationTime = { } -async def url(source, songId, quality, query): +async def url(source, songId, quality, query = {}): if (not quality): return { 'code': 2, diff --git a/termux.py b/termux.py index a7d5336..37489d2 100644 --- a/termux.py +++ b/termux.py @@ -1,3 +1,9 @@ +# for installing the dependencies on Termux. +# ruamel-yaml-clib need to build from source, but it will throw an error during +# the build process in default configuration. To fix this, we need to set +# CFLAGS environment variable to "-Wno-incompatible-function-pointer-types". +# Resolution from: https://github.com/termux/termux-packages/issues/16746 + import os import subprocess