feat: launch endpoint to insert anime only with malId

This commit is contained in:
Rafi Arrafif
2026-01-27 21:22:08 +07:00
parent 379a5b4b38
commit 2f1e37ce52
7 changed files with 39 additions and 36 deletions

View File

@ -21,6 +21,7 @@ Table medias {
mediaType MediaType [not null] mediaType MediaType [not null]
source String source String
studios studios [not null] studios studios [not null]
characters characters [not null]
onDraft Boolean [not null, default: true] onDraft Boolean [not null, default: true]
uploader users [not null] uploader users [not null]
uploadedBy String [not null] uploadedBy String [not null]
@ -90,6 +91,7 @@ Table characters {
deletedAt DateTime deletedAt DateTime
createdAt DateTime [default: `now()`, not null] createdAt DateTime [default: `now()`, not null]
updatedAt DateTime [default: `now()`, not null] updatedAt DateTime [default: `now()`, not null]
medias medias [not null]
voice_actors lang_va_char [not null] voice_actors lang_va_char [not null]
} }
@ -98,8 +100,8 @@ Table voice_actors {
malId Int [unique, not null] malId Int [unique, not null]
name String [not null] name String [not null]
birthday DateTime birthday DateTime
description String [not null] description String
aboutUrl String [not null] aboutUrl String
imageUrl String imageUrl String
websiteUrl String websiteUrl String
createdBy users [not null] createdBy users [not null]
@ -523,6 +525,11 @@ Table MediaStudios {
mediasId String [ref: > medias.id] mediasId String [ref: > medias.id]
} }
Table MediaCharacters {
charactersId String [ref: > characters.id]
mediasId String [ref: > medias.id]
}
Table MediaCollections { Table MediaCollections {
collectionsId String [ref: > collections.id] collectionsId String [ref: > collections.id]
mediasId String [ref: > medias.id] mediasId String [ref: > medias.id]

View File

@ -23,26 +23,27 @@ generator dbml {
//// Prisma Model //// //// Prisma Model ////
model Media { model Media {
id String @id @default(uuid()) id String @id @default(uuid())
title String @db.Text title String @db.Text
titleAlternative Json titleAlternative Json
slug String @db.Text @unique slug String @db.Text @unique
malId Int? @unique malId Int? @unique
pictureMedium String @db.Text pictureMedium String @db.Text
pictureLarge String @db.Text pictureLarge String @db.Text
genres Genre[] @relation("MediaGenres") genres Genre[] @relation("MediaGenres")
country Country @default(JP) country Country @default(JP)
score Decimal @db.Decimal(4, 2) @default(0.00) score Decimal @db.Decimal(4, 2) @default(0.00)
status String status String
startAiring DateTime? startAiring DateTime?
endAiring DateTime? endAiring DateTime?
synopsis String @db.Text synopsis String @db.Text
ageRating String ageRating String
mediaType MediaType mediaType MediaType
source String? source String?
studios Studio[] @relation("MediaStudios") studios Studio[] @relation("MediaStudios")
onDraft Boolean @default(true) characters Character[] @relation("MediaCharacters")
uploader User @relation("UserUploadedMedias", fields: [uploadedBy], references: [id]) onDraft Boolean @default(true)
uploader User @relation("UserUploadedMedias", fields: [uploadedBy], references: [id])
uploadedBy String uploadedBy String
deletedAt DateTime? deletedAt DateTime?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
@ -124,6 +125,7 @@ model Character {
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt updatedAt DateTime @default(now()) @updatedAt
medias Media[] @relation("MediaCharacters")
voice_actors LangVAChar[] @relation("CharVALanguage") voice_actors LangVAChar[] @relation("CharVALanguage")
@@map("characters") @@map("characters")
} }

View File

@ -8,8 +8,7 @@ export const bulkInsertAnimeController = async (
ctx: Context & { body: { mal_id: number } }, ctx: Context & { body: { mal_id: number } },
) => { ) => {
try { try {
// const bulkInsertResult = await bulkInsertAnimeService(ctx.body.mal_id); const bulkInsertResult = await bulkInsertAnimeService(ctx.body.mal_id);
const bulkInsertResult = await bulkInsertCharWithVAService(ctx.body.mal_id);
return returnWriteResponse( return returnWriteResponse(
ctx.set, ctx.set,
201, 201,

View File

@ -6,6 +6,7 @@ import { InsertMediaRepository } from "../repositories/bulkinsertMedia.repositor
import { bulkInsertStudiosRepository } from "../repositories/bulkInsertStudios.repository"; import { bulkInsertStudiosRepository } from "../repositories/bulkInsertStudios.repository";
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type"; import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
import { generateSlug } from "../../../helpers/characters/generateSlug"; import { generateSlug } from "../../../helpers/characters/generateSlug";
import { bulkInsertCharWithVAService } from "./internal/bulkInsertCharWithVA.service";
export const bulkInsertAnimeService = async (malId: number) => { export const bulkInsertAnimeService = async (malId: number) => {
try { try {
@ -16,8 +17,9 @@ export const bulkInsertAnimeService = async (malId: number) => {
const insertedGenres = await bulkInsertGenresRepository(mediaFullInfo); const insertedGenres = await bulkInsertGenresRepository(mediaFullInfo);
const insertedStudios = await bulkInsertStudiosRepository(mediaFullInfo); const insertedStudios = await bulkInsertStudiosRepository(mediaFullInfo);
const insertedCharacters = await bulkInsertCharWithVAService(malId);
const constructMediaPayload = { const constructMediaPayload: Prisma.MediaUpsertArgs["create"] = {
title: mediaFullInfo.data.title, title: mediaFullInfo.data.title,
titleAlternative: (mediaFullInfo.data titleAlternative: (mediaFullInfo.data
.titles as unknown) as Prisma.InputJsonValue, .titles as unknown) as Prisma.InputJsonValue,
@ -32,6 +34,9 @@ export const bulkInsertAnimeService = async (malId: number) => {
studios: { studios: {
connect: insertedStudios.map((id) => ({ id })), connect: insertedStudios.map((id) => ({ id })),
}, },
characters: {
connect: insertedCharacters.map(({ id }) => ({ id })),
},
score: mediaFullInfo.data.score, score: mediaFullInfo.data.score,
pictureMedium: mediaFullInfo.data.images.webp.image_url, pictureMedium: mediaFullInfo.data.images.webp.image_url,
pictureLarge: mediaFullInfo.data.images.webp.large_image_url, pictureLarge: mediaFullInfo.data.images.webp.large_image_url,

View File

@ -30,7 +30,7 @@ export const bulkInsertCharWithVAService = async (malId: number) => {
const insertedVAs: { staffId: string; lang: string }[] = []; const insertedVAs: { staffId: string; lang: string }[] = [];
for (const VAEntries of charEntry.voice_actors) { for (const VAEntries of charEntry.voice_actors) {
const insertedVAId = await bulkInsertStaffOrPeopleService( const insertedVAId = await bulkInsertStaffOrPeopleService(
VAEntries.person.mal_id, VAEntries.person,
); );
insertedVAs.push({ insertedVAs.push({
staffId: insertedVAId.id, staffId: insertedVAId.id,

View File

@ -1,24 +1,14 @@
import { SystemAccountId } from "../../../../config/account/system"; import { SystemAccountId } from "../../../../config/account/system";
import { getPeopleAPI } from "../../../../config/apis/people.reference";
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
import { bulkInsertVoiceActorRepository } from "../../repositories/bulkInsertVoiceActor.repository"; import { bulkInsertVoiceActorRepository } from "../../repositories/bulkInsertVoiceActor.repository";
import { PeopleInfoResponse } from "../../types/peopleInfo"; import { Person } from "../../types/mediaCharWithVAInfo";
export const bulkInsertStaffOrPeopleService = async (malId: number) => { export const bulkInsertStaffOrPeopleService = async (peopleData: Person) => {
try { try {
const { baseURL, getPeopleInfo } = getPeopleAPI(malId);
const peopleData = (await fetch(baseURL + getPeopleInfo).then((res) =>
res.json(),
)) as PeopleInfoResponse;
return await bulkInsertVoiceActorRepository({ return await bulkInsertVoiceActorRepository({
malId: peopleData.data.mal_id, malId: peopleData.mal_id,
name: peopleData.data.name, name: peopleData.name,
birthday: peopleData.data.birthday, imageUrl: peopleData.images.jpg.image_url,
description: peopleData.data.about,
aboutUrl: peopleData.data.url,
imageUrl: peopleData.data.images.jpg.image_url,
websiteUrl: peopleData.data.website_url,
creatorId: SystemAccountId, creatorId: SystemAccountId,
}); });
} catch (error) { } catch (error) {

View File

@ -35,7 +35,7 @@ enum Role {
Supporting = "Supporting", Supporting = "Supporting",
} }
interface VoiceActor { export interface VoiceActor {
person: Person; person: Person;
language: Language; language: Language;
} }
@ -47,7 +47,7 @@ enum Language {
Spanish = "Spanish", Spanish = "Spanish",
} }
interface Person { export interface Person {
mal_id: number; mal_id: number;
url: string; url: string;
images: PersonImages; images: PersonImages;