Compare commits

..

No commits in common. "cdfb501952d4757ac80160daa4c062e0606c940a" and "9ff76bd210b6ebc8b48e8477a3b46730784737a2" have entirely different histories.

14 changed files with 179 additions and 189 deletions

5
.gitignore vendored
View File

@ -66,7 +66,4 @@ public/assets/build/
.vscode/
package-lock.json
bun.lockb
bundle.js
mydb.sqlite
public/poster/
output/
bundle.js

5
app.ts
View File

@ -1,19 +1,20 @@
import express from "express";
import path from 'path'
import 'dotenv/config'
const hostname = '127.0.0.1';
const httpPort = 4080;
const app = express();
app.set('views', 'views');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// import morgan from 'morgan'
// app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static('public'));
app.use(express.static(path.join(__dirname, 'public')));
import mainRouter from './routes/main';
import apiRouter from './routes/api/apiRouter';

View File

@ -1,6 +0,0 @@
mkdir output
bun build ./app.ts --outfile=output/app.js --target=bun --minify
bun build ./frontend/list/list.tsx --outfile=public/assets/build/list.js --minify
cp -r views/ output/
cp -r public/ output/

20
build.ts Normal file
View File

@ -0,0 +1,20 @@
async function build() {
const minify = {
whitespace: true,
syntax: true,
identifiers: true,
}
const sa = await Bun.build({
entrypoints: ["./frontend/list/list"],
outdir: "./public/assets/build/",
minify,
})
console.log(sa);
}
build();
export default build;

View File

@ -1,14 +1,7 @@
import { type Request, type Response } from "express";
import UserModel, { values } from '../models/userModel';
import MediaModel, { Table, Media } from '../models/mediaModel';
import MediaModel, { Table } 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;
@ -17,31 +10,10 @@ function fromStringToTable(value: string): (Table | undefined) {
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);
const omdb_key = await UserModel.getValue(values.omdb_key);
if (!omdb_key) {
return res.status(500).json({ message: 'Error when creating media' });
@ -55,44 +27,39 @@ async function createMed(req: Request, res: Response) {
const uri = `http://www.omdbapi.com/?i=${mediaCode}&apikey=${omdb_key}`;
const mJson = await fetch(uri);
const mData: omdbRes = await mJson.json();
const mData = await mJson.json();
if (mData.Response == 'False') {
return res.status(404).json({ message: 'wrong code' });
}
const media: Media = {
id:0,
code: cleanCode,
const seriesFound = await MediaModel.findOne(Table.series, cleanCode);
if (seriesFound.length != 0) {
await MediaModel.updateWebImg(Table.series, cleanCode, mData.Poster);
return res.status(409).json({ message: 'Media already exists' });
}
const moviesFound = await MediaModel.findOne(Table.movies, cleanCode);
if (moviesFound.length != 0) {
await MediaModel.updateWebImg(Table.movies, cleanCode, mData.Poster);
return res.status(409).json({ message: 'Media already exists' });
}
if (mData.Type.localeCompare("movie") == 0) {
const savedMedia = await MediaModel.save(Table.movies, cleanCode, mData.Title, mData.Released, mData.Poster);
}
else if (mData.Type.localeCompare("series") == 0) {
const savedMedia = await MediaModel.save(Table.series, cleanCode, mData.Title, mData.Released, mData.Poster);
}
const media = {
code: mediaCode,
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);
return res.status(201).json(media);
} catch (err) {
return res.status(500).json({ message: 'Error when creating media' });
}
@ -101,15 +68,15 @@ async function createMed(req: Request, res: Response) {
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);
const twitch_client_id = await UserModel.getValue(values.twitch_client_id);
const twitch_client_secret = await 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);
const gameFound = await MediaModel.findOne(Table.games, gameCode);
if (gameFound) {
return res.status(409).json({ message: 'Game already exists' });
}
@ -154,15 +121,14 @@ async function createGame(req: Request, res: Response) {
)
const coverData = await response.json()
const game: Media = {
id: 0,
const game = {
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);
const savedGame = await MediaModel.save(Table.games, game.code, game.title, game.released, game.webImg);
return res.status(201).json(game);
} catch (error) {
@ -184,8 +150,16 @@ export default {
});
}
const media = MediaModel.find(mediaTable);
return res.json(media);
MediaModel.find(mediaTable)
.then(media => {
return res.json(media);
})
.catch(err => {
return res.status(500).json({
message: 'Error when getting media.',
error: err
});
});
},
create: async function (req: Request, res: Response) {
@ -200,7 +174,7 @@ export default {
/**
* mediaController.delete()
*/
remove: function (req: Request, res: Response) {
remove: async function (req: Request, res: Response) {
const mediaTable = fromStringToTable(req.params.mediaType);
if (!mediaTable) {
return res.status(500).json({
@ -212,7 +186,7 @@ export default {
try {
const mediaTable = req.baseUrl.includes('movies') ? Table.movies : Table.series;
const media = MediaModel.findOneAndDelete(mediaTable, code);
const media = await MediaModel.findOneAndDelete(mediaTable, code);
if (!media) {
return res.status(404).json({ message: 'No such media' });
}

View File

@ -3,20 +3,20 @@ import UserModel, { values } from '../models/userModel';
export default {
render: function (req: Request, res: Response) {
render: async function (req: Request, res: Response) {
res.render('user', { keys: UserModel.namesOfValues });
},
create: function (req: Request, res: Response) {
create: async function (req: Request, res: Response) {
const reqPassword: string = req.body.reqPassword;
if (!reqPassword) return res.render('user', { keys: UserModel.namesOfValues });
const password = UserModel.getValue(values.pass);
const password = await UserModel.getValue(values.pass);
// if no password in db save reqPassword
if (!password) {
const affectedRows = UserModel.updateValue("pass", reqPassword);
const affectedRows = await UserModel.updateValue("pass", reqPassword);
if (affectedRows > 0) {
return res.redirect('/list');
}
@ -35,7 +35,7 @@ export default {
return res.render('user', { keys: UserModel.namesOfValues });
}
const affectedRows = UserModel.updateValue(name, value);
const affectedRows = await UserModel.updateValue(name, value);
if (affectedRows == 0) {
return res.render('user', { keys: UserModel.namesOfValues });
}
@ -43,8 +43,8 @@ export default {
return res.redirect('/list');
},
get: function (req: Request, res: Response) {
const usersFound = UserModel.getAll();
get: async function (req: Request, res: Response) {
const usersFound = await UserModel.getAll();
return res.status(200).json(usersFound);
},
};

1
dev.ts
View File

@ -1,4 +1,5 @@
const build_cash = Bun.spawn(["bun", "build", "./frontend/cash/cash.tsx", "--outfile=public/assets/build/cash/cash.js", "--watch"]);
const build_list = Bun.spawn(["bun", "build", "./frontend/list/list.tsx", "--outfile=public/assets/build/list/list.js", "--watch"]);
const build_app = Bun.spawn(["bun", "--watch", "./app.ts"]);

View File

@ -1,9 +1,9 @@
import { type NextFunction, type Request, type Response } from "express";
import userModel, { values } from 'models/userModel';
function checkAuthenticated(req: Request, res: Response, next: NextFunction) {
async function checkAuthenticated(req: Request, res: Response, next: NextFunction) {
const pass = req.body.pass;
const password = userModel.getValue(values.pass);
const password = await userModel.getValue(values.pass);
if (pass && password) {
if (pass == password) {
return next();

View File

@ -1,65 +1,34 @@
import { Database } from "bun:sqlite";
import mysql, { type PoolOptions } from 'mysql2/promise'
const pool = new Database("mydb.sqlite", { strict: true });
pool.exec(`
CREATE TABLE IF NOT EXISTS series (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code INT NOT NULL,
title TEXT NOT NULL,
released TEXT NOT NULL,
webImg TEXT NOT NULL,
UNIQUE (code)
);
`);
pool.exec(`
CREATE TABLE IF NOT EXISTS movies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code INT NOT NULL,
title TEXT NOT NULL,
released TEXT NOT NULL,
webImg TEXT NOT NULL,
UNIQUE (code)
);
`);
pool.exec(`
CREATE TABLE IF NOT EXISTS games (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code INT NOT NULL,
title TEXT NOT NULL,
released TEXT NOT NULL,
webImg TEXT NOT NULL,
UNIQUE (code)
);
`);
pool.exec(`
CREATE TABLE IF NOT EXISTS userData (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
value TEXT NOT NULL
);
`);
function inset_keys() {
class co {
count!: number;
}
const result = pool.query("SELECT count(*) as count FROM userData;").as(co).get();
if(result && result.count >= 4){
return;
}
pool.exec(`
INSERT INTO userData (name, value) VALUES ("pass", "");
INSERT INTO userData (name, value) VALUES ("omdb_key", "");
INSERT INTO userData (name, value) VALUES ("twitch_client_id", "");
INSERT INTO userData (name, value) VALUES ("twitch_client_secret", "");
`);
const poolOptions: PoolOptions = {
host: "",
port: 0,
user: "",
password: "",
database: ""
}
inset_keys();
if (process.env.DBIP) {
poolOptions.host = process.env.DBIP;
}
if (process.env.DBPort) {
poolOptions.port = parseInt(process.env.DBPort);
}
if (process.env.DBUser) {
poolOptions.user = process.env.DBUser;
}
if (process.env.DBPassword) {
poolOptions.password = process.env.DBPassword;
}
if (process.env.DBDatabase) {
poolOptions.database = process.env.DBDatabase;
}
const pool = mysql.createPool(poolOptions);
export default pool;

View File

@ -1,12 +1,13 @@
import { type ResultSetHeader, type RowDataPacket, type QueryOptions } from "mysql2"
import pool from 'miscellaneous/db'
export class Media {
id!: number;
code!: number;
title!: string;
released!: string;
webImg!: string;
interface Media extends RowDataPacket {
id?: number;
code?: number;
title?: string;
released?: string;
webImg?: string;
}
export enum Table {
@ -15,12 +16,14 @@ export enum Table {
games = "games",
}
function save(table: Table, code: number, title: string, released: string, webImg: string): number {
async function save(table: Table, code: number, title: string, released: string, webImg: string): Promise<number> {
try {
const sql = "INSERT INTO " + table + " (code, title, released, webImg) VALUES (?,?,?,?)";
const result = pool.query(sql).run(code, title, released, webImg);
return result.changes;
const options: QueryOptions = {
sql: "INSERT INTO " + table + " (code, title, released, webImg) VALUES (?,?,?,?)",
values: [code, title, released, webImg]
};
const [result, fields] = await pool.query<ResultSetHeader>(options);
return result.affectedRows;
}
catch (err) {
console.log(err);
@ -28,11 +31,14 @@ function save(table: Table, code: number, title: string, released: string, webIm
return 0;
}
function updateWebImg(table: Table, code: number, webImg: string): number {
async function updateWebImg(table: Table, code: number, webImg: string): Promise<number> {
try {
const sql = "UPDATE " + table + " SET webImg = ? WHERE code = ?;";
const result = pool.query(sql).run(webImg, code);
return result.changes;
const options: QueryOptions = {
sql: "UPDATE " + table + "SET webImg = ? WHERE code = ?;",
values: [webImg, code]
};
const [result, fields] = await pool.query<ResultSetHeader>(options);
return result.affectedRows;
}
catch (err) {
console.log(err);
@ -40,10 +46,10 @@ function updateWebImg(table: Table, code: number, webImg: string): number {
return 0;
}
function findOneAndDelete(table: Table, code: number): number {
async function findOneAndDelete(table: Table, code: number): Promise<number> {
try {
const result = pool.query("DELETE FROM " + table + " WHERE code = ?;").run(code);
return result.changes;
const [result, fields] = await pool.query<ResultSetHeader>("DELETE FROM " + table + " WHERE code = ?;", [code]);
return result.affectedRows;
}
catch (err) {
console.log(err);
@ -51,9 +57,9 @@ function findOneAndDelete(table: Table, code: number): number {
return 0;
}
function findOne(table: Table, code: number): Media[] {
async function findOne(table: Table, code: number): Promise<Media[]> {
try {
const rows = pool.query("SELECT * FROM " + table + " WHERE code = ?;").as(Media).all(code);
const [rows, fields] = await pool.query<Media[]>("SELECT * FROM " + table + " WHERE code = ?;", [code]);
return rows;
}
catch (err) {
@ -62,9 +68,9 @@ function findOne(table: Table, code: number): Media[] {
return [];
}
function find(table: Table): Media[] {
async function find(table: Table): Promise<Media[]> {
try {
const rows = pool.query("SELECT * FROM " + table + ";").as(Media).all();
const [rows, fields] = await pool.query<Media[]>("SELECT * FROM " + table + ";");
return rows;
}
catch (err) {

View File

@ -1,6 +1,7 @@
import { type ResultSetHeader, type RowDataPacket } from "mysql2"
import pool from 'miscellaneous/db'
class UserD {
interface UserD extends RowDataPacket {
name?: string;
value?: string;
}
@ -14,9 +15,9 @@ export enum values {
const namesOfValues: string[] = ["", "pass", "omdb_key", "twitch_client_id", "twitch_client_secret"];
function getValue(name: values): string | undefined {
async function getValue(name: values): Promise<string | undefined> {
try {
const rows = pool.query("SELECT name, value FROM userData where id = ?;").as(UserD).all(name);
const [rows, fields] = await pool.query<UserD[]>("SELECT name, value FROM userData where id = ?;", [name]);
if (rows.length > 0)
return rows[0].value;
}
@ -26,10 +27,10 @@ function getValue(name: values): string | undefined {
return;
}
function updateValue(name: string, value: string): number {
async function updateValue(name: string, value: string): Promise<number> {
try {
const result = pool.query("UPDATE userData SET value = ? WHERE name = ?").run(value, name);
return result.changes;
const [result, fields] = await pool.query<ResultSetHeader>("UPDATE userData SET value = ? WHERE name = ?", [value, name]);
return result.affectedRows;
}
catch (err) {
console.log(err);
@ -37,9 +38,9 @@ function updateValue(name: string, value: string): number {
return 0;
}
function getAll(): UserD[] {
async function getAll(): Promise<UserD[]> {
try {
const rows = pool.query("SELECT name, value FROM userData;").as(UserD).all();
const [rows, fields] = await pool.query<UserD[]>("SELECT name, value FROM userData;");
return rows;
}
catch (err) {

View File

@ -2,12 +2,19 @@
"name": "web",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "bun ./app.ts",
"build_app": "bun build ./app.ts --outfile=bundle.js --target=bun"
},
"dependencies": {
"@types/express": "^4.17.21",
"@types/morgan": "^1.9.9",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"hbs": "^4.2.0",
"morgan": "~1.9.1",
"mysql2": "^3.10.3",
"chart.js": "^4.4.1",
"bun-types": "^1.0.23",
"typescript": "^5.3.3"
}

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS series (
CREATE TABLE series (
id INT NOT NULL AUTO_INCREMENT,
code INT NOT NULL,
title TEXT NOT NULL,
@ -6,9 +6,9 @@ CREATE TABLE IF NOT EXISTS series (
webImg TEXT NOT NULL,
PRIMARY KEY (id),
UNIQUE code (code)
);
) ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS movies (
CREATE TABLE movies (
id INT NOT NULL AUTO_INCREMENT,
code INT NOT NULL,
title TEXT NOT NULL,
@ -16,9 +16,9 @@ CREATE TABLE IF NOT EXISTS movies (
webImg TEXT NOT NULL,
PRIMARY KEY (id),
UNIQUE code (code)
);
) ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS games (
CREATE TABLE games (
id INT NOT NULL AUTO_INCREMENT,
code INT NOT NULL,
title TEXT NOT NULL,
@ -26,14 +26,14 @@ CREATE TABLE IF NOT EXISTS games (
webImg TEXT NOT NULL,
PRIMARY KEY (id),
UNIQUE code (code)
);
) ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS userData (
CREATE TABLE userData (
id INT NOT NULL AUTO_INCREMENT,
name TEXT NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (id),
);
) ENGINE = InnoDB;
INSERT INTO userData (name, value) VALUES ("pass", "");
@ -41,4 +41,19 @@ INSERT INTO userData (name, value) VALUES ("omdb_key", "");
INSERT INTO userData (name, value) VALUES ("twitch_client_id", "");
INSERT INTO userData (name, value) VALUES ("twitch_client_secret", "");
INSERT INTO
userData (name, value) VALUES ("twitch_client_secret", "");
CREATE TABLE bankCardTransaction (
id INT NOT NULL AUTO_INCREMENT,
day INT NOT NULL,
month INT NOT NULL,
year INT NOT NULL,
amount INT NOT NULL,
type INT NOT NULL,
raw TEXT NOT NULL,
company TEXT NOT NULL,
PRIMARY KEY (id),
INDEX date(day, month, year),
INDEX type (type)
) ENGINE = InnoDB;

5
templ.env Normal file
View File

@ -0,0 +1,5 @@
DBIP=''
DBPort=
DBUser=''
DBPassword=''
DBDatabase=''