Finished adding rest of database access classes
This commit is contained in:
parent
658348d993
commit
3b0b7bd559
|
@ -9,6 +9,7 @@ LICENSE
|
||||||
# Specific to this repository
|
# Specific to this repository
|
||||||
dist/
|
dist/
|
||||||
data/
|
data/
|
||||||
|
public/
|
||||||
docs/
|
docs/
|
||||||
*.md
|
*.md
|
||||||
tmp/
|
tmp/
|
||||||
|
|
|
@ -44,7 +44,8 @@ Certain variables are set via `.env` at the project root. These are for system c
|
||||||
- `ADMINS`: A comma-separated (with a space) list of bot admin IDs
|
- `ADMINS`: A comma-separated (with a space) list of bot admin IDs
|
||||||
- `SUPPORT`: A comma-separated (with a space) list of bot support IDs
|
- `SUPPORT`: A comma-separated (with a space) list of bot support IDs
|
||||||
- `WOLFRAM_API_KEY`: Used for `commands/utility/calc`
|
- `WOLFRAM_API_KEY`: Used for `commands/utility/calc`
|
||||||
- `DEV`: Enables dev mode as long as it isn't a falsy value (`DEV=1` works for example)
|
- `DEV`: Enables dev mode as long as it isn't a falsy value (`DEV=1` works for example), specific values can be checked to test certain features
|
||||||
|
- `DEV_DATABASE`: Specifies the file to use for trying out changes on a database (`DEV_DATABASE=test` writes to `data/test.db`)
|
||||||
|
|
||||||
# Utility Functions
|
# Utility Functions
|
||||||
|
|
||||||
|
|
|
@ -88,17 +88,16 @@ export const LeaderboardCommand = new NamedCommand({
|
||||||
async run({send, guild, channel, client}) {
|
async run({send, guild, channel, client}) {
|
||||||
if (isAuthorized(guild, channel)) {
|
if (isAuthorized(guild, channel)) {
|
||||||
const users = User.all();
|
const users = User.all();
|
||||||
const ids = Object.keys(users);
|
users.sort((a, b) => b.money - a.money);
|
||||||
ids.sort((a, b) => users[b].money - users[a].money);
|
|
||||||
const fields = [];
|
const fields = [];
|
||||||
|
|
||||||
for (let i = 0, limit = Math.min(10, ids.length); i < limit; i++) {
|
for (let i = 0, limit = Math.min(10, users.length); i < limit; i++) {
|
||||||
const id = ids[i];
|
const id = users[i].id;
|
||||||
const user = await client.users.fetch(id);
|
const user = await client.users.fetch(id);
|
||||||
|
|
||||||
fields.push({
|
fields.push({
|
||||||
name: `#${i + 1}. ${user.tag}`,
|
name: `#${i + 1}. ${user.tag}`,
|
||||||
value: pluralise(users[id].money, "Mon", "s")
|
value: pluralise(users[i].money, "Mon", "s")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ export default new NamedCommand({
|
||||||
any: new RestCommand({
|
any: new RestCommand({
|
||||||
async run({send, guild, args, combined}) {
|
async run({send, guild, args, combined}) {
|
||||||
const role = args[0] as Role;
|
const role = args[0] as Role;
|
||||||
new Guild(guild!.id).streamingRoles.set(role.id, combined);
|
new Guild(guild!.id).setStreamingRole(role.id, combined);
|
||||||
send(
|
send(
|
||||||
`Successfully set the category \`${combined}\` to notify \`${role.name}\`.`
|
`Successfully set the category \`${combined}\` to notify \`${role.name}\`.`
|
||||||
);
|
);
|
||||||
|
@ -229,11 +229,14 @@ export default new NamedCommand({
|
||||||
async run({send, guild, args}) {
|
async run({send, guild, args}) {
|
||||||
const role = args[0] as Role;
|
const role = args[0] as Role;
|
||||||
const guildStorage = new Guild(guild!.id);
|
const guildStorage = new Guild(guild!.id);
|
||||||
const category = guildStorage.streamingRoles.get(role.id);
|
const category = guildStorage.getStreamingRole(role.id);
|
||||||
delete guildStorage.streamingRoles[role.id];
|
if (guildStorage.removeStreamingRole(role.id)) {
|
||||||
send(
|
send(
|
||||||
`Successfully removed the category \`${category}\` to notify \`${role.name}\`.`
|
`Successfully removed the category \`${category}\` to notify \`${role.name}\`.`
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
send(`Failed to remove streaming role \`${role.id}\` (\`${category}\`).`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -248,8 +251,12 @@ export default new NamedCommand({
|
||||||
const voiceChannel = message.member?.voice.channel;
|
const voiceChannel = message.member?.voice.channel;
|
||||||
if (!voiceChannel) return send("You are not in a voice channel.");
|
if (!voiceChannel) return send("You are not in a voice channel.");
|
||||||
const guildStorage = new Guild(guild!.id);
|
const guildStorage = new Guild(guild!.id);
|
||||||
delete guildStorage.defaultChannelNames[voiceChannel.id];
|
|
||||||
return send(`Successfully removed the default channel name for ${voiceChannel}.`);
|
if (guildStorage.removeDefaultChannelName(voiceChannel.id)) {
|
||||||
|
send(`Successfully removed the default channel name for ${voiceChannel}.`);
|
||||||
|
} else {
|
||||||
|
send(`Failed to remove the default channel name for ${voiceChannel}`);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
any: new RestCommand({
|
any: new RestCommand({
|
||||||
async run({send, guild, message, combined}) {
|
async run({send, guild, message, combined}) {
|
||||||
|
@ -262,7 +269,7 @@ export default new NamedCommand({
|
||||||
if (!guild!.me?.permissions.has(Permissions.FLAGS.MANAGE_CHANNELS))
|
if (!guild!.me?.permissions.has(Permissions.FLAGS.MANAGE_CHANNELS))
|
||||||
return send("I can't change channel names without the `Manage Channels` permission.");
|
return send("I can't change channel names without the `Manage Channels` permission.");
|
||||||
|
|
||||||
guildStorage.defaultChannelNames.set(voiceChannel.id, newName);
|
guildStorage.setDefaultChannelName(voiceChannel.id, newName);
|
||||||
return await send(`Set default channel name to "${newName}".`);
|
return await send(`Set default channel name to "${newName}".`);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -115,7 +115,7 @@ export default new NamedCommand({
|
||||||
let found = false;
|
let found = false;
|
||||||
|
|
||||||
// Check if it's a valid category
|
// Check if it's a valid category
|
||||||
for (const [roleID, categoryName] of Object.entries(guildStorage.streamingRoles)) {
|
for (const [roleID, categoryName] of guildStorage.getStreamingRoleEntries()) {
|
||||||
if (combined === categoryName) {
|
if (combined === categoryName) {
|
||||||
found = true;
|
found = true;
|
||||||
memberStorage.streamCategory = roleID;
|
memberStorage.streamCategory = roleID;
|
||||||
|
@ -133,10 +133,16 @@ export default new NamedCommand({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
const categories = [];
|
||||||
|
|
||||||
|
for (const [_, category] of guildStorage.getStreamingRoleEntries()) {
|
||||||
|
categories.push(category);
|
||||||
|
}
|
||||||
|
|
||||||
send(
|
send(
|
||||||
`No valid category found by \`${combined}\`! The available categories are: \`${Object.values(
|
`No valid category found by \`${combined}\`! The available categories are: \`${categories.join(
|
||||||
guildStorage.streamingRoles
|
", "
|
||||||
).join(", ")}\``
|
)}\``
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {NamedCommand, RestCommand} from "onion-lasers";
|
import {Command, NamedCommand, RestCommand} from "onion-lasers";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import {User} from "../../lib";
|
import {User} from "../../lib";
|
||||||
import {MessageEmbed} from "discord.js";
|
import {MessageEmbed} from "discord.js";
|
||||||
|
@ -9,11 +9,12 @@ export default new NamedCommand({
|
||||||
const user = new User(author.id);
|
const user = new User(author.id);
|
||||||
const embed = new MessageEmbed().setTitle(`Todo list for ${author.tag}`).setColor("BLUE");
|
const embed = new MessageEmbed().setTitle(`Todo list for ${author.tag}`).setColor("BLUE");
|
||||||
|
|
||||||
for (const timestamp in user.todoList) {
|
for (const [id, {entry, lastModified}] of user.getTodoEntries()) {
|
||||||
const date = new Date(Number(timestamp));
|
|
||||||
embed.addField(
|
embed.addField(
|
||||||
`${moment(date).format("LT")} ${moment(date).format("LL")} (${moment(date).fromNow()})`,
|
`\`${id}\`: ${moment(lastModified).format("LT")} ${moment(lastModified).format("LL")} (${moment(
|
||||||
user.todoList[timestamp]
|
lastModified
|
||||||
|
).fromNow()})`,
|
||||||
|
entry
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,40 +25,29 @@ export default new NamedCommand({
|
||||||
run: "You need to specify a note to add.",
|
run: "You need to specify a note to add.",
|
||||||
any: new RestCommand({
|
any: new RestCommand({
|
||||||
async run({send, author, combined}) {
|
async run({send, author, combined}) {
|
||||||
const user = new User(author.id);
|
new User(author.id).addTodoEntry(combined);
|
||||||
user.todoList[Date.now().toString()] = combined;
|
|
||||||
Storage.save();
|
|
||||||
send(`Successfully added \`${combined}\` to your todo list.`);
|
send(`Successfully added \`${combined}\` to your todo list.`);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
remove: new NamedCommand({
|
remove: new NamedCommand({
|
||||||
run: "You need to specify a note to remove.",
|
run: "You need to specify a note to remove.",
|
||||||
any: new RestCommand({
|
number: new Command({
|
||||||
async run({send, author, combined}) {
|
async run({send, author, args}) {
|
||||||
const user = new User(author.id);
|
const user = new User(author.id);
|
||||||
let isFound = false;
|
const success = user.removeTodoEntry(args[0]);
|
||||||
|
|
||||||
for (const timestamp in user.todoList) {
|
if (success) {
|
||||||
const selectedNote = user.todoList[timestamp];
|
send(`Removed Note \`${args[0]}\` from your todo list.`);
|
||||||
|
} else {
|
||||||
if (selectedNote === combined) {
|
send("That item couldn't be found.");
|
||||||
delete user.todoList[timestamp];
|
|
||||||
Storage.save();
|
|
||||||
isFound = true;
|
|
||||||
send(`Removed \`${combined}\` from your todo list.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isFound) send("That item couldn't be found.");
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
clear: new NamedCommand({
|
clear: new NamedCommand({
|
||||||
async run({send, author}) {
|
async run({send, author}) {
|
||||||
const user = new User(author.id);
|
new User(author.id).clearTodoEntries();
|
||||||
user.todoList = {};
|
|
||||||
Storage.save();
|
|
||||||
send("Cleared todo list.");
|
send("Cleared todo list.");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,15 +23,23 @@ class Config {
|
||||||
this._systemLogsChannel = systemLogsChannel;
|
this._systemLogsChannel = systemLogsChannel;
|
||||||
db.prepare("UPDATE Settings SET SystemLogsChannel = ? WHERE Tag = 'Main'").run(systemLogsChannel);
|
db.prepare("UPDATE Settings SET SystemLogsChannel = ? WHERE Tag = 'Main'").run(systemLogsChannel);
|
||||||
}
|
}
|
||||||
get webhooks() {
|
|
||||||
return this._webhooks;
|
getWebhook(id: string) {
|
||||||
|
return this._webhooks.get(id);
|
||||||
|
}
|
||||||
|
getWebhookEntries() {
|
||||||
|
return this._webhooks.entries();
|
||||||
|
}
|
||||||
|
hasWebhook(id: string) {
|
||||||
|
return this._webhooks.has(id);
|
||||||
}
|
}
|
||||||
// getWebhook, setWebhook, removeWebhook, hasWebhook, getWebhookEntries
|
|
||||||
setWebhook(id: string, token: string) {
|
setWebhook(id: string, token: string) {
|
||||||
|
db.prepare("INSERT INTO Webhooks VALUES (?, ?)").run(id, token);
|
||||||
this._webhooks.set(id, token);
|
this._webhooks.set(id, token);
|
||||||
db.prepare(
|
}
|
||||||
"INSERT INTO Webhooks VALUES (:id, :token) ON CONFLICT (ID) DO UPDATE SET Token = :token WHERE ID = :id"
|
removeWebhook(id: string) {
|
||||||
).run({id, token});
|
db.prepare("DELETE FROM Webhooks WHERE ID = ?").run(id);
|
||||||
|
return this._webhooks.delete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ export class Guild {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.prepare(upsert("WelcomeType", "welcomeType")).run({
|
db.prepare(upsert("WelcomeType", "welcomeTypeInt")).run({
|
||||||
id: this.id,
|
id: this.id,
|
||||||
welcomeTypeInt
|
welcomeTypeInt
|
||||||
});
|
});
|
||||||
|
@ -154,13 +154,53 @@ export class Guild {
|
||||||
hasMessageEmbeds: +hasMessageEmbeds
|
hasMessageEmbeds: +hasMessageEmbeds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
get streamingRoles() {
|
|
||||||
return this._streamingRoles; // Role ID: Category Name
|
getStreamingRole(id: string) {
|
||||||
|
return this._streamingRoles.get(id);
|
||||||
}
|
}
|
||||||
get defaultChannelNames() {
|
getStreamingRoleEntries() {
|
||||||
return this._defaultChannelNames; // Channel ID: Channel Name
|
return this._streamingRoles.entries();
|
||||||
}
|
}
|
||||||
|
hasStreamingRole(id: string) {
|
||||||
|
return this._streamingRoles.has(id);
|
||||||
|
}
|
||||||
|
setStreamingRole(id: string, category: string) {
|
||||||
|
db.prepare("INSERT INTO StreamingRoles VALUES (?, ?, ?)").run(this.id, id, category);
|
||||||
|
this._streamingRoles.set(id, category);
|
||||||
|
}
|
||||||
|
removeStreamingRole(id: string) {
|
||||||
|
db.prepare("DELETE FROM StreamingRoles WHERE GuildID = ? AND RoleID = ?").run(this.id, id);
|
||||||
|
return this._streamingRoles.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultChannelName(id: string) {
|
||||||
|
return this._defaultChannelNames.get(id);
|
||||||
|
}
|
||||||
|
getDefaultChannelNameEntries() {
|
||||||
|
return this._defaultChannelNames.entries();
|
||||||
|
}
|
||||||
|
hasDefaultChannelName(id: string) {
|
||||||
|
return this._defaultChannelNames.has(id);
|
||||||
|
}
|
||||||
|
setDefaultChannelName(id: string, name: string) {
|
||||||
|
db.prepare("INSERT INTO DefaultChannelNames VALUES (?, ?, ?)").run(this.id, id, name);
|
||||||
|
this._defaultChannelNames.set(id, name);
|
||||||
|
}
|
||||||
|
removeDefaultChannelName(id: string) {
|
||||||
|
db.prepare("DELETE FROM DefaultChannelNames WHERE GuildID = ? AND ChannelID = ?").run(this.id, id);
|
||||||
|
return this._defaultChannelNames.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
get autoRoles() {
|
get autoRoles() {
|
||||||
return this._autoRoles; // string array of role IDs
|
return this._autoRoles;
|
||||||
|
}
|
||||||
|
set autoRoles(autoRoles) {
|
||||||
|
this._autoRoles = autoRoles;
|
||||||
|
db.prepare("DELETE FROM AutoRoles WHERE GuildID = ?").run(this.id);
|
||||||
|
const addAutoRoles = db.prepare("INSERT INTO AutoRoles VALUES (?, ?)");
|
||||||
|
|
||||||
|
for (const roleID of autoRoles) {
|
||||||
|
addAutoRoles.run(this.id, roleID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@ export class User {
|
||||||
private _timezoneOffset: number | null; // This is for the standard timezone only, not the daylight savings timezone
|
private _timezoneOffset: number | null; // This is for the standard timezone only, not the daylight savings timezone
|
||||||
private _daylightSavingsRegion: "na" | "eu" | "sh" | "none";
|
private _daylightSavingsRegion: "na" | "eu" | "sh" | "none";
|
||||||
private _ecoBetInsurance: number;
|
private _ecoBetInsurance: number;
|
||||||
private _todoList: Collection<number, string>;
|
private _todoList: Collection<number, {lastModified: Date; entry: string}>;
|
||||||
|
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
const data = db.prepare("SELECT * FROM Users WHERE ID = ?").get(id);
|
const data = db.prepare("SELECT * FROM Users WHERE ID = ?").get(id);
|
||||||
const todoList = db.prepare("SELECT Timestamp, Entry FROM TodoLists WHERE UserID = ?").all(id) ?? [];
|
const todoList = db.prepare("SELECT ID, LastModified, Entry FROM TodoLists WHERE UserID = ?").all(id) ?? [];
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
const {Money, LastReceived, LastMonday, TimezoneOffset, DaylightSavingsRegion, EcoBetInsurance} = data;
|
const {Money, LastReceived, LastMonday, TimezoneOffset, DaylightSavingsRegion, EcoBetInsurance} = data;
|
||||||
|
@ -51,8 +51,11 @@ export class User {
|
||||||
|
|
||||||
this._todoList = new Collection();
|
this._todoList = new Collection();
|
||||||
|
|
||||||
for (const {Timestamp, Entry} of todoList) {
|
for (const {ID, LastModified, Entry} of todoList) {
|
||||||
this._todoList.set(Timestamp, Entry);
|
this._todoList.set(ID, {
|
||||||
|
entry: Entry,
|
||||||
|
lastModified: new Date(LastModified)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,8 +150,52 @@ export class User {
|
||||||
get todoList() {
|
get todoList() {
|
||||||
return this._todoList;
|
return this._todoList;
|
||||||
}
|
}
|
||||||
// NOTE: Need to figure out an actual ID system
|
|
||||||
setTodoEntry(timestamp: number, entry: string) {
|
getTodoEntry(id: number) {
|
||||||
db.prepare("INSERT INTO TodoLists VALUES (?, ?, ?)").run(this.id, timestamp, entry);
|
return this._todoList.get(id);
|
||||||
|
}
|
||||||
|
getTodoEntries() {
|
||||||
|
return this._todoList.entries();
|
||||||
|
}
|
||||||
|
hasTodoEntry(id: number) {
|
||||||
|
return this._todoList.has(id);
|
||||||
|
}
|
||||||
|
addTodoEntry(entry: string) {
|
||||||
|
const lastModified = Date.now();
|
||||||
|
db.prepare("INSERT INTO TodoLists (UserID, Entry, LastModified) VALUES (?, ?, ?)").run(
|
||||||
|
this.id,
|
||||||
|
entry,
|
||||||
|
lastModified
|
||||||
|
);
|
||||||
|
const {ID} = db
|
||||||
|
.prepare("SELECT ID FROM TodoLists WHERE UserID = ? AND Entry = ? AND LastModified = ?")
|
||||||
|
.get(this.id, entry, lastModified);
|
||||||
|
this._todoList.set(ID, {
|
||||||
|
entry,
|
||||||
|
lastModified: new Date(lastModified)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setTodoEntry(id: number, entry: string): boolean {
|
||||||
|
const lastModified = Date.now();
|
||||||
|
const exists = !!db.prepare("SELECT * FROM TodoLists WHERE UserID = ? AND ID = ?").get(this.id, id);
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
db.prepare("INSERT INTO TodoLists VALUES (?, ?, ?, ?)").run(id, this.id, entry, lastModified);
|
||||||
|
this._todoList.set(id, {
|
||||||
|
entry,
|
||||||
|
lastModified: new Date(lastModified)
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeTodoEntry(id: number) {
|
||||||
|
db.prepare("DELETE FROM TodoLists WHERE UserID = ? AND ID = ?").run(this.id, id);
|
||||||
|
return this._todoList.delete(id);
|
||||||
|
}
|
||||||
|
clearTodoEntries() {
|
||||||
|
db.prepare("DELETE FROM TodoLists WHERE UserID = ?").run(this.id);
|
||||||
|
this._todoList.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@ import {Permissions} from "discord.js";
|
||||||
|
|
||||||
client.on("voiceStateUpdate", async (before, after) => {
|
client.on("voiceStateUpdate", async (before, after) => {
|
||||||
const channel = before.channel;
|
const channel = before.channel;
|
||||||
const {defaultChannelNames} = new Guild(after.guild.id);
|
const guild = new Guild(after.guild.id);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
channel &&
|
channel &&
|
||||||
channel.members.size === 0 &&
|
channel.members.size === 0 &&
|
||||||
defaultChannelNames.has(channel.id) &&
|
guild.hasDefaultChannelName(channel.id) &&
|
||||||
before.guild.me?.permissions.has(Permissions.FLAGS.MANAGE_CHANNELS)
|
before.guild.me?.permissions.has(Permissions.FLAGS.MANAGE_CHANNELS)
|
||||||
) {
|
) {
|
||||||
channel.setName(defaultChannelNames.get(channel.id)!);
|
channel.setName(guild.getDefaultChannelName(channel.id)!);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {join} from "path";
|
||||||
// Guilds: ID, Prefix (TEXT NULLABLE), WelcomeType (INT), WelcomeChannel (TEXT NULLABLE), WelcomeMessage (TEXT NULLABLE), StreamingChannel (TEXT NULLABLE), HasMessageEmbeds (BOOL)
|
// Guilds: ID, Prefix (TEXT NULLABLE), WelcomeType (INT), WelcomeChannel (TEXT NULLABLE), WelcomeMessage (TEXT NULLABLE), StreamingChannel (TEXT NULLABLE), HasMessageEmbeds (BOOL)
|
||||||
// Members: UserID, GuildID, StreamCategory (TEXT NULLABLE)
|
// Members: UserID, GuildID, StreamCategory (TEXT NULLABLE)
|
||||||
// Webhooks: ID, Token (TEXT)
|
// Webhooks: ID, Token (TEXT)
|
||||||
// TodoLists: UserID, Timestamp (TIME), Entry (TEXT)
|
// TodoLists: ID (INT PRIMARY KEY), UserID, Entry (TEXT), LastModified (TIME)
|
||||||
// StreamingRoles: GuildID, RoleID, Category (TEXT)
|
// StreamingRoles: GuildID, RoleID, Category (TEXT)
|
||||||
// DefaultChannelNames: GuildID, ChannelID, Name (TEXT)
|
// DefaultChannelNames: GuildID, ChannelID, Name (TEXT)
|
||||||
// AutoRoles: GuildID, RoleID
|
// AutoRoles: GuildID, RoleID
|
||||||
|
@ -33,7 +33,7 @@ import {join} from "path";
|
||||||
// - Booleans (marked as BOOL) will be stored as an integer, either 0 or 1 (though it just checks for 0).
|
// - Booleans (marked as BOOL) will be stored as an integer, either 0 or 1 (though it just checks for 0).
|
||||||
|
|
||||||
const DATA_FOLDER = "data";
|
const DATA_FOLDER = "data";
|
||||||
const DATABASE_FILE = join(DATA_FOLDER, "main.db");
|
const DATABASE_FILE = join(DATA_FOLDER, `${process.env.DEV_DATABASE ?? "main"}.db`);
|
||||||
|
|
||||||
// Calling migrations[2]() migrates the database from version 2 to version 3.
|
// Calling migrations[2]() migrates the database from version 2 to version 3.
|
||||||
// NOTE: Once a migration is written, DO NOT change that migration or it'll break all future migrations.
|
// NOTE: Once a migration is written, DO NOT change that migration or it'll break all future migrations.
|
||||||
|
@ -84,9 +84,10 @@ const migrations: (() => void)[] = [
|
||||||
Token TEXT NOT NULL
|
Token TEXT NOT NULL
|
||||||
)`,
|
)`,
|
||||||
`CREATE TABLE TodoLists (
|
`CREATE TABLE TodoLists (
|
||||||
|
ID INTEGER NOT NULL PRIMARY KEY ON CONFLICT REPLACE AUTOINCREMENT,
|
||||||
UserID TEXT NOT NULL,
|
UserID TEXT NOT NULL,
|
||||||
Timestamp INT NOT NULL,
|
Entry TEXT NOT NULL,
|
||||||
Entry TEXT NOT NULL
|
LastModified INT NOT NULL
|
||||||
)`,
|
)`,
|
||||||
`CREATE TABLE StreamingRoles (
|
`CREATE TABLE StreamingRoles (
|
||||||
GuildID TEXT NOT NULL,
|
GuildID TEXT NOT NULL,
|
||||||
|
@ -108,11 +109,18 @@ const migrations: (() => void)[] = [
|
||||||
if (hasLegacyData) {
|
if (hasLegacyData) {
|
||||||
const config = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
const config = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
||||||
const {users, guilds} = JSON.parse(readFileSync(STORAGE_FILE, "utf-8"));
|
const {users, guilds} = JSON.parse(readFileSync(STORAGE_FILE, "utf-8"));
|
||||||
|
|
||||||
db.prepare("INSERT INTO Settings VALUES ('Main', ?)").run(config.systemLogsChannel);
|
db.prepare("INSERT INTO Settings VALUES ('Main', ?)").run(config.systemLogsChannel);
|
||||||
|
const addWebhooks = db.prepare("INSERT INTO Webhooks VALUES (?, ?)");
|
||||||
|
const addUsers = db.prepare("INSERT INTO Users VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
const addTodoLists = db.prepare("INSERT INTO TodoLists (UserID, Entry, LastModified) VALUES (?, ?, ?)");
|
||||||
|
const addGuilds = db.prepare("INSERT INTO Guilds VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
const addMembers = db.prepare("INSERT INTO Members VALUES (?, ?, ?)");
|
||||||
|
const addStreamingRoles = db.prepare("INSERT INTO StreamingRoles VALUES (?, ?, ?)");
|
||||||
|
const addDefaultChannelNames = db.prepare("INSERT INTO DefaultChannelNames VALUES (?, ?, ?)");
|
||||||
|
const addAutoRoles = db.prepare("INSERT INTO AutoRoles VALUES (?, ?)");
|
||||||
|
|
||||||
for (const [id, token] of Object.entries(config.webhooks)) {
|
for (const [id, token] of Object.entries(config.webhooks)) {
|
||||||
db.prepare("INSERT INTO Webhooks VALUES (?, ?)").run(id, token);
|
addWebhooks.run(id, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id in users) {
|
for (const id in users) {
|
||||||
|
@ -134,19 +142,11 @@ const migrations: (() => void)[] = [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.prepare("INSERT INTO Users VALUES (?, ?, ?, ?, ?, ?, ?)").run(
|
addUsers.run(id, money, lastReceived, lastMonday, timezone, dstInfo, ecoBetInsurance);
|
||||||
id,
|
|
||||||
money,
|
|
||||||
lastReceived,
|
|
||||||
lastMonday,
|
|
||||||
timezone,
|
|
||||||
dstInfo,
|
|
||||||
ecoBetInsurance
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const timestamp in todoList) {
|
for (const timestamp in todoList) {
|
||||||
const entry = todoList[timestamp];
|
const entry = todoList[timestamp];
|
||||||
db.prepare("INSERT INTO TodoLists VALUES (?, ?, ?)").run(id, Number(timestamp), entry);
|
addTodoLists.run(id, entry, Number(timestamp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ const migrations: (() => void)[] = [
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.prepare("INSERT INTO Guilds VALUES (?, ?, ?, ?, ?, ?, ?)").run(
|
addGuilds.run(
|
||||||
id,
|
id,
|
||||||
prefix,
|
prefix,
|
||||||
welcomeTypeInt,
|
welcomeTypeInt,
|
||||||
|
@ -186,28 +186,28 @@ const migrations: (() => void)[] = [
|
||||||
|
|
||||||
for (const userID in members) {
|
for (const userID in members) {
|
||||||
const {streamCategory} = members[userID];
|
const {streamCategory} = members[userID];
|
||||||
db.prepare("INSERT INTO Members VALUES (?, ?, ?)").run(userID, id, streamCategory);
|
addMembers.run(userID, id, streamCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const roleID in streamingRoles) {
|
for (const roleID in streamingRoles) {
|
||||||
const category = streamingRoles[roleID];
|
const category = streamingRoles[roleID];
|
||||||
db.prepare("INSERT INTO StreamingRoles VALUES (?, ?, ?)").run(id, roleID, category);
|
addStreamingRoles.run(id, roleID, category);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const channelID in channelNames) {
|
for (const channelID in channelNames) {
|
||||||
const channelName = channelNames[channelID];
|
const channelName = channelNames[channelID];
|
||||||
db.prepare("INSERT INTO DefaultChannelNames VALUES (?, ?, ?)").run(id, channelID, channelName);
|
addDefaultChannelNames.run(id, channelID, channelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoRoles) {
|
if (autoRoles) {
|
||||||
for (const roleID of autoRoles) {
|
for (const roleID of autoRoles) {
|
||||||
db.prepare("INSERT INTO AutoRoles VALUES (?, ?)").run(id, roleID);
|
addAutoRoles.run(id, roleID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generateSQLMigration(["UPDATE System SET Version = 2"])
|
// generateSQLMigration([])
|
||||||
];
|
];
|
||||||
|
|
||||||
const isExistingDatabase = existsSync(DATABASE_FILE);
|
const isExistingDatabase = existsSync(DATABASE_FILE);
|
||||||
|
@ -244,6 +244,10 @@ if (isExistingDatabase) {
|
||||||
if (version !== -1) {
|
if (version !== -1) {
|
||||||
for (let v = version; v < migrations.length; v++) {
|
for (let v = version; v < migrations.length; v++) {
|
||||||
migrations[v]();
|
migrations[v]();
|
||||||
|
|
||||||
|
if (v >= 1) {
|
||||||
|
db.prepare("UPDATE System SET Version = ?").run(v + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ client.on("voiceStateUpdate", async (before, after) => {
|
||||||
// Note: isStopStreamEvent can be called twice in a row - If Discord crashes/quits while you're streaming, it'll call once with a null channel and a second time with a channel.
|
// Note: isStopStreamEvent can be called twice in a row - If Discord crashes/quits while you're streaming, it'll call once with a null channel and a second time with a channel.
|
||||||
|
|
||||||
if (isStartStreamEvent || isStopStreamEvent) {
|
if (isStartStreamEvent || isStopStreamEvent) {
|
||||||
const {streamingChannel, streamingRoles} = new Guild(after.guild.id);
|
const guild = new Guild(after.guild.id);
|
||||||
|
const {streamingChannel} = guild;
|
||||||
|
|
||||||
if (streamingChannel) {
|
if (streamingChannel) {
|
||||||
const member = after.member!;
|
const member = after.member!;
|
||||||
|
@ -79,9 +80,9 @@ client.on("voiceStateUpdate", async (before, after) => {
|
||||||
const roleID = new Member(member.id, after.guild.id).streamCategory;
|
const roleID = new Member(member.id, after.guild.id).streamCategory;
|
||||||
|
|
||||||
// Only continue if they set a valid category.
|
// Only continue if they set a valid category.
|
||||||
if (roleID && streamingRoles.has(roleID)) {
|
if (roleID && guild.hasStreamingRole(roleID)) {
|
||||||
streamNotificationPing = `<@&${roleID}>`;
|
streamNotificationPing = `<@&${roleID}>`;
|
||||||
category = streamingRoles.get(roleID)!;
|
category = guild.getStreamingRole(roleID)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
streamList.set(member.id, {
|
streamList.set(member.id, {
|
||||||
|
|
|
@ -38,7 +38,7 @@ export function deleteWebhook(urlOrID: string): boolean {
|
||||||
else if (ID_PATTERN.test(urlOrID)) id = ID_PATTERN.exec(urlOrID)![1];
|
else if (ID_PATTERN.test(urlOrID)) id = ID_PATTERN.exec(urlOrID)![1];
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
delete config.webhooks[id];
|
config.removeWebhook(id);
|
||||||
refreshWebhookCache();
|
refreshWebhookCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +55,13 @@ client.on("ready", refreshWebhookCache);
|
||||||
export async function refreshWebhookCache(): Promise<void> {
|
export async function refreshWebhookCache(): Promise<void> {
|
||||||
webhookStorage.clear();
|
webhookStorage.clear();
|
||||||
|
|
||||||
for (const [id, token] of Object.entries(Config.webhooks)) {
|
for (const [id, token] of config.getWebhookEntries()) {
|
||||||
// If there are stored webhook IDs/tokens that don't work, delete those webhooks from storage.
|
// If there are stored webhook IDs/tokens that don't work, delete those webhooks from storage.
|
||||||
try {
|
try {
|
||||||
const webhook = await client.fetchWebhook(id, token);
|
const webhook = await client.fetchWebhook(id, token);
|
||||||
webhookStorage.set(webhook.channelId, webhook);
|
webhookStorage.set(webhook.channelId, webhook);
|
||||||
} catch {
|
} catch {
|
||||||
delete Config.webhooks[id];
|
config.removeWebhook(id);
|
||||||
Config.save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue