hypixel-auction-notifier/src/sqlFunctions.ts
2024-12-29 00:07:30 +02:00

209 lines
6.2 KiB
TypeScript

import mariadb from 'mariadb';
import { loadConfig } from './configLoader';
const config = loadConfig();
class SqlSystem {
private static pool: mariadb.Pool = mariadb.createPool({ database: process.env.DATABASE, host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, connectionLimit: config.data.worker_count ?? 10 })
public static async InitDB() {
let conn: mariadb.PoolConnection | undefined;
try {
conn = await this.pool.getConnection();
//Setup tables for auctions and lifetimes
await conn.query(`
CREATE TABLE if NOT EXISTS auctions (
id INT AUTO_INCREMENT PRIMARY KEY,
auctionid VARCHAR(255) NOT NULL,
lbin DECIMAL(65,5) SIGNED,
UNIQUE INDEX 'auctionid' ('auctionid')
);
CREATE TABLE if NOT EXISTS lifetimes (id INT PRIMARY KEY, insertedon DATETIME(2));
`)
//Setup lifetime Trigger
await conn.query(`
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS insertLifetime
AFTER INSERT ON auctions
FOR EACH ROW
BEGIN
INSERT INTO lifetimes (id, insertedon)
VALUES (NEW.ID, NOW());
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS updateLifetime
AFTER UPDATE ON auctions
FOR EACH ROW
BEGIN
UPDATE lifetimes SET insertedon = NOW() WHERE id=NEW.ID;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS removeLifetime
BEFORE DELETE ON auctions
FOR EACH ROW
BEGIN
DELETE FROM lifetimes WHERE id=OLD.ID;
END$$
DELIMITER ;
`)
//Setup Table sanitation
await conn.query(`
DELIMITER $$
CREATE PROCEDURE IF NOT EXISTS CleanupOldEntries()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE temp_id INT;
DECLARE cur CURSOR FOR
SELECT id
FROM lifetimes
WHERE TIMESTAMPDIFF(HOUR, insertedon, NOW()) >= 6;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO temp_id;
IF done THEN
LEAVE read_loop;
END IF;
DELETE FROM auctions WHERE id = temp_id;
END LOOP;
CLOSE cur;
END$$
DELIMITER ;
SET GLOBAL event_scheduler = ON;
CREATE EVENT IF NOT EXISTS CleanupOldEntriesEvent
ON SCHEDULE EVERY 2 MINUTE
DO
CALL CleanupOldEntries();
`)
}
catch (error) {
console.error("InitDB Error: ", error);
throw error;
}
finally {
if (conn) conn.release();
}
}
//INSERT ELEMENT IN AUCTIONS TABLE OR UPDATE IF IT ALREADY EXISTS
public static async Upsert(auctionid: string, lbin: number) {
let conn: mariadb.PoolConnection | undefined;
try {
conn = await this.pool.getConnection();
await conn.beginTransaction();
await conn.query(`
INSERT INTO auctions (auctionid, LBin)
VALUES (?,?)
ON DUPLICATE KEY UPDATE
LBin = VALUES(LBin);
`, [auctionid, lbin]);
await conn.commit();
}
catch (error) {
console.error("InitDB Error: ", error);
if(conn) await conn.rollback();
throw error;
}
finally {
if (conn) conn.release();
}
}
//REMOVE ELEMENT IN AUCTIONS TABLE
public static async Remove(auctionId: string) {
let conn: mariadb.PoolConnection | undefined;
try {
conn = await this.pool.getConnection();
await conn.beginTransaction();
await conn.query(`
DELETE FROM auctions WHERE auctionid = ?
`,[auctionId]);
await conn.commit();
}
catch (error) {
console.error("InitDB Error: ", error);
if(conn) await conn.rollback();
throw error;
}
finally {
if (conn) conn.release();
}
}
//MATCH PROVIDED ELEMENTS IN AUCTIONS TABLE - returns true/false
public static async Match(auctionid:string|string[],lbin:number|number[]): Promise<boolean|any> {
let conn: mariadb.PoolConnection | undefined;
let result;
try{
conn = await this.pool.getConnection();
if(Array.isArray(auctionid) && Array.isArray(lbin))
if(auctionid.length === lbin.length) {
result = await conn.query(`
CREATE TEMPORARY TABLE IF NOT EXISTS TEMP (
auctionID VARCHAR(255) PRIMARY KEY,
lbin DECIMAL(65,5)
);
INSERT INTO TEMP (auctionID, lbin) VALUES ?
SELECT tmp.*
FROM TEMP AS tmp
WHERE NOT EXISTS (
SELECT 1
FROM auctions AS auc
WHERE auc.auctionID = tmp.auctionID
AND auc.lbin = tmp.lbin);
`,[await this.UnifiedArray(auctionid,lbin)])
return result;
}
else if(Array.isArray(auctionid) || Array.isArray(lbin)) throw Error('Match SQL Function error - cannot match collection to singlet');
else {
result = await conn.query(`
SELECT CASE
WHEN COUNT(*) > 0
THEN true
ELSE false
END AS user_exists
FROM auctions WHERE auctionID = ?;
`,[auctionid])
return Boolean(result[0].result)
}
}
catch(error)
{
console.error("message_before_error: ", error);
throw error;
}
finally
{
if (conn) conn.release();
}
}
//EXAMPLE BLOCK OF CODE FOR ADDING DATABASE FUNCTIONS
/*
public static async example_name() {
let conn:mariadb.PoolConnection|undefined;
try{
conn = await this.pool.getConnection();
await conn.beginTransaction();
//CODE HERE//
await conn.commit();
}
catch(error)
{
console.error("message_before_error: ", error);
if(conn) await conn.rollback();
throw error;
}
finally
{
if(conn) conn.release();
}
*/
private static async UnifiedArray<T1, T2>(auctionid: string[], lbin: number[]): Promise<{ x: string[], y: number[] }> {
return { x: [...auctionid], y: [...lbin] };
}
}
export {
SqlSystem
}