mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
✨ feat: 新增音源-gequbao
This commit is contained in:
107
electron/server/unblock/gequbao.ts
Normal file
107
electron/server/unblock/gequbao.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { SongUrlResult } from "./unblock";
|
||||
import { serverLog } from "../../main/logger";
|
||||
import axios from "axios";
|
||||
import { randomBytes } from "crypto";
|
||||
|
||||
/**
|
||||
* 搜索歌曲获取 ID
|
||||
* @param keyword 搜索关键词
|
||||
* @returns 歌曲 ID 或 null
|
||||
*/
|
||||
const search = async (keyword: string): Promise<string | null> => {
|
||||
try {
|
||||
const searchUrl = `https://www.gequbao.com/s/${encodeURIComponent(keyword)}`;
|
||||
const { data } = await axios.get(searchUrl);
|
||||
|
||||
// 匹配第一个歌曲链接 /music/12345
|
||||
// <a href="/music/17165" target="_blank" class="music-link d-block">
|
||||
const match = data.match(
|
||||
/<a href="\/music\/(\d+)" target="_blank" class="music-link d-block">/,
|
||||
);
|
||||
if (match && match[1]) {
|
||||
return match[1];
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
serverLog.error("❌ Get GequbaoSongId Error:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取播放 ID
|
||||
* @param id 歌曲 ID
|
||||
* @returns 播放 ID 或 null
|
||||
*/
|
||||
const getPlayId = async (id: string): Promise<string | null> => {
|
||||
try {
|
||||
const url = `https://www.gequbao.com/music/${id}`;
|
||||
const { data } = await axios.get(url);
|
||||
|
||||
// 匹配 window.appData 中的 play_id
|
||||
// "play_id":"EFwMVSQDBgsBQV5WBCUDAVkCSQ9WX3kFXV9XEl0KBSEaVldTR19NVndQVlhXRl5cUA=="
|
||||
const match = data.match(/"play_id":"(.*?)"/);
|
||||
if (match && match[1]) {
|
||||
return match[1];
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
serverLog.error("❌ Get GequbaoPlayId Error:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取歌曲 URL
|
||||
* @param keyword 搜索关键词
|
||||
* @returns 包含歌曲 URL 的结果对象
|
||||
*/
|
||||
const getGequbaoSongUrl = async (keyword: string): Promise<SongUrlResult> => {
|
||||
try {
|
||||
if (!keyword) return { code: 404, url: null };
|
||||
|
||||
// 1. 获取 ID
|
||||
const id = await search(keyword);
|
||||
if (!id) return { code: 404, url: null };
|
||||
|
||||
// 2. 获取 play_id
|
||||
const playId = await getPlayId(id);
|
||||
if (!playId) return { code: 404, url: null };
|
||||
|
||||
// 3. 获取播放链接
|
||||
const url = "https://www.gequbao.com/api/play-url";
|
||||
const headers = {
|
||||
accept: "application/json, text/javascript, */*; q=0.01",
|
||||
"accept-language": "zh-CN,zh;q=0.9",
|
||||
"cache-control": "no-cache",
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
pragma: "no-cache",
|
||||
priority: "u=1, i",
|
||||
"sec-ch-ua": '"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "same-origin",
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
cookie: `server_name_session=${randomBytes(16).toString("hex")}`,
|
||||
Referer: `https://www.gequbao.com/music/${id}`,
|
||||
};
|
||||
|
||||
const body = `id=${encodeURIComponent(playId)}`;
|
||||
|
||||
const { data } = await axios.post(url, body, { headers });
|
||||
|
||||
if (data.code === 1 && data.data && data.data.url) {
|
||||
serverLog.log("🔗 GequbaoSong URL:", data.data.url);
|
||||
return { code: 200, url: data.data.url };
|
||||
}
|
||||
|
||||
return { code: 404, url: null };
|
||||
} catch (error) {
|
||||
serverLog.error("❌ Get GequbaoSong URL Error:", error);
|
||||
return { code: 404, url: null };
|
||||
}
|
||||
};
|
||||
|
||||
export default getGequbaoSongUrl;
|
||||
@@ -1,9 +1,10 @@
|
||||
import { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
|
||||
import { SongUrlResult } from "./unblock";
|
||||
import { serverLog } from "../../main/logger";
|
||||
import getKuwoSongUrl from "./kuwo";
|
||||
import axios from "axios";
|
||||
import getKuwoSongUrl from "./kuwo";
|
||||
import getBodianSongUrl from "./bodian";
|
||||
import getGequbaoSongUrl from "./gequbao";
|
||||
|
||||
/**
|
||||
* 直接获取 网易云云盘 链接
|
||||
@@ -74,6 +75,18 @@ export const initUnblockAPI = async (fastify: FastifyInstance) => {
|
||||
return reply.send(result);
|
||||
},
|
||||
);
|
||||
// gequbao
|
||||
fastify.get(
|
||||
"/unblock/gequbao",
|
||||
async (
|
||||
req: FastifyRequest<{ Querystring: { [key: string]: string } }>,
|
||||
reply: FastifyReply,
|
||||
) => {
|
||||
const { keyword } = req.query;
|
||||
const result = await getGequbaoSongUrl(keyword);
|
||||
return reply.send(result);
|
||||
},
|
||||
);
|
||||
|
||||
serverLog.info("🌐 Register UnblockAPI successfully");
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "splayer",
|
||||
"productName": "SPlayer",
|
||||
"version": "3.0.0-beta.5",
|
||||
"version": "3.0.0-beta.6",
|
||||
"description": "A minimalist music player",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "imsyy",
|
||||
|
||||
@@ -494,6 +494,7 @@ const instantLyrics = computed(() => {
|
||||
}
|
||||
}
|
||||
.play-menu {
|
||||
margin-left: auto;
|
||||
max-width: 640px;
|
||||
.time-container {
|
||||
margin-right: 8px;
|
||||
|
||||
Reference in New Issue
Block a user