🚧 wip: update media bulk insert for new schema
This commit is contained in:
@ -252,8 +252,6 @@ Table medias {
|
||||
age_rating_id String
|
||||
country_id String
|
||||
related_media media_relations [not null]
|
||||
approver_id String
|
||||
created_by_id String
|
||||
updated_by_id String
|
||||
deleted_by_id String
|
||||
home_media_banners home_media_banners [not null]
|
||||
@ -296,7 +294,7 @@ Table media_collections {
|
||||
Table media_trailers {
|
||||
media_id String [pk]
|
||||
url String
|
||||
embed_url String
|
||||
embed_url String [unique]
|
||||
small_image_url String
|
||||
large_image_url String
|
||||
maximum_image_url String
|
||||
@ -661,7 +659,7 @@ Table countries {
|
||||
id String [pk]
|
||||
name String [not null]
|
||||
slug String [not null]
|
||||
code String [not null]
|
||||
code String [unique, not null]
|
||||
flag String
|
||||
banner String
|
||||
UserCountry users [not null]
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[embed_url]` on the table `media_trailers` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "media_trailers_embed_url_key" ON "media_trailers"("embed_url");
|
||||
@ -0,0 +1,8 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[code]` on the table `countries` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "countries_code_key" ON "countries"("code");
|
||||
@ -0,0 +1,10 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `approver_id` on the `medias` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `created_by_id` on the `medias` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "medias" DROP COLUMN "approver_id",
|
||||
DROP COLUMN "created_by_id";
|
||||
@ -366,8 +366,6 @@ model Media {
|
||||
age_rating_id String? @db.Uuid
|
||||
country_id String? @db.Uuid
|
||||
related_media MediaRelation[] @relation("MediaRelationRelatedMedia")
|
||||
approver_id String? @db.Uuid
|
||||
created_by_id String? @db.Uuid
|
||||
updated_by_id String? @db.Uuid
|
||||
deleted_by_id String? @db.Uuid
|
||||
home_media_banners HomeMediaBanner[]
|
||||
@ -407,7 +405,7 @@ model MediaCollection {
|
||||
model MediaTrailer {
|
||||
media_id String @id @db.Uuid
|
||||
url String? @db.VarChar(255)
|
||||
embed_url String? @db.VarChar(255)
|
||||
embed_url String? @db.VarChar(255) @unique
|
||||
small_image_url String? @db.VarChar(255)
|
||||
large_image_url String? @db.VarChar(255)
|
||||
maximum_image_url String? @db.VarChar(255)
|
||||
@ -802,7 +800,7 @@ model Country {
|
||||
id String @id @db.Uuid @default(uuid(7))
|
||||
name String @db.VarChar(155)
|
||||
slug String @db.VarChar(165)
|
||||
code String @db.VarChar(3)
|
||||
code String @db.VarChar(3) @unique
|
||||
flag String? @db.VarChar(255)
|
||||
banner String? @db.VarChar(255)
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@ import { Prisma } from "@prisma/client";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../utils/databases/prisma/connection";
|
||||
import { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
|
||||
import { SystemAccountId } from "../../../config/account/system";
|
||||
|
||||
/**
|
||||
* Media Payload Construction and Upsert
|
||||
@ -17,21 +19,100 @@ import { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||
* @param data - The full media data for constructing the media payload.
|
||||
* @returns The inserted or updated media record.
|
||||
*/
|
||||
export const InsertMediaRepository = async ({
|
||||
malId,
|
||||
payload,
|
||||
}: {
|
||||
malId: number;
|
||||
payload: Omit<Prisma.MediaUncheckedCreateInput, "id">;
|
||||
}) => {
|
||||
export const InsertMediaRepository = async ({ payload }: { payload: MediaFullInfoResponse["data"] }) => {
|
||||
try {
|
||||
return await prisma.media.upsert({
|
||||
where: { malId },
|
||||
update: payload,
|
||||
create: {
|
||||
id: generateUUIDv7(),
|
||||
...payload,
|
||||
const constructMediaPayload: Prisma.MediaUpsertArgs["create"] = {
|
||||
mal_id: payload.mal_id,
|
||||
title: payload.title,
|
||||
title_secondary: payload.title_english,
|
||||
title_original: payload.title_japanese,
|
||||
title_synonyms: payload.title_synonyms,
|
||||
trailer: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
embed_url: payload.trailer.embed_url,
|
||||
},
|
||||
create: {
|
||||
embed_url: payload.trailer.embed_url,
|
||||
url: payload.trailer.url,
|
||||
small_image_url: payload.trailer.images.small_image_url,
|
||||
large_image_url: payload.trailer.images.large_image_url,
|
||||
maximum_image_url: payload.trailer.images.maximum_image_url,
|
||||
},
|
||||
},
|
||||
},
|
||||
synopsis: payload.synopsis,
|
||||
small_image_url: payload.images.jpg.small_image_url,
|
||||
medium_image_url: payload.images.jpg.image_url,
|
||||
large_image_url: payload.images.jpg.large_image_url,
|
||||
type: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
name: payload.type.toLowerCase(),
|
||||
},
|
||||
create: {
|
||||
name: payload.type.toLowerCase(),
|
||||
},
|
||||
},
|
||||
},
|
||||
source: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
name: payload.source.toLowerCase(),
|
||||
},
|
||||
create: {
|
||||
name: payload.source.toLowerCase(),
|
||||
},
|
||||
},
|
||||
},
|
||||
status: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
name: payload.status.toLowerCase(),
|
||||
},
|
||||
create: {
|
||||
name: payload.status.toLowerCase(),
|
||||
},
|
||||
},
|
||||
},
|
||||
airing: payload.airing,
|
||||
start_airing: payload.aired.from,
|
||||
end_airing: payload.aired.to,
|
||||
age_rating: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
name: payload.rating.toLowerCase(),
|
||||
},
|
||||
create: {
|
||||
name: payload.rating.toLowerCase(),
|
||||
min_age: 0, // Placeholder, as the actual age rating details may require additional mapping
|
||||
},
|
||||
},
|
||||
},
|
||||
score_total: 0,
|
||||
score_count: 0,
|
||||
background: payload.background,
|
||||
season: payload.season,
|
||||
year: payload.year,
|
||||
country: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
code: "jpn",
|
||||
},
|
||||
create: {
|
||||
name: "japan",
|
||||
slug: "japan",
|
||||
code: "jpn",
|
||||
},
|
||||
},
|
||||
},
|
||||
broadcast_day: payload.broadcast.day,
|
||||
};
|
||||
|
||||
return await prisma.media.upsert({
|
||||
where: { mal_id: payload.mal_id },
|
||||
create: constructMediaPayload,
|
||||
update: constructMediaPayload,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to insert media", error);
|
||||
|
||||
@ -1,61 +1,15 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||
import { bulkInsertGenresRepository } from "../../repositories/bulkInsertGenres.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";
|
||||
import { bulkInsertCharWithVAService } from "../internal/bulkInsertCharWithVA.service";
|
||||
import { generateUUIDv7 } from "../../../../helpers/databases/uuidv7";
|
||||
import { SystemAccountId } from "../../../../config/account/system";
|
||||
import { getContentReferenceAPI } from "../../../../config/apis/jikan/media.reference";
|
||||
|
||||
export const bulkInsertAnimeService = async (malId: number) => {
|
||||
try {
|
||||
const { baseURL, getMediaFullInfo } = getContentReferenceAPI(malId);
|
||||
const mediaFullInfo = (await fetch(baseURL + getMediaFullInfo).then((res) =>
|
||||
res.json(),
|
||||
)) as MediaFullInfoResponse;
|
||||
const mediaFullInfo = (await fetch(baseURL + getMediaFullInfo).then((res) => res.json())) as MediaFullInfoResponse;
|
||||
|
||||
const insertedGenres = await bulkInsertGenresRepository(mediaFullInfo);
|
||||
const insertedStudios = await bulkInsertStudiosRepository(mediaFullInfo);
|
||||
const insertedCharacters = await bulkInsertCharWithVAService(malId);
|
||||
|
||||
const constructMediaPayload: Prisma.MediaUpsertArgs["create"] = {
|
||||
id: generateUUIDv7(),
|
||||
title: mediaFullInfo.data.title,
|
||||
titleAlternative: mediaFullInfo.data
|
||||
.titles as unknown as Prisma.InputJsonValue,
|
||||
slug: await generateSlug(mediaFullInfo.data.title, {
|
||||
model: "media",
|
||||
target: "slug",
|
||||
}),
|
||||
malId: mediaFullInfo.data.mal_id,
|
||||
genres: {
|
||||
connect: insertedGenres.map((id) => ({ id })),
|
||||
},
|
||||
studios: {
|
||||
connect: insertedStudios.map((id) => ({ id })),
|
||||
},
|
||||
characters: {
|
||||
connect: insertedCharacters.map(({ id }) => ({ id })),
|
||||
},
|
||||
score: mediaFullInfo.data.score,
|
||||
pictureMedium: mediaFullInfo.data.images.webp.image_url,
|
||||
pictureLarge: mediaFullInfo.data.images.webp.large_image_url,
|
||||
status: mediaFullInfo.data.status,
|
||||
startAiring: mediaFullInfo.data.aired.from,
|
||||
endAiring: mediaFullInfo.data.aired.to,
|
||||
synopsis: mediaFullInfo.data.synopsis,
|
||||
ageRating: mediaFullInfo.data.rating,
|
||||
mediaType: mediaFullInfo.data.type,
|
||||
source: mediaFullInfo.data.source,
|
||||
onDraft: false,
|
||||
uploadedBy: SystemAccountId,
|
||||
};
|
||||
const insertedMedia = await InsertMediaRepository({
|
||||
malId: mediaFullInfo.data.mal_id,
|
||||
payload: constructMediaPayload,
|
||||
payload: mediaFullInfo.data,
|
||||
});
|
||||
|
||||
return insertedMedia;
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { MediaFullInfoResponse } from "../../types/mediaFullInfo.type";
|
||||
import { prisma } from "../../../../utils/databases/prisma/connection";
|
||||
|
||||
interface InsertedProducer {
|
||||
producer: string[];
|
||||
licensor: string[];
|
||||
studio: string[];
|
||||
}
|
||||
|
||||
export const bulkInsertProducerService = async (payload: MediaFullInfoResponse, systemAccountId: string) => {
|
||||
const insertedPayload: InsertedProducer = {
|
||||
producer: [],
|
||||
licensor: [],
|
||||
studio: [],
|
||||
};
|
||||
|
||||
const insertingMainProducer = await prisma.producer.createMany({
|
||||
data: payload.data.producers.map((producer) => ({
|
||||
mal_id: producer.mal_id,
|
||||
type: producer.type,
|
||||
name: producer.name,
|
||||
url: producer.url,
|
||||
created_by_id: systemAccountId,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
};
|
||||
@ -1,4 +1,4 @@
|
||||
import { MediaType } from "@prisma/client";
|
||||
import { media_season } from "@prisma/client";
|
||||
export interface MediaFullInfoResponse {
|
||||
data: Data;
|
||||
}
|
||||
@ -14,7 +14,7 @@ interface Data {
|
||||
title_english: string;
|
||||
title_japanese: string;
|
||||
title_synonyms: string[];
|
||||
type: MediaType;
|
||||
type: string;
|
||||
source: string;
|
||||
episodes: number;
|
||||
status: string;
|
||||
@ -30,7 +30,7 @@ interface Data {
|
||||
favorites: number;
|
||||
synopsis: string;
|
||||
background: string;
|
||||
season: string;
|
||||
season: media_season;
|
||||
year: number;
|
||||
broadcast: Broadcast;
|
||||
producers: Genre[];
|
||||
|
||||
Reference in New Issue
Block a user