LinkCloudDev/server/Utility/lsModel.js
2024-08-02 18:55:55 -04:00

226 lines
6.8 KiB
JavaScript

import { runPrepQuery, numRows } from "../Utility/db.js";
import { Warn, Log, Err, Debug } from "./loggerUtility.js";
import { Webhook } from 'discord-webhook-node';
import crypto from "crypto";
const linkshells = {};
const reloadModel = (lsName, serverId, ffxiver) => {
runPrepQuery(
"SELECT * FROM linkshells WHERE server = ? AND `name` = ? AND `ffxiver` = ? LIMIT 0,1",
[serverId, lsName, ffxiver],
async (r, f, e) => {
if (!e) {
if (numRows(r)) {
updateMemory(r[0])
} else {
Warn(`Unable to locate linkshell model ${lsName}, ${serverId}, ${ffxiver}`);
}
} else {
console.log(e);
}
}
);
};
export const getLsFromChannelId = (channelId) => {
for(const ls in linkshells) {
for(const channel in linkshells[ls]?.channels) {
if(linkshells[ls]?.channels[channel]?.channelId == channelId) {
return linkshells[ls]
}
}
}
return false
}
const reloadModelById = (id) => {
runPrepQuery("SELECT * FROM linkshells WHERE id = ? LIMIT 0,1", [id], async (r, f, e) => {
if (!e) {
if (numRows(r)) {
updateMemory(r[0])
} else {
Warn(`Unable to locate linkshell model ${id},`);
}
} else {
console.log(e);
}
});
};
const getLSChannels = (linkshellId) => {
return new Promise((resolve, reject) => {
const out = [];
runPrepQuery("SELECT * FROM linkshellchannels WHERE linkshellId = ?", [linkshellId], (r, f, e) => {
if (!e) {
if (numRows(r)) {
for (const row of r) {
row.Webhook = new Webhook(row.webhookUrl)
row.hookHistory = []
out.push(row);
}
}
resolve(out);
} else {
console.log(e);
reject(e);
}
});
});
};
export const createNewLS = async (lsName, serverId, ffxiver, ownerId) => {
return new Promise(async (resolve, reject) => {
if (!(await lsExists(lsName, serverId, ffxiver))) {
runPrepQuery(
"INSERT INTO linkshells (`name`, `server`, `discord_owner_id`, `ffxiver`) VALUES(?,?,?,?)",
[lsName, serverId, ownerId, ffxiver],
(r, f, e) => {
if (!e) {
reloadModel(lsName, serverId, ffxiver);
resolve(true);
} else {
reject(e);
}
}
);
} else {
resolve(false);
}
});
};
export const addChannelForLinkshell = (linkshellId, channelId, guildId, webhookUrl) => {
return new Promise((resolve, reject) => {
runPrepQuery("DELETE FROM linkshellchannels WHERE guildId = ? AND channelId = ? LIMIT 1", [guildId, channelId], (r,f,e) => {
if(!e) {
runPrepQuery(
"INSERT INTO linkshellchannels (channelId, linkshellId, guildId, webhookUrl) VALUES(?,?,?,?)",
[channelId, linkshellId, guildId, webhookUrl],
(r, f, e) => {
if (!e) {
reloadModelById(linkshellId);
resolve(true);
} else {
reject(e);
}
}
);
} else {
reject(e);
}
})
});
};
export const getLSFromGuildId = (gid) => {
for (const platform in linkshells) {
for (const server in linkshells[platform]) {
for (const linkshell in linkshells[platform][server]) {
for (const channel in linkshells[platform][server][linkshell].channels) {
if (linkshells[platform][server][linkshell].channels[channel].guildId == gid) {
return getLSModel(linkshell, platform, server)
}
}
}
}
}
return false;
};
export const getLSModel = (ls, platform, server) => {
try {
return linkshells[platform][server][ls] ? linkshells[platform][server][ls] : false;
} catch (e) {
console.log(e)
return false
}
};
export const updateLSModel = (ls, newModel) => {
if (!linkshells[ls]) return false;
linkshells[ls] = { ...linkshells[ls], ...newModel };
return true;
};
export const lsExists = (ls, server, version) => {
return new Promise((resolve, reject) => {
const lsExistsResult = runPrepQuery(
"SELECT * FROM linkshells WHERE server = ? AND `name` = ? AND `ffxiver` = ? LIMIT 0,1",
[server, ls, version],
(r, f, e) => {
if (e) return reject(e);
if (numRows(r)) {
resolve(true);
} else {
resolve(false);
}
}
);
});
};
export const loadModelFromDB = () => {
return new Promise((resolve, reject) => {
runPrepQuery("SELECT * FROM linkshells", [], async (r, f, e) => {
if (!e) {
if (numRows(r)) {
for(const row of r) {
updateMemory(row)
}
}
} else {
console.log(e);
}
resolve(true)
});
})
};
const updateMemory = async (row) => {
if(!linkshells[row.ffxiver]) linkshells[row.ffxiver] = {}
if(!linkshells[row.ffxiver][row.server]) linkshells[row.ffxiver][row.server] = {}
if(linkshells[row.ffxiver][row.server][row.name]?.webhookTimer) clearTimeout(linkshells[row.ffxiver][row.server][row.name].webhookTimer)
linkshells[row.ffxiver][row.server][row.name] = row
linkshells[row.ffxiver][row.server][row.name].channels = await getLSChannels(row.id);
linkshells[row.ffxiver][row.server][row.name].webhookQueue = []
linkshells[row.ffxiver][row.server][row.name].webhookTimer = processWebhookQueue(linkshells[row.ffxiver][row.server][row.name])
}
const processWebhookQueue = (linkshell) => {
const nextItem = linkshell.webhookQueue.shift()
if(!nextItem) {
return setTimeout(() => { processWebhookQueue(linkshell) }, 100)
}
const packet = nextItem.packet
const trimmedMsg = packet.payload.message.replace(/[\n\r]/g, '').trim()
console.log(`"${packet.payload.name + trimmedMsg}"`)
const msgHash = crypto.createHash("md5").update(packet.payload.name + trimmedMsg).digest("hex");
for (const channel of linkshell.channels) {
if (!findInRecent(msgHash, channel.hookHistory)) {
channel.hookHistory.push({msgHash: msgHash, timeStamp: Date.now()})
Debug(`${msgHash} added to message hashes.`)
channel.Webhook.setUsername(packet.payload.name);
channel.Webhook.setAvatar("https://ui-avatars.com/api/?background=random&name=" + packet.payload.name)
channel.Webhook.send(trimmedMsg);
if(channel.hookHistory.length > 100) {
const removed = channel.hookHistory.shift()
Debug(`${removed.msgHash} removed from hashes.`)
}
}
}
return setTimeout(() => { processWebhookQueue(linkshell) }, 100)
}
const findInRecent = (msgHash, history) => {
for(const idx in history) {
const msgHashData = history[idx]
if(msgHashData.msgHash == msgHash) {
Debug(`Found Message Hash`)
if(msgHashData.timeStamp + 5000 > Date.now()) {
Debug(`Hash Timestamp Not Expired ${msgHashData.timeStamp + 5000} / ${Date.now()}`)
return true
} else {
Debug(`Hash Timestamp Expired ${msgHashData.timeStamp + 5000} / ${Date.now()}`)
}
} else {
Debug(`Message Hash Not Found. ${msgHash}`)
}
}
return false
}