fix: 修复咪咕集体无版权 & feat: 更换咪咕API为网页版接口 & fix: 修复网络库潜在报错问题

Close #39
This commit is contained in:
helloplhm-qwq 2024-03-03 18:37:20 +08:00
parent 64a1b2ffac
commit e6115b555b
No known key found for this signature in database
GPG Key ID: B7542212855B2C26
4 changed files with 96 additions and 34 deletions

View File

@ -108,7 +108,7 @@ def request(url: str, options = {}) -> requests.Response:
# 获取请求方法没有则默认为GET请求 # 获取请求方法没有则默认为GET请求
try: try:
method = options['method'] method = options['method'].upper()
options.pop('method') options.pop('method')
except Exception as e: except Exception as e:
method = 'GET' method = 'GET'
@ -277,14 +277,14 @@ async def AsyncRequest(url, options = {}) -> ClientResponse:
logger.debug(f'HTTP Request: {url}\noptions: {options}') logger.debug(f'HTTP Request: {url}\noptions: {options}')
# 转换body/form参数为原生的data参数并为form请求追加Content-Type头 # 转换body/form参数为原生的data参数并为form请求追加Content-Type头
if (method == 'POST') or (method == 'PUT'): if (method == 'POST') or (method == 'PUT'):
if options.get('body'): if (options.get('body') is not None):
options['data'] = options['body'] options['data'] = options['body']
options.pop('body') options.pop('body')
if options.get('form'): if (options.get('form') is not None):
options['data'] = convert_dict_to_form_string(options['form']) options['data'] = convert_dict_to_form_string(options['form'])
options.pop('form') options.pop('form')
options['headers']['Content-Type'] = 'application/x-www-form-urlencoded' options['headers']['Content-Type'] = 'application/x-www-form-urlencoded'
if (isinstance(options['data'], dict)): if (isinstance(options.get('data'), dict)):
options['data'] = json.dumps(options['data']) options['data'] = json.dumps(options['data'])
# 进行请求 # 进行请求
try: try:

View File

