187 lines
6.7 KiB
JavaScript
187 lines
6.7 KiB
JavaScript
import { prefixCache, disabledCmdCache, disabledCache, commands, messageCommands } from "../collections.js";
|
|
|
|
import Postgres from "postgres";
|
|
const sql = Postgres(process.env.DB, {
|
|
onnotice: () => {}
|
|
});
|
|
|
|
const settingsSchema = `
|
|
CREATE TABLE IF NOT EXISTS settings (
|
|
id smallint PRIMARY KEY,
|
|
version integer NOT NULL, CHECK(id = 1)
|
|
);
|
|
`;
|
|
|
|
const schema = `
|
|
ALTER TABLE settings ADD COLUMN broadcast text;
|
|
CREATE TABLE guilds (
|
|
guild_id VARCHAR(30) NOT NULL PRIMARY KEY,
|
|
prefix VARCHAR(15) NOT NULL,
|
|
disabled text ARRAY NOT NULL,
|
|
disabled_commands text ARRAY NOT NULL
|
|
);
|
|
CREATE TABLE counts (
|
|
command VARCHAR NOT NULL PRIMARY KEY,
|
|
count integer NOT NULL
|
|
);
|
|
CREATE TABLE tags (
|
|
guild_id VARCHAR(30) NOT NULL,
|
|
name text NOT NULL,
|
|
content text NOT NULL,
|
|
author VARCHAR(30) NOT NULL,
|
|
UNIQUE(guild_id, name)
|
|
);
|
|
`;
|
|
|
|
const updates = [
|
|
"", // reserved
|
|
"CREATE TABLE IF NOT EXISTS settings ( id smallint PRIMARY KEY, version integer NOT NULL, CHECK(id = 1) );\nALTER TABLE guilds ADD COLUMN accessed timestamp;",
|
|
"ALTER TABLE guilds DROP COLUMN accessed",
|
|
"ALTER TABLE settings ADD COLUMN IF NOT EXISTS broadcast text"
|
|
];
|
|
|
|
export async function setup() {
|
|
const existingCommands = (await sql`SELECT command FROM counts`).map(x => x.command);
|
|
const commandNames = [...commands.keys(), ...messageCommands.keys()];
|
|
for (const command of existingCommands) {
|
|
if (!commandNames.includes(command)) {
|
|
await sql`DELETE FROM counts WHERE command = ${command}`;
|
|
}
|
|
}
|
|
for (const command of commandNames) {
|
|
if (!existingCommands.includes(command)) {
|
|
await sql`INSERT INTO counts ${sql({ command, count: 0 }, "command", "count")}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function upgrade(logger) {
|
|
try {
|
|
await sql.begin(async (sql) => {
|
|
await sql.unsafe(settingsSchema);
|
|
let version;
|
|
const settingsrow = (await sql`SELECT version FROM settings WHERE id = 1`);
|
|
if (settingsrow.length == 0) {
|
|
version = 0;
|
|
} else {
|
|
version = settingsrow[0].version;
|
|
}
|
|
const latestVersion = updates.length - 1;
|
|
if (version === 0) {
|
|
logger.info("Initializing PostgreSQL database...");
|
|
await sql.unsafe(schema);
|
|
} else if (version < latestVersion) {
|
|
logger.info(`Migrating PostgreSQL database, which is currently at version ${version}...`);
|
|
while (version < latestVersion) {
|
|
version++;
|
|
logger.info(`Running version ${version} update script...`);
|
|
await sql.unsafe(updates[version]);
|
|
}
|
|
} else if (version > latestVersion) {
|
|
throw new Error(`PostgreSQL database is at version ${version}, but this version of the bot only supports up to version ${latestVersion}.`);
|
|
} else {
|
|
return;
|
|
}
|
|
await sql`INSERT INTO settings ${sql({ id: 1, version: latestVersion })} ON CONFLICT (id) DO UPDATE SET version = ${latestVersion}`;
|
|
});
|
|
} catch (e) {
|
|
logger.error(`PostgreSQL migration failed: ${e}`);
|
|
logger.error("Unable to start the bot, quitting now.");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
export async function getGuild(query) {
|
|
let guild;
|
|
await sql.begin(async (sql) => {
|
|
guild = (await sql`SELECT * FROM guilds WHERE guild_id = ${query}`)[0];
|
|
if (guild == undefined) {
|
|
guild = { guild_id: query, prefix: process.env.PREFIX, disabled: [], disabled_commands: [] };
|
|
await sql`INSERT INTO guilds ${sql(guild)}`;
|
|
}
|
|
});
|
|
return guild;
|
|
}
|
|
|
|
export async function setPrefix(prefix, guild) {
|
|
await sql`UPDATE guilds SET prefix = ${prefix} WHERE guild_id = ${guild.id}`;
|
|
prefixCache.set(guild.id, prefix);
|
|
}
|
|
|
|
export async function getTag(guild, tag) {
|
|
const tagResult = await sql`SELECT * FROM tags WHERE guild_id = ${guild} AND name = ${tag}`;
|
|
return tagResult[0] ? { content: tagResult[0].content, author: tagResult[0].author } : undefined;
|
|
}
|
|
|
|
export async function getTags(guild) {
|
|
const tagArray = await sql`SELECT * FROM tags WHERE guild_id = ${guild}`;
|
|
const tags = {};
|
|
for (const tag of tagArray) {
|
|
tags[tag.name] = { content: tag.content, author: tag.author };
|
|
}
|
|
return tags;
|
|
}
|
|
|
|
export async function setTag(name, content, guild) {
|
|
await sql`INSERT INTO tags ${sql({ guild_id: guild.id, name, content: content.content, author: content.author }, "guild_id", "name", "content", "author")}`;
|
|
}
|
|
|
|
export async function editTag(name, content, guild) {
|
|
await sql`UPDATE tags SET content = ${content.content}, author = ${content.author} WHERE guild_id = ${guild.id} AND name = ${name}`;
|
|
}
|
|
|
|
export async function removeTag(name, guild) {
|
|
await sql`DELETE FROM tags WHERE guild_id = ${guild.id} AND name = ${name}`;
|
|
}
|
|
|
|
export async function setBroadcast(msg) {
|
|
await sql`UPDATE settings SET broadcast = ${msg} WHERE id = 1`;
|
|
}
|
|
|
|
export async function getBroadcast() {
|
|
const result = await sql`SELECT broadcast FROM settings WHERE id = 1`;
|
|
return result[0].broadcast;
|
|
}
|
|
|
|
export async function disableCommand(guild, command) {
|
|
const guildDB = await this.getGuild(guild);
|
|
await sql`UPDATE guilds SET disabled_commands = ${(guildDB.disabled_commands ? [...guildDB.disabled_commands, command] : [command]).filter((v) => !!v)} WHERE guild_id = ${guild}`;
|
|
disabledCmdCache.set(guild, guildDB.disabled_commands ? [...guildDB.disabled_commands, command] : [command].filter((v) => !!v));
|
|
}
|
|
|
|
export async function enableCommand(guild, command) {
|
|
const guildDB = await this.getGuild(guild);
|
|
const newDisabled = guildDB.disabled_commands ? guildDB.disabled_commands.filter(item => item !== command) : [];
|
|
await sql`UPDATE guilds SET disabled_commands = ${newDisabled} WHERE guild_id = ${guild}`;
|
|
disabledCmdCache.set(guild, newDisabled);
|
|
}
|
|
|
|
export async function disableChannel(channel) {
|
|
const guildDB = await this.getGuild(channel.guildID);
|
|
await sql`UPDATE guilds SET disabled_commands = ${[...guildDB.disabled, channel.id]} WHERE guild_id = ${channel.guildID}`;
|
|
disabledCache.set(channel.guildID, [...guildDB.disabled, channel.id]);
|
|
}
|
|
|
|
export async function enableChannel(channel) {
|
|
const guildDB = await this.getGuild(channel.guildID);
|
|
const newDisabled = guildDB.disabled.filter(item => item !== channel.id);
|
|
await sql`UPDATE guilds SET disabled_commands = ${newDisabled} WHERE guild_id = ${channel.guildID}`;
|
|
disabledCache.set(channel.guildID, newDisabled);
|
|
}
|
|
|
|
export async function getCounts() {
|
|
const counts = await sql`SELECT * FROM counts`;
|
|
const countObject = {};
|
|
for (const { command, count } of counts) {
|
|
countObject[command] = count;
|
|
}
|
|
return countObject;
|
|
}
|
|
|
|
export async function addCount(command) {
|
|
await sql`INSERT INTO counts ${sql({ command, count: 1 }, "command", "count")} ON CONFLICT (command) DO UPDATE SET count = counts.count + 1 WHERE counts.command = ${command}`;
|
|
}
|
|
|
|
export async function stop() {
|
|
await sql.end();
|
|
}
|