From 00369dc92c67d4cf570c702fe4a592171f36cc5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E6=99=93=E6=99=B4?= <37541680+Suxiaoqinx@users.noreply.github.com> Date: Wed, 28 Aug 2024 03:16:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0GUI=20WEB=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- maingui.py | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 maingui.py diff --git a/maingui.py b/maingui.py new file mode 100644 index 0000000..f0c1e05 --- /dev/null +++ b/maingui.py @@ -0,0 +1,191 @@ +from flask import Flask, request, render_template, jsonify, Response +import json +import os +import urllib.parse +from hashlib import md5 +from random import randrange +import requests +from cryptography.hazmat.primitives import padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from flask_wtf import FlaskForm +from wtforms import StringField, SelectField, SubmitField +from wtforms.validators import DataRequired + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'your_secret_key' + +# 定义表单类 +class SongForm(FlaskForm): + song_ids = StringField('Song ID or URL', validators=[DataRequired()]) + level = SelectField('Quality Level', choices=[ + ('standard', '标准音质'), + ('exhigh', '极高音质'), + ('lossless', '无损音质'), + ('hires', 'Hires音质'), + ('sky', '沉浸环绕声'), + ('jyeffect', '高清环绕声'), + ('jymaster', '超清母带'), + ], validators=[DataRequired()]) + submit = SubmitField('Submit') + +def HexDigest(data): + return "".join([hex(d)[2:].zfill(2) for d in data]) + +def HashDigest(text): + HASH = md5(text.encode("utf-8")) + return HASH.digest() + +def HashHexDigest(text): + return HexDigest(HashDigest(text)) + +def parse_cookie(text: str): + cookie_ = [item.strip().split('=', 1) for item in text.strip().split(';') if item] + cookie_ = {k.strip(): v.strip() for k, v in cookie_} + return cookie_ + +def ids(ids): + if '163cn.tv' in ids: + response = requests.get(ids, allow_redirects=False) + ids = response.headers.get('Location') + if 'music.163.com' in ids: + index = ids.find('id=') + 3 + ids = ids[index:].split('&')[0] + return ids + +def read_cookie(): + script_dir = os.path.dirname(os.path.abspath(__file__)) + cookie_file = os.path.join(script_dir, 'cookie.txt') + with open(cookie_file, 'r') as f: + cookie_contents = f.read() + return cookie_contents + +def post(url, params, cookie): + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36 Chrome/91.0.4472.164 NeteaseMusicDesktop/2.10.2.200154', + 'Referer': '', + } + cookies = { + "os": "pc", + "appver": "", + "osver": "", + "deviceId": "pyncm!" + } + cookies.update(cookie) + response = requests.post(url, headers=headers, cookies=cookies, data={"params": params}) + return response.text + +def size(value): + units = ["B", "KB", "MB", "GB", "TB", "PB"] + size = 1024.0 + for i in range(len(units)): + if (value / size) < 1: + return "%.2f%s" % (value, units[i]) + value = value / size + return value + +def music_level1(value): + if value == 'standard': + return "标准音质" + elif value == 'exhigh': + return "极高音质" + elif value == 'lossless': + return "无损音质" + elif value == 'hires': + return "Hires音质" + elif value == 'sky': + return "沉浸环绕声" + elif value == 'jyeffect': + return "高清环绕声" + elif value == 'jymaster': + return "超清母带" + else: + return "未知音质" + +def url_v1(id, level, cookies): + url = "https://interface3.music.163.com/eapi/song/enhance/player/url/v1" + AES_KEY = b"e82ckenh8dichen8" + config = { + "os": "pc", + "appver": "", + "osver": "", + "deviceId": "pyncm!", + "requestId": str(randrange(20000000, 30000000)) + } + + payload = { + 'ids': [id], + 'level': level, + 'encodeType': 'flac', + 'header': json.dumps(config), + } + + if level == 'sky': + payload['immerseType'] = 'c51' + + url2 = urllib.parse.urlparse(url).path.replace("/eapi/", "/api/") + digest = HashHexDigest(f"nobody{url2}use{json.dumps(payload)}md5forencrypt") + params = f"{url2}-36cd479b6b5-{json.dumps(payload)}-36cd479b6b5-{digest}" + padder = padding.PKCS7(algorithms.AES(AES_KEY).block_size).padder() + padded_data = padder.update(params.encode()) + padder.finalize() + cipher = Cipher(algorithms.AES(AES_KEY), modes.ECB()) + encryptor = cipher.encryptor() + enc = encryptor.update(padded_data) + encryptor.finalize() + params = HexDigest(enc) + response = post(url, params, cookies) + return json.loads(response) + +def name_v1(id): + urls = "https://interface3.music.163.com/api/v3/song/detail" + data = {'c': json.dumps([{"id":id,"v":0}])} + response = requests.post(url=urls, data=data) + return response.json() + +def lyric_v1(id, cookies): + url = "https://interface3.music.163.com/api/song/lyric" + data = {'id': id, 'cp': 'false', 'tv': '0', 'lv': '0', 'rv': '0', 'kv': '0', 'yv': '0', 'ytv': '0', 'yrv': '0'} + response = requests.post(url=url, data=data, cookies=cookies) + return response.json() + +@app.route('/', methods=['GET', 'POST']) +def index(): + form = SongForm() + return render_template('index.html', form=form) + +@app.route('/fetch_data', methods=['POST']) +def fetch_data(): + song_ids = request.form.get('song_ids') + level = request.form.get('level') + + if not song_ids or not level: + return jsonify({"status": 400, "msg": "缺少参数!"}) + + cookies = parse_cookie(read_cookie()) + song_id = ids(song_ids) + urlv1 = url_v1(song_id, level, cookies) + namev1 = name_v1(urlv1['data'][0]['id']) + lyricv1 = lyric_v1(urlv1['data'][0]['id'], cookies) + + if urlv1['data'][0]['url'] is not None: + song_url = urlv1['data'][0]['url'] + song_name = namev1['songs'][0]['name'] + song_picUrl = namev1['songs'][0]['al']['picUrl'] + song_alname = namev1['songs'][0]['al']['name'] + artist_names = '/'.join(ar['name'] for ar in namev1['songs'][0]['ar']) + + data = { + "status": 200, + "name": song_name, + "pic": song_picUrl, + "ar_name": artist_names, + "al_name": song_alname, + "level": music_level1(urlv1['data'][0]['level']), + "size": size(urlv1['data'][0]['size']), + "url": song_url, + "lyric": lyricv1.get('lrc', {}).get('lyric', '无歌词'), + "tlyric": lyricv1.get('tlyric', {}).get('lyric', '无翻译歌词') + } + return jsonify(data) + return jsonify({"status": 400, "msg": "信息获取不完整!"}) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000, debug=False)