Files
AnimeTV-Backend/src/modules/internal/repositories/bulkinsertMedia.repository.ts

157 lines
4.7 KiB
TypeScript

import { Prisma } from "@prisma/client";
import { AppError } from "../../../helpers/error/instances/app";
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
import { prisma } from "../../../utils/databases/prisma/connection";
import { bulkInsertMediaProducerStudioLicensorRepository } from "./bulkInsertMediaProducerStudioLicensor.repository";
/**
* Media Payload Construction and Upsert
*
* This section constructs the payload for the media insertion or update.
* It gathers all necessary information from the media data, including
* title, alternative titles, slug, associated genres and studios, score,
* images, status, airing dates, synopsis, age rating, media type, source,
* and other relevant details. This payload is then used in an upsert
* operation to ensure that the media record is either created or updated
* in the database.
*
* @param data - The full media data for constructing the media payload.
* @returns The inserted or updated media record.
*/
export const InsertMediaRepository = async ({ payload }: { payload: MediaFullInfoResponse["data"] }) => {
try {
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,
};
const producerPayload = [
...payload.producers.map((producer) => ({
mal_id: producer.mal_id,
type: producer.type,
name: producer.name,
url: producer.url,
status: "producer" as const,
})),
...payload.licensors.map((licensor) => ({
mal_id: licensor.mal_id,
type: licensor.type,
name: licensor.name,
url: licensor.url,
status: "licensor" as const,
})),
...payload.studios.map((studio) => ({
mal_id: studio.mal_id,
type: studio.type,
name: studio.name,
url: studio.url,
status: "studio" as const,
})),
];
return await prisma.$transaction(async (tx) => {
const media = await tx.media.upsert({
where: { mal_id: payload.mal_id },
create: constructMediaPayload,
update: constructMediaPayload,
select: {
id: true,
},
});
await bulkInsertMediaProducerStudioLicensorRepository(tx, media.id, producerPayload);
return {
id: media.id,
mal_id: payload.mal_id,
name: payload.title,
};
});
} catch (error) {
throw new AppError(500, "Failed to insert media", error);
}
};