226 lines
6.8 KiB
JavaScript
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
|
|
} |