Feat: Add ACGM API
随机动漫音乐曲库可根据 id 和番名添加(无鉴权),目录结构调整,前端部分内容更正
This commit is contained in:
parent
48d289b076
commit
0dbad9a6a6
|
|
@ -4,6 +4,13 @@ import { defineConfig } from '@midwayjs/hooks-kit';
|
|||
import { resolve } from "path";
|
||||
|
||||
export default defineConfig({
|
||||
source: "./src/server",
|
||||
routes: [
|
||||
{
|
||||
baseDir: "api",
|
||||
basePath: "/api"
|
||||
}
|
||||
],
|
||||
vite: {
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
|
|
|
|||
|
|
@ -16,5 +16,6 @@ model ACGM {
|
|||
bangumi String?
|
||||
music_id Int @unique
|
||||
created_at DateTime @default(now())
|
||||
enabled Boolean @default(true)
|
||||
updated_at DateTime?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ export const About = () => {
|
|||
<>
|
||||
<h3>关于本项目</h3>
|
||||
<p>保罗 API 基本上作为一只辅助角色,默默无闻的服务着其他主要项目,这便是它存在的意义。像「随机动漫壁纸」接口就是为 <a href="https://github.com/Dreamer-Paul/Single" target="_blank">Single</a> 主题量身定做的,既符合主题外观特性,又能满足其他人的快捷使用。它诞生于 2018 年 4 月,是保罗入门后端和 PHP 语言的主要项目之一。</p>
|
||||
<p>项目后端采用原生 PHP 编写,前端是原生 CSS 和 JS,也就是非前后端分离项目,不需要额外的前端 SSR 服务。它没有任何框架加持(自己写的),所以执行速度和并发还是个谜。尽管如此,它也较为稳定的跑了这么久,不是吗?</p>
|
||||
<p>项目后端采用 MidwayJS 重构,前端是 React,相较于原先的 PHP 版本,性能确实略快了一些,就是没有 SSR。</p>
|
||||
<ul>
|
||||
<li>前端:React (CSR)</li>
|
||||
<li>后端:MidwayJS (NodeJS)</li>
|
||||
<li>数据库:MariaDB</li>
|
||||
<li>缓存:Redis</li>
|
||||
<li>前端:React (CSR)</li>
|
||||
<li>后端:MidwayJS (NodeJS)</li>
|
||||
<li>数据库:MariaDB</li>
|
||||
<li>缓存:Redis</li>
|
||||
</ul>
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ function FrontWrapper(props: FrontWrapperProps) {
|
|||
else if (name) {
|
||||
document.title = String(name);
|
||||
}
|
||||
}, []);
|
||||
}, [location.pathname]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
window.scrollTo({ top: 0, left: 0 });
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
|
||||
import { useRequest } from "ahooks";
|
||||
|
||||
import getStat from "../api/stat";
|
||||
import getStat from "../server/api/stat";
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
import ArticleHead from "@/components/Layout/ArticleHead";
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ function Netease() {
|
|||
|
||||
<h3>示例:</h3>
|
||||
<p>通过 ID 获得一首歌的信息</p>
|
||||
<pre className="language-javascript"><code>{`https://api.paugram.com/netease/?id=448143347
|
||||
<pre className="language-javascript"><code>{`https://api.paugram.com/api/netease/?id=448143347
|
||||
|
||||
// 返回的是:
|
||||
|
||||
|
|
@ -137,11 +137,11 @@ function Netease() {
|
|||
}
|
||||
`}</code></pre>
|
||||
<p>通过 ID 获得一首歌,并跳转到实际地址</p>
|
||||
<pre><code>https://api.paugram.com/netease/?id=517567145&play=true</code></pre>
|
||||
<pre><code>https://api.paugram.com/api/netease/?id=517567145&play=true</code></pre>
|
||||
<p>结合 Kico Style 和 Kico Player 使用本 API</p>
|
||||
<pre className="language-javascript"><code>{`ks.ajax({
|
||||
method: "GET",
|
||||
url: \`https://api.paugram.com/netease/?id=\${id}\`,
|
||||
url: \`https://api.paugram.com/api/netease/?id=\${id}\`,
|
||||
success: (req) => {
|
||||
const item = JSON.parse(req.response);
|
||||
声明的播放器.add([item]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
import { Api, Post, Query, useContext, useInject } from "@midwayjs/hooks";
|
||||
import { RedisService } from "@midwayjs/redis";
|
||||
import { prisma } from "../../utils/prisma";
|
||||
|
||||
import { getSong } from "../../utils/netease";
|
||||
|
||||
export default Api(
|
||||
Post(),
|
||||
Query<{ id: string, bangumi: string }>(),
|
||||
async () => {
|
||||
const ctx = useContext();
|
||||
const client = await useInject(RedisService);
|
||||
|
||||
const { id, bangumi } = ctx.query;
|
||||
|
||||
if (!id || !bangumi) {
|
||||
return {
|
||||
code: 0,
|
||||
msg: "Required id or bangumi"
|
||||
}
|
||||
}
|
||||
|
||||
// 查重
|
||||
const isExist = await prisma.aCGM.findUnique({
|
||||
where: {
|
||||
music_id: Number(id)
|
||||
}
|
||||
});
|
||||
|
||||
if (isExist) {
|
||||
return {
|
||||
code: 0,
|
||||
msg: "this song are existed"
|
||||
}
|
||||
}
|
||||
|
||||
let result;
|
||||
|
||||
// 尝试使用缓存
|
||||
const cached = await client.lrange(`api-next:163:${id}`, 0, 7);
|
||||
|
||||
if (cached.length) {
|
||||
result = {
|
||||
id: Number(id),
|
||||
title: cached[0],
|
||||
artist: cached[1],
|
||||
album: cached[2],
|
||||
alias: cached[3],
|
||||
cover: cached[4],
|
||||
lyric: cached[5],
|
||||
sub_lyric: cached[6],
|
||||
link: cached[7],
|
||||
served: Boolean(cached[8]),
|
||||
cached: true
|
||||
};
|
||||
}
|
||||
|
||||
// 全新获取
|
||||
const song = await getSong(id);
|
||||
|
||||
if (song) {
|
||||
await client.rpush(`api-next:163:${id}`,
|
||||
song.title,
|
||||
song.artist,
|
||||
song.album,
|
||||
song.alias,
|
||||
song.cover,
|
||||
song.lyric,
|
||||
song.sub_lyric,
|
||||
song.link,
|
||||
song.served,
|
||||
err => {
|
||||
err && console.log(err);
|
||||
}
|
||||
);
|
||||
await client.expire(`api-next:163:${id}`, 21600);
|
||||
|
||||
console.log(song);
|
||||
|
||||
result = {
|
||||
...song,
|
||||
cached: false
|
||||
}
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
|
||||
// 有数据支撑
|
||||
if (result) {
|
||||
// 创建数据
|
||||
await prisma.aCGM.create({
|
||||
data: {
|
||||
title: result.title,
|
||||
artist: result.artist,
|
||||
album: result.album,
|
||||
alias: result.alias,
|
||||
bangumi,
|
||||
music_id: Number(id),
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
msg: "Success",
|
||||
data: result
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
code: 0,
|
||||
msg: "Failed",
|
||||
data: undefined
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
|
||||
import { RedisService } from "@midwayjs/redis";
|
||||
import { prisma } from "./utils/prisma";
|
||||
import { prisma } from "../../utils/prisma";
|
||||
|
||||
import { getSong } from "./utils/netease";
|
||||
import { getSong } from "../../utils/netease";
|
||||
|
||||
export default Api(
|
||||
Get(),
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
|
||||
import { RedisService } from "@midwayjs/redis";
|
||||
|
||||
import { getVideoInfo } from "./utils/bili";
|
||||
import { getVideoInfo } from "../utils/bili";
|
||||
|
||||
const availableStyle = ["gray", "white", "black", "shadow"];
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
|
||||
import { RedisService } from "@midwayjs/redis";
|
||||
|
||||
import { getSong } from "./utils/netease";
|
||||
import { getSong } from "../utils/netease";
|
||||
|
||||
export default Api(
|
||||
Get(),
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
|
||||
import { RedisService } from "@midwayjs/redis";
|
||||
|
||||
import { source } from "./data/wallpaper";
|
||||
import { source } from "../data/wallpaper";
|
||||
import { random } from "lodash";
|
||||
|
||||
export default Api(
|
||||
|
|
@ -12,6 +12,7 @@ export default createConfiguration({
|
|||
imports: [Koa, redis, hooks()],
|
||||
importConfigs: [{
|
||||
default: {
|
||||
keys: "session_keys",
|
||||
redis: {
|
||||
client: {
|
||||
port: Number(env.parsed ?. CACHE_PORT) || 6379,
|
||||
|
|
@ -46,7 +46,7 @@ export const parseSongData = async (item: any) => {
|
|||
id: item.id,
|
||||
title: item.name,
|
||||
artist: item.artists ?. [0].name || "",
|
||||
alias: item.alias ?. [0] || "",
|
||||
alias: item.transName || (Array.isArray(item.alias) ? (item.alias[0] || "") : ""),
|
||||
album: item.album.name || "",
|
||||
cover: `${item.album.picUrl.replace("http://", "https://")}?param=250y250"`,
|
||||
lyric,
|
||||
Loading…
Reference in New Issue