lx-source/src/middleware/loadpublic/public/lx-custom-source.js
2023-12-27 02:07:37 +08:00

134 lines
6.3 KiB
JavaScript
Raw 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.

/**
* @name Lx-Custom-Source
* @description Client
* version 1.0.1
* @author Zxwy
* @homepage https://github.com/ZxwyWebSite/lx-source
*/
// 脚本配置
const version = '1.0.3' // 脚本版本
const apiaddr = 'http://127.0.0.1:1011/' // 服务端地址,末尾加斜杠
const apipass = '' // 验证密钥,由服务端自动生成 '${apipass}'
const devmode = true // 调试模式
// 常量 & 默认值
const { EVENT_NAMES, request, on, send } = window.lx ?? globalThis.lx
const defs = { type: 'music', actions: ['musicUrl'] }
// const defaults = {
// type: 'music', // 目前固定为 music
// actions: ['musicUrl'], // 目前固定为 ['musicUrl']
// qualitys: ['128k', '320k', 'flac', 'flac24bit'], // 当前脚本的该源所支持获取的Url音质有效的值有['128k', '320k', 'flac', 'flac24bit']
// }
const defheaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 HBPC/12.1.2.300',
'Accept': 'application/json, text/plain, */*',
'X-LxM-Auth': apipass,
}
const conf = {
api: {
addr: apiaddr, // 服务端地址,末尾加斜杠
pass: apipass, // 验证密钥,由服务端自动生成 '${apipass}'
glbv: 'v1' // 大版本号
},
info: {
version: version, // 脚本版本
devmode: devmode, // 调试模式
},
}
const httpRequest = (url, options) => new Promise((resolve, reject) => {
options.headers = { ...defheaders, ...options.headers } // 添加默认请求头
request(url, options, (err, resp) => {
if (err) return reject(err)
resolve(resp.body)
})
})
const musicUrl = async (source, info, quality) => {
const start = new Date().getTime();
const id = info.hash ?? info.copyrightId ?? info.songmid // 音乐id kg源为hash, mg源为copyrightId
const ext = source == 'kg' ? info.albumId : source == 'tx' ? info.strMediaMid : ''
const query = `${source}/${id}${(ext != '' && ext != void 0) ? '-' + ext : ''}/${quality}`
console.log('创建任务: %s, 音乐信息: %O', query, info)
const body = await httpRequest(`${apiaddr}link/${query}`, { method: 'get' });
console.log('返回数据: %O', body, `, 耗时 ${new Date().getTime() - start} ms`)
return body.data != '' ? body.data : Promise.reject(body.msg) // 没有获取到链接则将msg作为错误抛出
}
// 注册应用API请求事件
// source 音乐源可能的值取决于初始化时传入的sources对象的源key值
// info 请求附加信息内容根据action变化
// action 请求操作类型目前只有musicUrl即获取音乐URL链接
// 当action为musicUrl时info的结构{type, musicInfo}
// info.type音乐质量可能的值有128k / 320k / flac / flac24bit取决于初始化时对应源传入的qualitys值中的一个
// info.musicInfo音乐信息对象里面有音乐ID、名字等信息
on(EVENT_NAMES.request, ({ source, action, info }) => {
// 回调必须返回 Promise 对象
switch (action) {
// action 为 musicUrl 时需要在 Promise 返回歌曲 url
case 'musicUrl':
return musicUrl(source, info.musicInfo, info.type).catch(err => {
console.log('发生错误: %o', err)
return Promise.reject(err)
})
}
})
// 脚本初始化 (目前只有检查更新)
const init = () => {
'use strict';
console.log('初始化脚本, 版本: %s, 服务端地址: %s', version, apiaddr)
var stat = false; var msg = ''; var updUrl = ''; var sourcess = {}
httpRequest(apiaddr, { method: 'get' })
.catch((err) => { msg = '初始化失败: ' + err ?? '连接服务端超时'; console.log(msg) })
.then((body) => {
if (!body) { msg = '初始化失败:' + '无返回数据'; return }
console.log('获取服务端数据成功: %o', body)
// 检查Api大版本
if (body.msg != `Hello~::^-^::~${conf.api.glbv}~`) {
msg = 'Api大版本不匹配请检查服务端与脚本是否兼容'; return
}
// 检查脚本更新
const script = body.script // 定位到Script部分
const lv = version.split('.'); const rv = script.ver.split('.') // 分别对主次小版本检查更新
for (var i = 0; i < 3; i++) {
if (lv[i] < rv[i]) {
console.log('发现更新, 版本: %s, 信息: %s, 地址: %s, 强制推送: %o', script.ver, script.log, script.url, script.force)
msg = `${script.force ? '强制' : '发现'}更新:` + script.log; updUrl = script.url; if (script.force) return; break
}
}
// 激活可用源
const source = body.source // 定位到Source部分
Object.keys(source).forEach(v => {
if (source[v] != null /*== true*/) {
sourcess[v] = {
name: v,
...defs, // ...defaults,
qualitys: source[v], // 支持返回音质时启用 使用后端音质表
}
}
})
// 完成初始化
stat = true
})
.finally(() => {
// 脚本初始化完成后需要发送inited事件告知应用
send(EVENT_NAMES.inited, {
status: stat, // 初始化成功 or 失败 (初始化失败不打开控制台, 使用更新提示接口返回信息)
openDevTools: stat ? devmode : false, // 是否打开开发者工具,方便用于调试脚本 'devmode' or 'stat ? devmode : false'
sources: sourcess, // 使用服务端源列表
// sources: { // 当前脚本支持的源
// wy: { name: '网易音乐', ...defaults, },
// mg: { name: '咪咕音乐', ...defaults, },
// kw: { name: '酷我音乐', ...defaults, },
// // kg: { name: '酷狗音乐', ...defaults, }, // 暂不支持,仅供换源
// },
})
// 发送更新提示
if (msg) send(EVENT_NAMES.updateAlert, { log: '提示:' + msg, updateUrl: updUrl ? apiaddr + updUrl : '' })
})
}
console.log('\n __ __ __ ______ ______ __ __ ____ ______ ______\n / / / / / / / ____/ / __ / / / / / / __ \\ / ____/ / ____/\n / / / /_/ / __ / /___ / / / / / / / / / /_/ / / / / /___\n / / \\_\\ \\ /_/ /___ / / / / / / / / / / ___/ / / / ____/\n / /___ / / / / ____/ / / /_/ / / /_/ / / / \\ / /___ / /___\n/_____/ /_/ /_/ /_____/ /_____/ /_____/ /_/ \\_\\ /_____/ /_____/\n=======================================================================\n')
init() // 启动!!!