qinglong/netease-music/netease_music_copartner.py

185 lines
7.2 KiB
Python
Raw Normal View History

2024-05-14 17:10:26 +08:00
# -*- coding: utf-8 -*-
"""
cron: 0 8 * * *
new Env('网易音乐合伙人');
"""
import requests
import base64
import codecs
import execjs
import json
from Crypto.Cipher import AES
from notify import send
def to_16(key):
while len(key) % 16 != 0:
key += '\0'
return str.encode(key)
def aes_encrypt(text, key, iv):
bs = AES.block_size
pad2 = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs)
encryptor = AES.new(to_16(key), AES.MODE_CBC, to_16(iv))
encrypt_aes = encryptor.encrypt(str.encode(pad2(text)))
encrypt_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')
return encrypt_text
def rsa_encrypt(text, pubKey, modulus):
text = text[::-1]
rs = int(codecs.encode(text.encode('utf-8'), 'hex_codec'), 16) ** int(pubKey, 16) % int(modulus, 16)
return format(rs, 'x').zfill(256)
# 获取i值的函数即随机生成长度为16的字符串
get_i = execjs.compile(r"""
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
""")
class Copartner():
name = "音乐合伙人"
def __init__(self, check_item):
self.csrf = None
self.musicDataUrl = "http://interface.music.163.com/api/music/partner/daily/task/get"
self.userInfoUrl = "https://music.163.com/api/nuser/account/get"
self.signUrl = "https://interface.music.163.com/weapi/music/partner/work/evaluate?csrf_token="
self.g = '0CoJUm6Qyw8W8jud' # buU9L(["爱心", "女孩", "惊恐", "大笑"])的值
self.b = "010001" # buU9L(["流泪", "强"])的值
# buU9L(Rg4k.md)的值
self.c = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
self.i = get_i.call('a', 16) # 随机生成长度为16的字符串
self.iv = "0102030405060708" # 偏移量
self.headers = {
"Accept": "application/json, text/javascript",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh-Hans;q=0.9",
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "http://mp.music.163.com",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 CloudMusic/0.1.1 NeteaseMusic/8.8.01"
}
self.musicTags = "3-A-1"
self.musicScore = "3"
self.check_item = check_item
def get_enc_sec_key(self):
return rsa_encrypt(self.i, self.b, self.c)
def get_params(self, data):
enc_text = str(data)
return aes_encrypt(aes_encrypt(enc_text, self.g, self.iv), self.i, self.iv)
def sign(self, session, music_data, msg):
works = music_data['works']
task_id = music_data['id']
begin = False
for work in works:
_work = work['work']
if work['completed']:
msg.append({
"name": f"{_work['name']}{_work['authorName']}",
"value": f"评分完成:{work['score']}"
})
else:
if not begin:
msg.append({"name": "本次进度", "value": ""})
begin = True
data = {
"params": self.get_params({
"taskId": task_id,
"workId": _work['id'],
"score": self.musicScore,
"tags": self.musicTags,
"customTags": "%5B%5D",
"comment": "",
"syncYunCircle": "true",
"csrf_token": self.csrf
}).replace("\n", ""),
"encSecKey": self.get_enc_sec_key()
}
try:
response = session.post(
url=f"{self.signUrl}={self.csrf}",
data=data, headers=self.headers).json()
if response["code"] == 200:
msg.append({
"name": f"{_work['name']}{_work['authorName']}",
"value": f"评分完成:{self.musicScore}"
})
except Exception as e:
print(f"歌曲 {_work['name']} 评分异常,原因{str(e)}")
def valid(self, session):
try:
content = session.get(url=self.musicDataUrl,
headers={**self.headers, "Referer": "https://mp.music.163.com/"})
except Exception as e:
return False, f"登录验证异常,错误信息: {e}"
data = content.json()
if data["code"] == 301:
return False, data["message"]
if data["code"] == 200:
music_data = data["data"]
user_name = self.login_info(session=session)["profile"]["nickname"]
return music_data, user_name
return False, "登录信息异常"
def login_info(self, session):
try:
return session.get(url=self.userInfoUrl, headers=self.headers).json()
except Exception as e:
print(e)
return {
"profile": {
"nickname": "获取用户信息异常"
}
}
def main(self):
session = requests.session()
cookie = self.check_item.get("cookie")
music_cookie = {item.split("=")[0]: item.split("=")[1] for item in cookie.split("; ")}
self.csrf = music_cookie['__csrf']
requests.utils.add_dict_to_cookiejar(session.cookies, music_cookie)
music_data, user_name = self.valid(session)
if music_data:
completed = music_data['completed']
msg = [
{"name": "帐号信息", "value": f"{user_name}"},
{"name": "当前进度", "value": ""},
{"name": "今日完成状态", "value": f"{'已完成' if completed else '未完成'}"},
{"name": "当前获得积分", "value": music_data['integral']},
{"name": "已完成评定数", "value": music_data["completedCount"]},
]
if not completed:
self.sign(session, music_data, msg)
else:
msg = [
{"name": "帐号信息", "value": user_name},
{"name": "cookie信息", "value": "Cookie 可能过期"},
]
msg = "\n".join([f"{one.get('name')}: {one.get('value')}" for one in msg])
return msg
if __name__ == "__main__":
with open("/ql/config/netease_music_cookie.json", "r", encoding="utf-8") as f:
all_data = json.loads(f.read())
_check_item = all_data.get("MUSIC_COPARTNER", [])
res = ""
for index, item in enumerate(_check_item):
res = f'{res}账号{index + 1}\n{Copartner(item).main()}\n'
print(res)
send('网易音乐合伙人', res)