qinglong/netease-music/netease_music_copartner.py
2024-05-14 17:10:26 +08:00

185 lines
7.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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)