diff --git a/prisma/dbml/schema.dbml b/prisma/dbml/schema.dbml index 279775c..4a08353 100644 --- a/prisma/dbml/schema.dbml +++ b/prisma/dbml/schema.dbml @@ -77,6 +77,37 @@ Table studios { medias medias [not null] } +Table characters { + id String [pk] + malId Int [unique, not null] + name String [not null] + role CharacterRole [not null] + favorites Int [not null, default: 0] + imageUrl String + smallImageUrl String + createdBy users [not null] + creatorId String [not null] + deletedAt DateTime + createdAt DateTime [default: `now()`, not null] + updatedAt DateTime [default: `now()`, not null] +} + +Table voice_actors { + id String [pk] + malId Int [unique, not null] + name String [not null] + birthday DateTime + description String [not null] + aboutUrl String [not null] + imageUrl String + websiteUrl String + createdBy users [not null] + creatorId String [not null] + deletedAt DateTime + createdAt DateTime [default: `now()`, not null] + updatedAt DateTime [default: `now()`, not null] +} + Table episodes { id String [pk] media medias [not null] @@ -172,6 +203,8 @@ Table users { media_approveds media_logs [not null] genres genres [not null] studios studios [not null] + characters characters [not null] + voice_actor voice_actors [not null] episodes episodes [not null] episode_likes episode_likes [not null] videos videos [not null] @@ -501,6 +534,11 @@ Enum Country { KR } +Enum CharacterRole { + Main + Supporting +} + Enum MediaOperation { create update @@ -605,6 +643,10 @@ Ref: genres.createdBy > users.id Ref: studios.createdBy > users.id +Ref: characters.creatorId > users.id + +Ref: voice_actors.creatorId > users.id + Ref: episodes.mediaId > medias.id Ref: episodes.uploadedBy > users.id diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 63131fb..c3a78ea 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -111,24 +111,25 @@ model Studio { } model Character { - id String @id @default(uuid()) @db.Uuid - name String - role CharacterRole - favorites Int @default(0) - imageUrl String? + id String @id @default(uuid()) @db.Uuid + malId Int @unique + name String + role CharacterRole + favorites Int @default(0) + imageUrl String? smallImageUrl String? - createdBy User @relation("UserCreatedCharacters", fields: [creatorId], references: [id]) - creatorId String - deletedAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt + createdBy User @relation("UserCreatedCharacters", fields: [creatorId], references: [id]) + creatorId String + deletedAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt @@map("characters") } model VoiceActor { id String @id @default(uuid()) @db.Uuid - malId Int + malId Int @unique name String birthday DateTime? description String @db.Text diff --git a/src/config/apis/media.reference.ts b/src/config/apis/media.reference.ts index 9f6cae9..e077bb8 100644 --- a/src/config/apis/media.reference.ts +++ b/src/config/apis/media.reference.ts @@ -2,5 +2,6 @@ export const getContentReferenceAPI = (malId: number) => { return { baseURL: "https://api.jikan.moe/v4", getMediaFullInfo: `/anime/${malId}/full`, + getMediaCharactersWithVA: `/anime/${malId}/characters`, }; }; diff --git a/src/modules/internal/controllers/bulkInsertAnime.controller.ts b/src/modules/internal/controllers/bulkInsertAnime.controller.ts index 9bb78c3..6fe2267 100644 --- a/src/modules/internal/controllers/bulkInsertAnime.controller.ts +++ b/src/modules/internal/controllers/bulkInsertAnime.controller.ts @@ -2,12 +2,14 @@ import { Context } from "elysia"; import { mainErrorHandler } from "../../../helpers/error/handler"; import { bulkInsertAnimeService } from "../services/bulkInsertAnime.service"; import { returnWriteResponse } from "../../../helpers/callback/httpResponse"; +import { bulkInsertCharWithVAService } from "../services/internal/bulkInsertCharWithVA.service"; export const bulkInsertAnimeController = async ( ctx: Context & { body: { mal_id: number } }, ) => { 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( ctx.set, 201, diff --git a/src/modules/internal/repositories/bulkInsertVA.repository.ts b/src/modules/internal/repositories/bulkInsertVA.repository.ts new file mode 100644 index 0000000..a07f236 --- /dev/null +++ b/src/modules/internal/repositories/bulkInsertVA.repository.ts @@ -0,0 +1,19 @@ +import { Prisma } from "@prisma/client"; +import { AppError } from "../../../helpers/error/instances/app"; +import { prisma } from "../../../utils/databases/prisma/connection"; + +export const bulkInsertVARepository = async ( + payload: Prisma.VoiceActorUpsertArgs["create"], +) => { + try { + const insertedVA = await prisma.voiceActor.upsert({ + where: { malId: payload.malId }, + create: payload, + update: payload, + select: { id: true }, + }); + return insertedVA.id; + } catch (error) { + throw new AppError(500, "Failed to bulk insert VAs", error); + } +}; diff --git a/src/modules/internal/repositories/bulkinsertMediaa.repository.ts b/src/modules/internal/repositories/bulkinsertMedia.repository.ts similarity index 100% rename from src/modules/internal/repositories/bulkinsertMediaa.repository.ts rename to src/modules/internal/repositories/bulkinsertMedia.repository.ts diff --git a/src/modules/internal/services/bulkInsertAnime.service.ts b/src/modules/internal/services/bulkInsertAnime.service.ts index 57b3684..8379125 100644 --- a/src/modules/internal/services/bulkInsertAnime.service.ts +++ b/src/modules/internal/services/bulkInsertAnime.service.ts @@ -2,7 +2,7 @@ import { Prisma } from "@prisma/client"; import { getContentReferenceAPI } from "../../../config/apis/media.reference"; import { ErrorForwarder } from "../../../helpers/error/instances/forwarder"; import { bulkInsertGenresRepository } from "../repositories/bulkInsertGenres.repository"; -import { InsertMediaRepository } from "../repositories/bulkinsertMediaa.repository"; +import { InsertMediaRepository } from "../repositories/bulkinsertMedia.repository"; import { bulkInsertStudiosRepository } from "../repositories/bulkInsertStudios.repository"; import { MediaFullInfoResponse } from "../types/mediaFullInfo.type"; import { generateSlug } from "../../../helpers/characters/generateSlug"; diff --git a/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts b/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts new file mode 100644 index 0000000..3ab13d6 --- /dev/null +++ b/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts @@ -0,0 +1,16 @@ +import { getContentReferenceAPI } from "../../../../config/apis/media.reference"; +import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; +import { MediaCharWithVAInfo } from "../../types/mediaCharWithVAInfo"; + +export const bulkInsertCharWithVAService = async (malId: number) => { + try { + const { baseURL, getMediaCharactersWithVA } = getContentReferenceAPI(malId); + const charactersWithVAData = (await fetch( + `${baseURL}${getMediaCharactersWithVA}`, + ).then((res) => res.json())) as MediaCharWithVAInfo; + + return; + } catch (error) { + ErrorForwarder(error); + } +}; diff --git a/src/modules/internal/types/mediaCharWithVAInfo.ts b/src/modules/internal/types/mediaCharWithVAInfo.ts new file mode 100644 index 0000000..30e52e8 --- /dev/null +++ b/src/modules/internal/types/mediaCharWithVAInfo.ts @@ -0,0 +1,59 @@ +export interface MediaCharWithVAInfo { + data: Datum[]; +} + +interface Datum { + character: Character; + role: Role; + favorites: number; + voice_actors: VoiceActor[]; +} + +interface Character { + mal_id: number; + url: string; + images: CharacterImages; + name: string; +} + +interface CharacterImages { + jpg: Jpg; + webp: Webp; +} + +interface Jpg { + image_url: string; +} + +interface Webp { + image_url: string; + small_image_url: string; +} + +enum Role { + Main = "Main", + Supporting = "Supporting", +} + +interface VoiceActor { + person: Person; + language: Language; +} + +enum Language { + English = "English", + Japanese = "Japanese", + PortugueseBR = "Portuguese (BR)", + Spanish = "Spanish", +} + +interface Person { + mal_id: number; + url: string; + images: PersonImages; + name: string; +} + +interface PersonImages { + jpg: Jpg; +}