feat(trpc): media router mount/library/scrape/playback/danmaku
This commit is contained in:
parent
8839763f24
commit
f009d2cce4
|
|
@ -2,6 +2,7 @@
|
||||||
// Router
|
// Router
|
||||||
export { appRouter } from "./router/index.js";
|
export { appRouter } from "./router/index.js";
|
||||||
export type { AppRouter, RouterInputs, RouterOutputs, TrpcContext } from "./router/index.js";
|
export type { AppRouter, RouterInputs, RouterOutputs, TrpcContext } from "./router/index.js";
|
||||||
|
export { mediaRouter } from "./router/media.router.js";
|
||||||
|
|
||||||
// Service layer — usable without tRPC (tests, scripts)
|
// Service layer — usable without tRPC (tests, scripts)
|
||||||
export { userService } from "./services/user.service.js";
|
export { userService } from "./services/user.service.js";
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { userSchemas } from "@app/types";
|
||||||
import { userService } from "../services/user.service.js";
|
import { userService } from "../services/user.service.js";
|
||||||
import type { TrpcContext } from "../context.js";
|
import type { TrpcContext } from "../context.js";
|
||||||
import { authRouter } from "./auth.router.js";
|
import { authRouter } from "./auth.router.js";
|
||||||
|
import { mediaRouter } from "./media.router.js";
|
||||||
|
|
||||||
// ─── User router ────────────────────────────────────────────────────────
|
// ─── User router ────────────────────────────────────────────────────────
|
||||||
export const userRouter = t.router({
|
export const userRouter = t.router({
|
||||||
|
|
@ -34,6 +35,7 @@ export const userRouter = t.router({
|
||||||
export const appRouter = t.router({
|
export const appRouter = t.router({
|
||||||
user: userRouter,
|
user: userRouter,
|
||||||
auth: authRouter,
|
auth: authRouter,
|
||||||
|
media: mediaRouter,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ─── Type re-exports ────────────────────────────────────────────────────
|
// ─── Type re-exports ────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
import {
|
||||||
|
danmakuSchemas,
|
||||||
|
librarySchemas,
|
||||||
|
mountSchemas,
|
||||||
|
playbackSchemas,
|
||||||
|
scrapeSchemas,
|
||||||
|
} from "@app/types";
|
||||||
|
import { t } from "../context.js";
|
||||||
|
import { danmakuService } from "../services/danmaku.service.js";
|
||||||
|
import { libraryService } from "../services/library.service.js";
|
||||||
|
import { mountService } from "../services/mount.service.js";
|
||||||
|
import { playbackService } from "../services/playback.service.js";
|
||||||
|
import { protectedProcedure } from "../services/procedure.js";
|
||||||
|
import { scrapeService } from "../services/scrape.service.js";
|
||||||
|
|
||||||
|
export const mediaRouter = t.router({
|
||||||
|
mountList: protectedProcedure
|
||||||
|
.input(mountSchemas.list)
|
||||||
|
.query(({ ctx }) => mountService.list(ctx.userId)),
|
||||||
|
mountCreate: protectedProcedure
|
||||||
|
.input(mountSchemas.create)
|
||||||
|
.mutation(({ ctx, input }) => mountService.create(ctx.userId, input)),
|
||||||
|
mountUpdate: protectedProcedure
|
||||||
|
.input(mountSchemas.update)
|
||||||
|
.mutation(({ ctx, input }) => mountService.update(ctx.userId, input)),
|
||||||
|
mountDelete: protectedProcedure
|
||||||
|
.input(mountSchemas.delete)
|
||||||
|
.mutation(({ ctx, input }) => mountService.delete(ctx.userId, input.id)),
|
||||||
|
mountTest: protectedProcedure
|
||||||
|
.input(mountSchemas.test)
|
||||||
|
.mutation(({ input }) => mountService.test(input)),
|
||||||
|
mountListDir: protectedProcedure
|
||||||
|
.input(mountSchemas.listDir)
|
||||||
|
.query(({ ctx, input }) => mountService.listDir(ctx.userId, input)),
|
||||||
|
|
||||||
|
libraryList: protectedProcedure
|
||||||
|
.input(librarySchemas.list)
|
||||||
|
.query(({ ctx, input }) => libraryService.list(ctx.userId, input)),
|
||||||
|
libraryGet: protectedProcedure
|
||||||
|
.input(librarySchemas.get)
|
||||||
|
.query(({ ctx, input }) => libraryService.get(ctx.userId, input.id)),
|
||||||
|
libraryScan: protectedProcedure
|
||||||
|
.input(librarySchemas.scan)
|
||||||
|
.mutation(({ ctx, input }) => libraryService.scan(ctx.userId, input.mountId)),
|
||||||
|
|
||||||
|
scrapeSearch: protectedProcedure
|
||||||
|
.input(scrapeSchemas.search)
|
||||||
|
.query(({ input }) => scrapeService.search(input.q)),
|
||||||
|
scrapeBind: protectedProcedure
|
||||||
|
.input(scrapeSchemas.bind)
|
||||||
|
.mutation(({ ctx, input }) =>
|
||||||
|
scrapeService.bind(ctx.userId, input.mediaItemId, input.bangumiId),
|
||||||
|
),
|
||||||
|
scrapeRescrape: protectedProcedure
|
||||||
|
.input(scrapeSchemas.rescrape)
|
||||||
|
.mutation(({ ctx, input }) =>
|
||||||
|
scrapeService
|
||||||
|
.autoScrape(ctx.userId, input.mediaItemId)
|
||||||
|
.then(() => ({ success: true as const })),
|
||||||
|
),
|
||||||
|
|
||||||
|
playbackReport: protectedProcedure
|
||||||
|
.input(playbackSchemas.report)
|
||||||
|
.mutation(({ ctx, input }) => playbackService.report(ctx.userId, input)),
|
||||||
|
playbackGet: protectedProcedure
|
||||||
|
.input(playbackSchemas.get)
|
||||||
|
.query(({ ctx, input }) => playbackService.get(ctx.userId, input.mediaItemId)),
|
||||||
|
|
||||||
|
danmakuFetch: protectedProcedure
|
||||||
|
.input(danmakuSchemas.fetch)
|
||||||
|
.query(({ ctx, input }) => danmakuService.fetch(ctx.userId, input.mediaItemId)),
|
||||||
|
danmakuImportMeta: protectedProcedure
|
||||||
|
.input(danmakuSchemas.importMeta)
|
||||||
|
.mutation(({ ctx, input }) =>
|
||||||
|
danmakuService.importMeta(ctx.userId, input.mediaItemId, input.byteSize),
|
||||||
|
),
|
||||||
|
danmakuGetSettings: protectedProcedure.input(danmakuSchemas.getSettings).query(() => ({
|
||||||
|
enabled: true,
|
||||||
|
opacity: 0.8,
|
||||||
|
density: 1,
|
||||||
|
})),
|
||||||
|
danmakuSaveSettings: protectedProcedure
|
||||||
|
.input(danmakuSchemas.settings)
|
||||||
|
.mutation(({ input }) => input),
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import { t } from "../context.js";
|
||||||
|
import { authService } from "./auth.service.js";
|
||||||
|
|
||||||
|
/** 需要登录;解析出 userId 注入 ctx。 */
|
||||||
|
export const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
|
||||||
|
if (!ctx.sessionToken) {
|
||||||
|
throw new TRPCError({ code: "UNAUTHORIZED", message: "请先登录" });
|
||||||
|
}
|
||||||
|
const user = await authService.getSessionUser(ctx.sessionToken);
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError({ code: "UNAUTHORIZED", message: "请先登录" });
|
||||||
|
}
|
||||||
|
return next({
|
||||||
|
ctx: {
|
||||||
|
sessionToken: ctx.sessionToken,
|
||||||
|
setCookie: ctx.setCookie,
|
||||||
|
userId: user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue