personal_website/controllers/mediaController.ts
2025-07-16 19:17:34 +02:00

227 lines
6.6 KiB
TypeScript

import { type Request, type Response } from "express";
import UserModel, { values } from '../models/userModel';
import MediaModel, { Table, Media } from '../models/mediaModel';
interface omdbRes{
Title: string,
Released: string,
Response: string,
Poster: string,
Type: string
}
function fromStringToTable(value: string): (Table | undefined) {
if (value.localeCompare("games") == 0) return Table.games;
if (value.localeCompare("movies") == 0) return Table.movies;
if (value.localeCompare("series") == 0) return Table.series;
return;
}
async function downloadImage(mData: Media, type: Table) {
// Specify the path where you want to save the image
const outputPath = '/poster/' + type + '/' + mData.code + '.jpg';
// Use Bun's built-in fetch to download the image
const response = await fetch(mData.webImg);
// Check if the request was successful
if (!response.ok) {
console.log("fetch image error");
return
}
// Convert the response to a blob
const imageBlob = await response.blob();
// Use Bun's write to save the image to a file
await Bun.write('./public/' + outputPath, await imageBlob.arrayBuffer());
MediaModel.updateWebImg(type, mData.code, outputPath);
}
async function createMed(req: Request, res: Response) {
const mediaCode: string = req.body.code;
const omdb_key = UserModel.getValue(values.omdb_key);
if (!omdb_key) {
return res.status(500).json({ message: 'Error when creating media' });
}
// remove the tt in front in DB its stored as number
const sub = mediaCode.substring(2);
const cleanCode = parseInt(sub);
try {
const uri = `http://www.omdbapi.com/?i=${mediaCode}&apikey=${omdb_key}`;
const mJson = await fetch(uri);
const mData: omdbRes = await mJson.json();
if (mData.Response == 'False') {
return res.status(404).json({ message: 'wrong code' });
}
const media: Media = {
id:0,
code: cleanCode,
title: mData.Title,
released: mData.Released,
webImg: mData.Poster,
};
const seriesFound = MediaModel.findOne(Table.series, cleanCode);
if (seriesFound.length != 0) {
res.status(409).json({ message: 'Media already exists' });
await downloadImage(media, Table.series);
return;
}
const moviesFound = MediaModel.findOne(Table.movies, cleanCode);
if (moviesFound.length != 0) {
res.status(409).json({ message: 'Media already exists' });
await downloadImage(media, Table.movies);
return;
}
if (mData.Type.localeCompare("movie") == 0) {
const savedMedia = MediaModel.save(Table.movies, cleanCode, mData.Title, mData.Released, mData.Poster);
await downloadImage(media, Table.movies);
}
else if (mData.Type.localeCompare("series") == 0) {
const savedMedia = MediaModel.save(Table.series, cleanCode, mData.Title, mData.Released, mData.Poster);
await downloadImage(media, Table.series);
}
res.status(201).json(media);
} catch (err) {
return res.status(500).json({ message: 'Error when creating media' });
}
}
async function createGame(req: Request, res: Response) {
var gameCode = req.body.code;
const twitch_client_id = UserModel.getValue(values.twitch_client_id);
const twitch_client_secret = UserModel.getValue(values.twitch_client_secret);
if (!twitch_client_id || !twitch_client_secret) {
return res.status(500).json({ message: 'Error when creating game' });
}
try {
const gameFound = MediaModel.findOne(Table.games, gameCode);
if (gameFound) {
return res.status(409).json({ message: 'Game already exists' });
}
const uri = "https://id.twitch.tv/oauth2/token?client_id=" + twitch_client_id + "&client_secret=" + twitch_client_secret + "&grant_type=client_credentials";
var response = await fetch(uri, { method: 'POST' });
const mData = await response.json();
const mheaders: HeadersInit = {
'Accept': 'application/json',
'Client-ID': twitch_client_id,
'Authorization': 'Bearer ' + mData.access_token
}
gameCode = parseInt(gameCode)
response = await fetch(
"https://api.igdb.com/v4/games",
{
method: 'POST',
headers: mheaders,
body: `fields name, first_release_date; where id = ${gameCode};`
}
)
const gameData = await response.json()
if (gameData.length == 0) {
return res.status(404).json({ message: 'wrong code' });
}
const date = new Date(gameData[0].first_release_date * 1000);
const options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'short', year: 'numeric' }
const dateStr = date.toLocaleDateString(undefined, options);
response = await fetch(
"https://api.igdb.com/v4/covers",
{
method: 'POST',
headers: mheaders,
body: `fields image_id; where game = ${gameCode};`
}
)
const coverData = await response.json()
const game: Media = {
id: 0,
code: gameCode,
title: gameData[0].name,
released: dateStr,
webImg: `https://images.igdb.com/igdb/image/upload/t_cover_big/${coverData[0].image_id}.jpg`,
};
const savedGame = MediaModel.save(Table.games, game.code, game.title, game.released, game.webImg);
return res.status(201).json(game);
} catch (error) {
return res.status(500).json({ message: 'Error when creating game', error: error });
}
}
export default {
/**
* mediaController.list()
*/
list: function (req: Request, res: Response) {
const mediaTable = fromStringToTable(req.params.mediaType);
if (!mediaTable) {
return res.status(500).json({
message: 'Error when getting media.'
});
}
const media = MediaModel.find(mediaTable);
return res.json(media);
},
create: async function (req: Request, res: Response) {
const mediaCode: string = req.body.code;
if (mediaCode.startsWith("t")) {
return await createMed(req, res);
} else {
return await createGame(req, res);
}
},
/**
* mediaController.delete()
*/
remove: function (req: Request, res: Response) {
const mediaTable = fromStringToTable(req.params.mediaType);
if (!mediaTable) {
return res.status(500).json({
message: 'Error when deleting the media.'
});
}
const code = req.body.code;
try {
const mediaTable = req.baseUrl.includes('movies') ? Table.movies : Table.series;
const media = MediaModel.findOneAndDelete(mediaTable, code);
if (!media) {
return res.status(404).json({ message: 'No such media' });
}
return res.status(204).json();
}
catch (err) {
return res.status(500).json({ message: 'Error when deleting the media.' });
}
},
};