@ -234,11 +234,15 @@ default = {
"mg": { "mg": {
"desc": "咪咕音乐相关配置", "desc": "咪咕音乐相关配置",
"user": { "user": {
"desc": "研究不深后两项自行抓包获取在header里", "desc": "研究不深后两项自行抓包获取网页端cookie",
"aversionid": "", "by": "",
"token": "", "session": "",
"osversion": "10",
"useragent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36", "useragent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36",
"refresh_login": {
"enable": False,
"interval": 86400,
"desc": "进行cookie保活"
}
}, },
}, },
"kw": { "kw": {
@ -301,10 +305,13 @@ default = {
], ],
'mg': [ 'mg': [
{ {
'aversionid': '', 'by': '',
'token': '', 'session': '',
'osversion': '10',
'useragent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36', 'useragent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36',
"refresh_login": {
"enable": False,
"interval": 86400
}
} }
], ],
'kw': [ 'kw': [

View File

@ -12,48 +12,52 @@ from common import Httpx
from common import config from common import config
from common import variable from common import variable
from common.exceptions import FailedException from common.exceptions import FailedException
from . import refresh_login
tools = { tools = {
'url': 'https://app.c.nf.migu.cn/MIGUM2.0/strategy/listen-url/v2.4?toneFlag=__quality__&songId=__songId__&resourceType=2',
'qualityMap': { 'qualityMap': {
'128k': 'PQ', '128k': '1',
'320k': 'HQ', '320k': '2',
'flac': 'SQ', 'flac': '3',
'flac24bit': 'ZQ', 'flac24bit': '4',
"master": "5"
}, },
'qualityMapReverse': { 'qualityMapReverse': {
'PQ': '128k', '000009': '128k',
'HQ': '320k', '020010': '320k',
'SQ': 'flac', '011002': 'flac',
'ZQ': 'flac24bit', '011005': 'flac24bit',
}, },
} }
async def url(songId, quality): async def url(songmid, quality):
info_url = f"http://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/resourceinfo.do?resourceType=2&copyrightId=" + songmid
info_request = await Httpx.AsyncRequest(info_url, {"method": "POST", "cache": 259200})
infobody = info_request.json()
if infobody["code"] != "000000":
raise FailedException("failed to fetch song info")
user_info = config.read_config('module.mg.user') if (not variable.use_cookie_pool) else random.choice(config.read_config('module.cookiepool.mg')) user_info = config.read_config('module.mg.user') if (not variable.use_cookie_pool) else random.choice(config.read_config('module.cookiepool.mg'))
req = await Httpx.AsyncRequest(tools['url'].replace('__quality__', tools['qualityMap'][quality]).replace('__songId__', songId), { req = await Httpx.AsyncRequest(f'https://m.music.migu.cn/migumusic/h5/play/auth/getSongPlayInfo?type={tools["qualityMap"][quality]}&copyrightId={infobody["resource"][0]["copyrightId"]}', {
'method': 'GET', 'method': 'GET',
'headers': { 'headers': {
'User-Agent': user_info['useragent'], 'User-Agent': user_info['useragent'],
'aversionid': user_info['aversionid'], "by": user_info["by"],
'token': user_info['token'], "Cookie": "SESSION=" + user_info["session"],
'channel': '0146832', "Referer": "https://m.music.migu.cn/v4/",
'language': 'Chinese', "Origin": "https://m.music.migu.cn",
'ua': 'Android_migu',
'mode': 'android',
'os': 'Android ' + user_info['osversion'],
}, },
}) })
try: try:
body = req.json() body = req.json()
data = body['data']
if ((not int(body['code']) == 0) or ( not data['url'])): if (int(body['code']) != 200 or (not body.get("data")) or (not body["data"]["playUrl"])):
raise FailedException('failed') raise FailedException(body.get("msg") if body.get("msg") else "failed")
data = body["data"]
return { return {
'url': data['url'].split('?')[0], 'url': body["data"]["playUrl"].split("?")[0] if body["data"]["playUrl"].split("?")[0].startswith("http") else "http:" + body["data"]["playUrl"].split("?")[0],
'quality': tools['qualityMapReverse'][data['audioFormatType']], 'quality': tools['qualityMapReverse'].get(data['formatId']) if (tools['qualityMapReverse'].get(data['formatId'])) else "unknown",
} }
except: except:
raise FailedException('failed') raise FailedException('failed')

View File

@ -0,0 +1,51 @@
# ----------------------------------------
# - mode: python -
# - author: helloplhm-qwq -
# - name: refresh_login.py -
# - project: lx-music-api-server -
# - license: MIT -
# ----------------------------------------
# This file is part of the "lx-music-api-server" project.
from common import Httpx
from common import config
from common.exceptions import FailedException
from common import scheduler
from common import variable
from common import log
logger = log.log("migu_refresh_login")
async def do_account_refresh(user_info):
req = await Httpx.AsyncRequest("https://m.music.migu.cn/migumusic/h5/user/auth/userActiveNotice", {
"method": "POST",
"body": "",
"headers": {
"User-Agent": user_info["useragent"],
"by": user_info["by"],
"Cookie": "SESSION=" + user_info["session"],
"Referer": "https://m.music.migu.cn/v4/my",
"Origin": "https://m.music.migu.cn",
},
})
body = req.json()
if (int(body["code"]) != 200):
raise FailedException("咪咕session保活失败: " + str(body["msg"]))
return logger.info("咪咕session保活成功")
if (variable.use_cookie_pool):
users = config.read_config("module.cookiepool.mg")
for u in users:
ref = u.get("refresh_login") if u.get("refresh_login") else {
"enable": False,
"interval": 86400
}
if (ref["enable"]):
scheduler.append("migu_refresh_login_pooled_" + users["by"], do_account_refresh, ref["interval"], {"user_info": u})
else:
u = config.read_config("module.mg.user")
ref = config.read_config("module.mg.user.refresh_login")
if (ref["enable"]):
scheduler.append("migu_refresh_login", do_account_refresh, ref["interval"], {"user_info": u})