Feat: Add ACGM API

随机动漫音乐曲库可根据 id 和番名添加(无鉴权),目录结构调整,前端部分内容更正
This commit is contained in:
2022-04-23 01:36:02 +08:00
parent 48d289b076
commit 0dbad9a6a6
20 changed files with 140 additions and 16 deletions
+5 -5
View File
@@ -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>
</>
)
+1 -1
View File
@@ -28,7 +28,7 @@ function FrontWrapper(props: FrontWrapperProps) {
else if (name) {
document.title = String(name);
}
}, []);
}, [location.pathname]);
useLayoutEffect(() => {
window.scrollTo({ top: 0, left: 0 });
+1 -1
View File
@@ -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";
+3 -3
View File
@@ -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]);
+115
View File
@@ -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 -1
View File
@@ -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,