From 131da9292fb506701a3faf39ff5c1640dce330a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=B6=9B?= Date: Sat, 24 Jun 2023 15:50:12 +0800 Subject: [PATCH] feat: support modfiy movie name that is incorrect --- domains/drive/index.ts | 2 +- domains/searcher/index.ts | 1 + domains/tmdb/services.ts | 1 + package.json | 2 +- pages/api/admin/movie/[id].ts | 3 +- pages/api/admin/shared_file/save.ts | 7 +- pages/api/admin/tmdb/search.ts | 12 +++- pages/api/admin/unknown_movie/list.ts | 60 ++++++++++++++++ pages/api/admin/unknown_movie/update/[id].ts | 73 ++++++++++++++++++++ utils/__tests__/movie.test.ts | 12 ++++ utils/index.ts | 6 +- 11 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 pages/api/admin/unknown_movie/list.ts create mode 100644 pages/api/admin/unknown_movie/update/[id].ts diff --git a/domains/drive/index.ts b/domains/drive/index.ts index 05b5a15a..49338565 100644 --- a/domains/drive/index.ts +++ b/domains/drive/index.ts @@ -232,7 +232,7 @@ export class Drive extends BaseDomain { } has_root_folder() { - if (this.profile.root_folder_id === null) { + if (!this.profile.root_folder_id || !this.profile.root_folder_name) { return false; } return true; diff --git a/domains/searcher/index.ts b/domains/searcher/index.ts index efc810f1..3c9f9c5a 100644 --- a/domains/searcher/index.ts +++ b/domains/searcher/index.ts @@ -1012,6 +1012,7 @@ export class MediaSearcher extends BaseDomain { // log(`[${prefix}]`, "使用", original_name, "搜索到的结果为", tv_profile.name || tv_profile.original_name); return Result.Ok(movie_profile); } + /** 新增电影和电影详情 */ async add_movie_from_parsed_movie(body: { parsed_movie: ParsedMovieRecord }) { const { parsed_movie } = body; const { id, name, original_name, correct_name } = parsed_movie; diff --git a/domains/tmdb/services.ts b/domains/tmdb/services.ts index 47e07b19..d4a9a7eb 100644 --- a/domains/tmdb/services.ts +++ b/domains/tmdb/services.ts @@ -193,6 +193,7 @@ export async function search_movie_in_tmdb(keyword: string, options: TMDBRequest name: title, original_name: original_title, air_date: release_date, + first_air_date: release_date, ...fix_TMDB_image_path({ backdrop_path, poster_path, diff --git a/package.json b/package.json index 63ba8a1d..d9ae0be6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@family-flix/api", - "version": "1.2.1", + "version": "1.3.0", "private": true, "scripts": { "dev": "node static.js & next dev --port 3200", diff --git a/pages/api/admin/movie/[id].ts b/pages/api/admin/movie/[id].ts index 2820bc17..a04e816c 100644 --- a/pages/api/admin/movie/[id].ts +++ b/pages/api/admin/movie/[id].ts @@ -32,7 +32,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< }, }); if (tv === null) { - return e("没有匹配的电视剧记录"); + return e("没有匹配的电影记录"); } const data = (() => { @@ -47,6 +47,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< poster_path, backdrop_path, original_language, + tmdb_id: profile.tmdb_id, sources, }; })(); diff --git a/pages/api/admin/shared_file/save.ts b/pages/api/admin/shared_file/save.ts index 7845a7d3..44249a37 100644 --- a/pages/api/admin/shared_file/save.ts +++ b/pages/api/admin/shared_file/save.ts @@ -69,10 +69,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< } const drive = drive_res.data; const { profile, client } = drive; - if (!profile.root_folder_name) { - return e("请先为云盘添加索引根目录"); + if (!drive.has_root_folder()) { + return e("请先为云盘设置索引根目录"); } - // await client.fetch_share_profile(url, { force: true }); const r1 = await client.save_shared_files({ url, file_id, @@ -83,7 +82,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< await store.add_tmp_file({ name: file_name, type: FileType.Folder, - parent_paths: profile.root_folder_name, + parent_paths: profile.root_folder_name!, drive_id, user_id, }); diff --git a/pages/api/admin/tmdb/search.ts b/pages/api/admin/tmdb/search.ts index 93afad60..85e3884d 100644 --- a/pages/api/admin/tmdb/search.ts +++ b/pages/api/admin/tmdb/search.ts @@ -1,5 +1,5 @@ /** - * @file TMDB 搜索电视剧 + * @file TMDB 搜索影视剧 */ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type { NextApiRequest, NextApiResponse } from "next"; @@ -18,11 +18,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< page: page_str = "1", page_size: page_size_str = "20", token, + type = "1", } = req.query as Partial<{ keyword: string; page: string; page_size: string; token?: string; + /** 搜索电视剧1 还是电影2 */ + type?: string; }>; if (!keyword) { return e("缺少搜索关键字"); @@ -38,7 +41,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< }); const page = Number(page_str); const page_size = Number(page_size_str); - const r = await tmdb.search_tv(keyword, { page }); + const r = await (() => { + if (type === "2") { + return tmdb.search_movie(keyword, { page }); + } + return tmdb.search_tv(keyword, { page }); + })(); if (r.error) { return e(r); } diff --git a/pages/api/admin/unknown_movie/list.ts b/pages/api/admin/unknown_movie/list.ts new file mode 100644 index 00000000..59568a04 --- /dev/null +++ b/pages/api/admin/unknown_movie/list.ts @@ -0,0 +1,60 @@ +/** + * @file 获取未识别的电影 + */ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import type { NextApiRequest, NextApiResponse } from "next"; + +import { BaseApiResp } from "@/types"; +import { response_error_factory } from "@/utils/backend"; +import { store } from "@/store"; +import { User } from "@/domains/user"; + +export default async function handler(req: NextApiRequest, res: NextApiResponse>) { + const e = response_error_factory(res); + const { query } = req; + const { page: page_str = "1", page_size: page_size_str = "20" } = query as Partial<{ + page: string; + page_size: string; + }>; + const { authorization } = req.headers; + const t_res = await User.New(authorization, store); + if (t_res.error) { + return e(t_res); + } + const { id: user_id } = t_res.data; + const page = Number(page_str); + const page_size = Number(page_size_str); + + const where: NonNullable[number]>["where"] = { + movie_id: null, + user_id, + }; + const list = await store.prisma.parsed_movie.findMany({ + where, + orderBy: { + created: "desc", + }, + take: page_size, + skip: (page - 1) * page_size, + }); + const count = await store.prisma.parsed_movie.count({ where }); + res.status(200).json({ + code: 0, + msg: "", + data: { + page, + page_size, + total: count, + no_more: list.length + (page - 1) * page_size >= count, + list: list.map((parsed_season) => { + const { id, name, original_name, file_name } = parsed_season; + return { + id, + name, + original_name, + file_name, + }; + }), + }, + }); +} diff --git a/pages/api/admin/unknown_movie/update/[id].ts b/pages/api/admin/unknown_movie/update/[id].ts new file mode 100644 index 00000000..3af5616c --- /dev/null +++ b/pages/api/admin/unknown_movie/update/[id].ts @@ -0,0 +1,73 @@ +/** + * @file 更新未识别的电影名称 + */ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import type { NextApiRequest, NextApiResponse } from "next"; + +import { User } from "@/domains/user"; +import { BaseApiResp } from "@/types"; +import { response_error_factory } from "@/utils/backend"; +import { app, store } from "@/store"; +import { MediaSearcher } from "@/domains/searcher"; + +export default async function handler(req: NextApiRequest, res: NextApiResponse>) { + const e = response_error_factory(res); + const { authorization } = req.headers; + const { id } = req.query as Partial<{ id: string }>; + const { name } = req.body as Partial<{ name: string }>; + + if (!id) { + return e("缺少电影 id"); + } + if (!name) { + return e("缺少正确的电影名称"); + } + + const t_res = await User.New(authorization, store); + if (t_res.error) { + return e(t_res); + } + const user = t_res.data; + const parsed_movie = await store.prisma.parsed_movie.findFirst({ + where: { + id, + user_id: user.id, + }, + }); + if (!parsed_movie) { + return e("没有匹配的季"); + } + + const { drive_id } = parsed_movie; + if (parsed_movie.name === name) { + return e(`名称已经是 '${name}' 了`); + } + const searcher_res = await MediaSearcher.New({ + user_id: user.id, + drive_id, + tmdb_token: user.settings.tmdb_token, + assets: app.assets, + force: true, + store, + }); + if (searcher_res.error) { + return e(searcher_res); + } + const searcher = searcher_res.data; + const r = await searcher.add_movie_from_parsed_movie({ + parsed_movie: { + ...parsed_movie, + correct_name: name, + }, + }); + if (r.error) { + return e(r.error); + } + const r2 = await store.update_parsed_movie(parsed_movie.id, { + correct_name: name, + }); + if (r2.error) { + return e(r2); + } + res.status(200).json({ code: 0, msg: "修改成功", data: null }); +} diff --git a/utils/__tests__/movie.test.ts b/utils/__tests__/movie.test.ts index 72ec4c9f..39356afe 100644 --- a/utils/__tests__/movie.test.ts +++ b/utils/__tests__/movie.test.ts @@ -18,4 +18,16 @@ describe("电影", () => { episode_name: "UHD", }); }); + + test("Q 请回答1988蓝光版", () => { + const name = "Q 请回答1988蓝光版"; + const result = parse_filename_for_video(name); + expect(result).toStrictEqual({ + name: "请回答1988", + original_name: "", + season: "", + episode: "", + episode_name: "", + }); + }); }); diff --git a/utils/index.ts b/utils/index.ts index f4b3d31a..eb2b6c3f 100644 --- a/utils/index.ts +++ b/utils/index.ts @@ -306,11 +306,7 @@ export function parse_filename_for_video( { regexp: /GB/ }, // 分辨率 { - regexp: /蓝光/, - }, - { - key: k("resolution"), - regexp: /(蓝光){0,1}4[kK]/, + regexp: /蓝光版{0,1}/, }, { key: k("resolution"),