Added DB interactions with paintings routes

This commit is contained in:
Florian Sylvain
2023-03-07 16:11:44 +01:00
parent 0b12ab2b56
commit c2aa80ecf1
2 changed files with 201 additions and 20 deletions
+201 -18
View File
@@ -1,14 +1,53 @@
import { PrismaClient } from "@prisma/client"
import { PrismaClient, PaintingAuthor, Painting, Author } from "@prisma/client"
import express, { RequestHandler } from "express"
import { z } from "zod"
import { getPaintingQuery } from "../utils/queries.js"
import fs from "fs"
const paintingsRouter = express.Router()
// const prisma = new PrismaClient()
interface GraphQlPainting {
data: {
nodeQuery: {
entities: {
entityUuid: string
title: string
absolutePath: string
fieldOeuvreAuteurs: {
entity: {
fieldAuteurAuteur: {
entity: {
name: string
}
}
}
}[]
fieldVisuels: {
entity: {
publicUrl: string
}
}[]
fieldMusee: {
entity: {
name: string
}
}
}[]
}
}
}
const paintingParser = z
interface ParsedPainting {
image_url: string
name: string
link: string
musuem: string
author: string
}
const paintingsRouter = express.Router()
const prisma = new PrismaClient()
const paintingParamsParser = z
.object({
uuid: z.string(),
})
@@ -20,7 +59,18 @@ const randomParser = z
})
.required()
async function fetchPainting(uuid: string): Promise<unknown> {
function parseGraphQlPainting(painting: GraphQlPainting): ParsedPainting {
const graphQlPainting = painting.data.nodeQuery.entities[0]
return {
image_url: graphQlPainting.fieldVisuels[0].entity.publicUrl,
name: graphQlPainting.title,
link: graphQlPainting.absolutePath,
musuem: graphQlPainting.fieldMusee.entity.name,
author: graphQlPainting.fieldOeuvreAuteurs[0].entity.fieldAuteurAuteur.entity.name,
}
}
function fetchPainting(uuid: string): Promise<GraphQlPainting> {
return new Promise((resolve, reject) => {
fetch("https://apicollections.parismusees.paris.fr/graphql", {
method: "POST",
@@ -35,32 +85,165 @@ async function fetchPainting(uuid: string): Promise<unknown> {
})
}
async function getRandomPaintings(limit: number): Promise<unknown[]> {
const paintingsUUIDs = JSON.parse(
fs.readFileSync("src/assets/paintingsUUID.json", "utf8")
)
const randomUUIDs = paintingsUUIDs.paintings
.sort(() => Math.random() - 0.5)
.slice(0, limit)
async function getRandomPaintings(limit: number): Promise<(Painting | null)[]> {
const paintingsUUIDs = JSON.parse(fs.readFileSync("src/assets/paintingsUUID.json", "utf8"))
const randomUUIDs = paintingsUUIDs.paintings.sort(() => Math.random() - 0.5).slice(0, limit)
const paintings = []
for (const uuid of randomUUIDs) {
const painting = await fetchPainting(uuid)
paintings.push(painting)
const fetchedPainting = await fetchPainting(uuid)
const parsedPainting = parseGraphQlPainting(fetchedPainting)
const painting = await getPainting(undefined, parsedPainting.name)
if (!painting) {
const createdPaintingAuthor = await createPainting(parsedPainting)
paintings.push(await getPainting(createdPaintingAuthor.painting_id, undefined))
continue
}
await updatePaintingIfNeeded(painting, parsedPainting)
paintings.push(await getPainting(undefined, parsedPainting.name))
}
return paintings
}
async function createPainting(painting: ParsedPainting): Promise<PaintingAuthor> {
return await prisma.paintingAuthor.create({
data: {
painting: {
create: {
image_url: painting.image_url,
name: painting.name,
link: painting.link,
Musuem: {
connectOrCreate: {
where: {
name: painting.musuem,
},
create: {
name: painting.musuem,
},
},
},
},
},
author: {
connectOrCreate: {
where: {
fullname: painting.author,
},
create: {
fullname: painting.author,
},
},
},
},
})
}
async function getPainting(id?: number, name?: string): Promise<Painting | null> {
if (!id && !name) return null
return await prisma.painting.findUnique({
where: id ? { id } : { name },
include: { PaintingAuthor: { select: { author: true } } },
})
}
async function getPaintingAuthors(paintingId: number): Promise<(Author | null)[]> {
const paintingAuthors = (
await prisma.painting.findUnique({
where: { id: paintingId },
include: { PaintingAuthor: true },
})
)?.PaintingAuthor
if (!paintingAuthors) return []
const authors = []
for (const paintingAuthor of paintingAuthors) {
const author = await prisma.author.findUnique({
where: { id: paintingAuthor.author_id },
})
authors.push(author)
}
return authors
}
async function updatePainting(id: number, painting: ParsedPainting): Promise<Painting> {
return await prisma.painting.update({
where: {
id: id,
},
data: {
image_url: painting.image_url,
name: painting.name,
link: painting.link,
Musuem: {
connectOrCreate: {
where: {
name: painting.musuem,
},
create: {
name: painting.musuem,
},
},
},
},
})
}
async function updatePaintingIfNeeded(
painting: Painting,
parsedPainting: ParsedPainting
): Promise<void> {
const paintingMusuem = (
await prisma.painting.findUnique({
where: {
id: painting.id,
},
select: {
Musuem: true,
},
})
)?.Musuem
const paintingAuthors = await getPaintingAuthors(painting.id)
if (
painting.image_url !== parsedPainting.image_url ||
painting.name !== parsedPainting.name ||
painting.link !== parsedPainting.link ||
paintingMusuem?.name !== parsedPainting.musuem ||
paintingAuthors?.[0]?.fullname !== parsedPainting.author
) {
updatePainting(painting.id, parsedPainting)
}
}
const paintingRouterGet: RequestHandler = async (req, res) => {
const parsedPainting = paintingParser.safeParse(req.params)
if (!parsedPainting.success) {
const parsedPaintingParams = paintingParamsParser.safeParse(req.params)
if (!parsedPaintingParams.success) {
res.status(400).send({ message: "Please provide valid painting UUID." })
return
}
const painting = await fetchPainting(parsedPainting.data.uuid)
res.send({ painting })
const fetchedPainting = await fetchPainting(parsedPaintingParams.data.uuid)
const parsedPainting = parseGraphQlPainting(fetchedPainting)
const painting = await getPainting(undefined, parsedPainting.name)
if (!painting) {
const createdPaintingAuthor = await createPainting(parsedPainting)
res.send({ painting: await getPainting(createdPaintingAuthor.painting_id, undefined) })
return
}
await updatePaintingIfNeeded(painting, parsedPainting)
res.send({ painting: await getPainting(undefined, parsedPainting.name) })
return
}
const paintingRouterGetRandoms: RequestHandler = async (req, res) => {
-2
View File
@@ -9,7 +9,6 @@ export function getPaintingQuery(uuid: string) {
... on NodeOeuvre {
title
absolutePath
fieldUrlAlias
fieldOeuvreAuteurs {
entity {
fieldAuteurAuteur {
@@ -22,7 +21,6 @@ export function getPaintingQuery(uuid: string) {
fieldVisuels {
entity {
name
vignette
publicUrl
}
}