From f43d78c7c606ea093913214fc07e976098bc9ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E5=88=80=E9=B1=BC?= <9903082+qdyovo@user.noreply.gitee.com> Date: Tue, 15 Oct 2024 14:22:12 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=B7=BB=E5=8A=A0=E7=BD=91?= =?UTF-8?q?=E6=98=93=E4=BA=91=E6=89=AB=E7=A0=81=E7=99=BB=E5=BD=95/?= =?UTF-8?q?=E7=BD=91=E6=98=93=E4=BA=91=E7=99=BB=E5=BD=95=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/tools.js | 145 ++++++++++++++++++++++++++++++++++++++++-- config/tools.yaml | 5 ++ constants/constant.js | 12 ++++ guoba.support.js | 42 +++++++++++- 4 files changed, 199 insertions(+), 5 deletions(-) diff --git a/apps/tools.js b/apps/tools.js index 5dcdf86..8d4f7a6 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -23,7 +23,7 @@ import { SUMMARY_PROMPT, transMap, TWITTER_BEARER_TOKEN, - XHS_NO_WATERMARK_HEADER, + XHS_NO_WATERMARK_HEADER } from "../constants/constant.js"; import { ANIME_SERIES_SEARCH_LINK, @@ -123,7 +123,7 @@ export class tools extends plugin { priority: 300, rule: [ { - reg: `^(翻|trans)[${ tools.Constants.existsTransKey }]`, + reg: `^(翻|trans)[${tools.Constants.existsTransKey}]`, fnc: "trans", }, { @@ -214,7 +214,18 @@ export class tools extends plugin { { reg: '^#验车(.*?)', fnc: 'yc' - } + }, + { + reg: "^#(网易云登录状态|网易状态|网易云状态)$", + fnc: "neteaseStatus", + permission: 'master', + }, + { + reg: "^#(网易云扫码登录|网易扫码登录)$", + fnc: 'netease_scan', + permission: 'master', + }, + ], }); // 配置文件 @@ -226,7 +237,7 @@ export class tools extends plugin { // 魔法接口 this.proxyAddr = this.toolsConfig.proxyAddr; this.proxyPort = this.toolsConfig.proxyPort; - this.myProxy = `http://${ this.proxyAddr }:${ this.proxyPort }`; + this.myProxy = `http://${this.proxyAddr}:${this.proxyPort}`; // 加载识别前缀 this.identifyPrefix = this.toolsConfig.identifyPrefix; // 加载直播录制时长 @@ -251,6 +262,14 @@ export class tools extends plugin { this.biliUseBBDown = this.toolsConfig.biliUseBBDown; // 加载 BBDown 的CDN配置 this.biliCDN = this.toolsConfig.biliCDN; + // 加载网易云Cookie + this.neteaseCookie = this.toolsConfig.neteaseCookie + // 加载是否自建服务器 + this.useLocalNeteaseAPI = this.toolsConfig.useLocalNeteaseAPI + // 加载自建服务器API + this.neteaseCloudAPIServer = this.toolsConfig.neteaseCloudAPIServer + // 加载网易云解析最高音质 + this.neteaseCloudAudioQuality = this.toolsConfig.neteaseCloudAudioQuality // 加载哔哩哔哩是否使用Aria2 this.biliDownloadMethod = this.toolsConfig.biliDownloadMethod; // 加载哔哩哔哩最高分辨率 @@ -1361,6 +1380,124 @@ export class tools extends plugin { return true; } + // 网易云登录状态 + async neteaseStatus(e) { + // 优先判断是否使用自建 API + let autoSelectNeteaseApi + // 判断海外 + const isOversea = await this.isOverseasServer(); + if (this.useLocalNeteaseAPI) { + // 使用自建 API + autoSelectNeteaseApi = this.neteaseCloudAPIServer + } else { + // 自动选择 API + autoSelectNeteaseApi = isOversea ? NETEASE_SONG_DOWNLOAD : NETEASE_API_CN; + } + const statusUrl = autoSelectNeteaseApi + '/login/status' + axios.get(statusUrl, { + headers: { + "User-Agent": COMMON_USER_AGENT, + "Cookie": this.neteaseCookie + }, + }).then(res => { + // logger.info('登录状态', res.data) + const userInfo = res.data.data.profile + if (userInfo) { + axios.get(`${autoSelectNeteaseApi}/vip/info?uid=${userInfo.userId}`, { + headers: { + "User-Agent": COMMON_USER_AGENT, + "Cookie": this.neteaseCookie + }, + }).then(res => { + // logger.info('vip信息', res.data) + const vipInfo = res.data.data + if (vipInfo.redplus.code != 0) { + const expireTime = new Date(vipInfo.redplus.expireTime).toLocaleString(); + e.reply([segment.image(`${userInfo.avatarUrl}?param=158y158`), `网易云已登录:\n${userInfo.nickname}\n会员等级:\nSVIP${vipInfo.redplus.vipLevel}\n最高解析音质:\njymaster(超清母带)\n会员到期时间:\n${expireTime}`]); + } else if (vipInfo.associator.code != 0) { + const expireTime = new Date(vipInfo.associator.expireTime).toLocaleString(); + e.reply([segment.image(`${userInfo.avatarUrl}?param=158y158`), `网易云已登录:\n${userInfo.nickname}\n会员等级:\nVIP${vipInfo.associator.vipLevel}\n最高解析音质:\lossless(无损)\n会员到期时间:\n${expireTime}`]); + } else { + e.reply([segment.image(`${userInfo.avatarUrl}?param=158y158`), `网易云已登录:\n${userInfo.nickname}\n会员等级:\n暂无VIP\n最高解析音质:\exhigh(极高)`]); + } + }) + } else { + e.reply('暂未登录,请发#网易云扫码登陆进行登陆绑定ck') + } + }) + } + // 网易扫码登录 + async netease_scan(e) { + // 优先判断是否使用自建 API + let autoSelectNeteaseApi + // 判断海外 + const isOversea = await this.isOverseasServer(); + if (this.useLocalNeteaseAPI) { + // 使用自建 API + autoSelectNeteaseApi = this.neteaseCloudAPIServer + } else { + // 自动选择 API + autoSelectNeteaseApi = isOversea ? NETEASE_SONG_DOWNLOAD : NETEASE_API_CN; + } + // 获取登录key + let keyUrl = autoSelectNeteaseApi + '/login/qr/key' + axios.get(keyUrl, { + headers: { + "User-Agent": COMMON_USER_AGENT + }, + }).then(res => { + // 获取登录二维码 + const unikey = res.data.data.unikey + let url = autoSelectNeteaseApi + '/login/qr/create?key=' + unikey + "&qrimg=true" + axios.get(url, { + headers: { + "User-Agent": COMMON_USER_AGENT, + }, + }).then(res => { + e.reply([segment.image(res.data.data.qrimg), '请在30秒内使用网易云APP进行扫码']); + }) + + //最大轮询次数 5s/check + let pollCount = 0; // 轮询计数器 + const maxPolls = 6; // 最大轮询次数 + + function pollRequest() { + let pollUrl = autoSelectNeteaseApi + '/login/qr/check?key=' + unikey + '×tamp=' + Date.now() + axios.get(pollUrl, { + headers: { + "User-Agent": COMMON_USER_AGENT, + }, + }).then(res => { + if (res.data.code == '800') { + e.reply(`二维码过期,请重新获取`); + clearInterval(intervalId); + return + } + if (res.data.code == '803') { + config.updateField("tools", "neteaseCookie", res.data.cookie) + const regex = /music_u=([^;]+)/i; // 使用 'i' 进行不区分大小写匹配 + const match = res.data.cookie.match(regex); + if (match) { + config.updateField("tools", "neteaseCookie", match[0]) + } + // logger.info('ck------', match[0]) + e.reply(`扫码登录成功,ck已自动保存`); + clearInterval(intervalId); + return + } + pollCount++ + // logger.info('登录erweima',res) + }) + if (pollCount >= maxPolls) { + clearInterval(intervalId); // 停止轮询 + logger.info('超时轮询已停止'); + e.reply('扫码超时,请重新获取'); + } + } + const intervalId = setInterval(pollRequest, 5000); + }) + } + // 网易云解析 async netease(e) { let message = diff --git a/config/tools.yaml b/config/tools.yaml index 96b57cd..019c01f 100644 --- a/config/tools.yaml +++ b/config/tools.yaml @@ -22,6 +22,11 @@ biliCDN: 0 # 哔哩哔哩 CDN,默认为0表示不使用 biliDownloadMethod: 0 # 哔哩哔哩的下载方式:0默认使用原生稳定的下载方式,如果你在乎内存可以使用轻量的wget和axel下载方式,如果在乎性能可以使用Aria2下载 biliResolution: 1 # 哔哩哔哩的下载画质,0为原画,1为清晰画,2为流畅画(默认为0) +useLocalNeteaseAPI: false #是否使用网易云解析自建API +neteaseCookie: '' #网易云ck +neteaseCloudAPIServer: '' #网易云自建服务器地址 +neteaseCloudAudioQuality: exhigh #网易云解析最高音质 默认exhigh(极高) 分类:standard => 标准,higher => 较高, exhigh=>极高, lossless=>无损, hires=>Hi-Res, jyeffect => 高清环绕声, sky => 沉浸环绕声, dolby => 杜比全景声, jymaster => 超清母带 + YouTubeGraphicsOptions: 720 #YouTobe的下载画质,0为原画,1080,720,480,自定义画面高度(默认为720) douyinCookie: '' # douyin's cookie, 格式:odin_tt=xxx;passport_fe_beating_status=xxx;sid_guard=xxx;uid_tt=xxx;uid_tt_ss=xxx;sid_tt=xxx;sessionid=xxx;sessionid_ss=xxx;sid_ucp_v1=xxx;ssid_ucp_v1=xxx;passport_assist_user=xxx;ttwid=xxx; diff --git a/constants/constant.js b/constants/constant.js index 15c7a99..da62f8f 100644 --- a/constants/constant.js +++ b/constants/constant.js @@ -193,6 +193,18 @@ export const YOUTUBE_GRAPHICS_LIST = Object.freeze([ { label: '720P 高清', value: 720 }, { label: '480P 清晰', value: 480 }, ]); + +export const NETEASECLOUD_QUALITY_LIST = Object.freeze([ + { label: '标准', value: 'standard' }, + { label: '较高', value: 'higher' }, + { label: '极高', value: 'exhigh' }, + { label: '无损', value: 'lossless' }, + { label: 'Hi-Res', value: 'hires' }, + { label: '高清环绕声', value: 'jyeffect' }, + { label: '沉浸环绕声', value: 'sky' }, + { label: '杜比全景声', value: 'dolby' }, + { label: '超清母带', value: 'jymaster' }, +]); /** * 消息撤回时间 * @type {number} diff --git a/guoba.support.js b/guoba.support.js index 257c5f2..774a632 100644 --- a/guoba.support.js +++ b/guoba.support.js @@ -1,6 +1,6 @@ import _ from "lodash"; import path from "path"; -import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD, BILI_RESOLUTION_LIST, YOUTUBE_GRAPHICS_LIST } from "./constants/constant.js"; +import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD, BILI_RESOLUTION_LIST, YOUTUBE_GRAPHICS_LIST, NETEASECLOUD_QUALITY_LIST } from "./constants/constant.js"; import model from "./model/config.js"; const pluginName = `rconsole-plugin`; @@ -230,6 +230,46 @@ export function supportGuoba() { options: YOUTUBE_GRAPHICS_LIST, } }, + { + field: "tools.useLocalNeteaseAPI", + label: "使用自建网易云API", + bottomHelpMessage: + "默认不开启,有条件可以查看https://gitlab.com/Binaryify/neteasecloudmusicapi进行搭建", + component: "Switch", + required: false, + }, + { + field: "tools.neteaseCloudAPIServer", + label: "自建网易云API地址", + bottomHelpMessage: + "填入自建API地址,例:http://xxxxxxxx", + component: "Input", + required: false, + componentProps: { + placeholder: "填入自建API地址", + }, + }, + { + field: "tools.neteaseCookie", + label: "网易云Cookie", + bottomHelpMessage: + "可以发送 #网易云扫码登陆 快捷获取 或 者在网易云官网自己获取", + component: "Input", + required: false, + componentProps: { + placeholder: "使用vip账号登陆获取更高音质解析", + }, + }, + { + field: "tools.neteaseCloudAudioQuality", + label: "网易云解析最高音质", + bottomHelpMessage: + "网易云解析最高音质(需vip账号ck!!! 默认极高,更高请根据登陆的账号和服务器承载能力进行选择)", + component: "Select", + componentProps: { + options: NETEASECLOUD_QUALITY_LIST, + } + }, { field: "tools.douyinCookie", label: "抖音的Cookie",