mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-30 18:22:41 -04:00 
			
		
		
		
	Create movie seed route handler
This commit is contained in:
		
							parent
							
								
									1309749e46
								
							
						
					
					
						commit
						30d5d65755
					
				
							
								
								
									
										19
									
								
								api/src/controllers/seed/images.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								api/src/controllers/seed/images.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| import type { Image } from "~/models/utils"; | ||||
| 
 | ||||
| export const processImage = async (url: string): Promise<Image> => { | ||||
| 	const hasher = new Bun.CryptoHasher("sha256"); | ||||
| 	hasher.update(url); | ||||
| 
 | ||||
| 	// TODO: download source, save it in multiples qualities & process blurhash
 | ||||
| 
 | ||||
| 	return { | ||||
| 		id: hasher.digest().toString(), | ||||
| 		source: url, | ||||
| 		blurhash: "", | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| export const processOptImage = (url: string | null): Promise<Image | null> => { | ||||
| 	if (!url) return Promise.resolve(null); | ||||
| 	return processImage(url); | ||||
| }; | ||||
							
								
								
									
										79
									
								
								api/src/controllers/seed/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								api/src/controllers/seed/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| import Elysia, { t } from "elysia"; | ||||
| import { Movie, SeedMovie } from "~/models/movie"; | ||||
| import { db } from "~/db"; | ||||
| import { | ||||
| 	shows, | ||||
| 	showTranslations, | ||||
| 	entries, | ||||
| 	entryTranslations, | ||||
| } from "~/db/schema"; | ||||
| import { guessNextRefresh } from "./refresh"; | ||||
| import { processOptImage } from "./images"; | ||||
| 
 | ||||
| type Show = typeof shows.$inferInsert; | ||||
| type ShowTrans = typeof showTranslations.$inferInsert; | ||||
| type Entry = typeof entries.$inferInsert; | ||||
| 
 | ||||
| export const seed = new Elysia() | ||||
| 	.model({ | ||||
| 		movie: Movie, | ||||
| 		"seed-movie": SeedMovie, | ||||
| 		error: t.String(), | ||||
| 	}) | ||||
| 	.post( | ||||
| 		"/movies", | ||||
| 		async ({ body }) => { | ||||
| 			const { translations, videos, ...bMovie } = body; | ||||
| 
 | ||||
| 			const ret = await db.transaction(async (tx) => { | ||||
| 				const movie: Show = { | ||||
| 					kind: "movie", | ||||
| 					startAir: bMovie.airDate, | ||||
| 					nextRefresh: guessNextRefresh(bMovie.airDate ?? new Date()), | ||||
| 					...bMovie, | ||||
| 				}; | ||||
| 				const [ret] = await tx | ||||
| 					.insert(shows) | ||||
| 					.values(movie) | ||||
| 					.returning({ pk: shows.pk, id: shows.id }); | ||||
| 
 | ||||
| 				// even if never shown to the user, a movie still has an entry.
 | ||||
| 				const movieEntry: Entry = { type: "movie", ...bMovie }; | ||||
| 				const [entry] = await tx | ||||
| 					.insert(entries) | ||||
| 					.values(movieEntry) | ||||
| 					.returning({ pk: entries.pk }); | ||||
| 
 | ||||
| 				const trans: ShowTrans[] = await Promise.all( | ||||
| 					Object.entries(translations).map(async ([lang, tr]) => ({ | ||||
| 						pk: ret.pk, | ||||
| 						// TODO: normalize lang or error if invalid
 | ||||
| 						language: lang, | ||||
| 						...tr, | ||||
| 						poster: await processOptImage(tr.poster), | ||||
| 						thumbnail: await processOptImage(tr.thumbnail), | ||||
| 						logo: await processOptImage(tr.logo), | ||||
| 						banner: await processOptImage(tr.banner), | ||||
| 					})), | ||||
| 				); | ||||
| 				await tx.insert(showTranslations).values(trans); | ||||
| 
 | ||||
| 				const entryTrans = trans.map((x) => ({ ...x, pk: entry.pk })); | ||||
| 				await tx.insert(entryTranslations).values(entryTrans); | ||||
| 
 | ||||
| 				return { ...ret, entry: entry.pk }; | ||||
| 			}); | ||||
| 
 | ||||
| 			// TODO: insert entry-video links
 | ||||
| 			// await db.transaction(async tx => {
 | ||||
| 			// 	await tx.insert(videos).values(videos);
 | ||||
| 			// });
 | ||||
| 
 | ||||
| 			return ret.id; | ||||
| 		}, | ||||
| 		{ | ||||
| 			body: "seed-movie", | ||||
| 			response: { 200: "movie", 400: "error" }, | ||||
| 			tags: ["movies"], | ||||
| 		}, | ||||
| 	); | ||||
							
								
								
									
										12
									
								
								api/src/controllers/seed/refresh.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								api/src/controllers/seed/refresh.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| // oh i hate js dates so much.
 | ||||
| export const guessNextRefresh = (airDate: Date | string) => { | ||||
| 	if (typeof airDate === "string") airDate = new Date(airDate); | ||||
| 	const diff = new Date().getTime() - airDate.getTime(); | ||||
| 	const days = diff / (24 * 60 * 60 * 1000); | ||||
| 
 | ||||
| 	const ret = new Date(); | ||||
| 	if (days <= 4) ret.setDate(ret.getDate() + 4); | ||||
| 	else if (days <= 21) ret.setDate(ret.getDate() + 14); | ||||
| 	else ret.setMonth(ret.getMonth() + 2); | ||||
| 	return ret.toISOString().substring(0, 10); | ||||
| }; | ||||
| @ -1,7 +1,7 @@ | ||||
| import { t } from "elysia"; | ||||
| 
 | ||||
| export const Image = t.Object({ | ||||
| 	id: t.String({ format: "uuid" }), | ||||
| 	id: t.String(), | ||||
| 	source: t.String({ format: "uri" }), | ||||
| 	blurhash: t.String(), | ||||
| }); | ||||
|  | ||||
| @ -3,11 +3,19 @@ | ||||
| 		"target": "ES2021", | ||||
| 		"module": "ES2022", | ||||
| 		"moduleResolution": "node", | ||||
| 		"types": ["bun-types"], | ||||
| 		"types": [ | ||||
| 			"bun-types" | ||||
| 		], | ||||
| 		"esModuleInterop": true, | ||||
| 		"forceConsistentCasingInFileNames": true, | ||||
| 		"strict": true, | ||||
| 		"skipLibCheck": true, | ||||
| 		"noErrorTruncation": true | ||||
| 		"noErrorTruncation": true, | ||||
| 		"baseUrl": ".", | ||||
| 		"paths": { | ||||
| 			"~/*": [ | ||||
| 				"./src/*" | ||||
| 			] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user