This commit is contained in:
parent
f9bb94a4a1
commit
486ed80d31
@ -1,10 +1,10 @@
|
|||||||
name: Silvanus Production Dockerization
|
name: Silvanus Production Dockerization
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
push:
|
||||||
branches:
|
tags:
|
||||||
- main
|
- '*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DHUB_UNAME: ${{ secrets.DHUB_UNAME }}
|
DHUB_UNAME: ${{ secrets.DHUB_UNAME }}
|
||||||
DHUB_PWORD: ${{ secrets.DHUB_PWORD }}
|
DHUB_PWORD: ${{ secrets.DHUB_PWORD }}
|
||||||
@ -27,7 +27,7 @@ jobs:
|
|||||||
cd silvanus
|
cd silvanus
|
||||||
else
|
else
|
||||||
cd silvanus
|
cd silvanus
|
||||||
git pull
|
git fetch --tags --force origin
|
||||||
fi
|
fi
|
||||||
git checkout ${{ gitea.ref}}
|
git checkout ${{ gitea.ref}}
|
||||||
- name: Build the Docker image
|
- name: Build the Docker image
|
||||||
|
|||||||
70
main.js
70
main.js
@ -31,7 +31,77 @@ const { GuildInfo } = require('./modules/CustomClasses.js');
|
|||||||
const isDev = process.env.DEBUG === "true";
|
const isDev = process.env.DEBUG === "true";
|
||||||
let statusChannel;
|
let statusChannel;
|
||||||
|
|
||||||
|
// Silvanus is being shut down: on launch, leave every guild and exit instead of starting normally.
|
||||||
|
const shuttingDown = true;
|
||||||
|
|
||||||
|
const farewellMessage = [
|
||||||
|
'Silvanus is being permanently shut down. Many of its core features are now built into Grow A Tree, and Discord has restricted bots\' access to message content, which Silvanus needs in order to work.',
|
||||||
|
'',
|
||||||
|
'It has been so much fun over the last few years. Thank you all for your support, and much love to you all!',
|
||||||
|
'',
|
||||||
|
'So long and thanks for all the apples 🍎',
|
||||||
|
'-Silvanus and @vfsh'
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
// Post the farewell in the guild's reminder channel, falling back to its tree channel. Returns the channel used, if any.
|
||||||
|
async function sendFarewell(guild) {
|
||||||
|
const guildInfo = client.guildInfos.get(guild.id);
|
||||||
|
if (!guildInfo) return;
|
||||||
|
const channelIds = [...new Set([guildInfo.reminderChannelId, guildInfo.treeChannelId].filter(id => id))];
|
||||||
|
for (const channelId of channelIds) {
|
||||||
|
try {
|
||||||
|
const channel = await client.channels.fetch(channelId);
|
||||||
|
if (channel.guildId !== guild.id) continue;
|
||||||
|
await channel.send({ content: farewellMessage, allowedMentions: { parse: [] } });
|
||||||
|
return channel;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to send farewell to channel ${channelId} in ${guild.name} (${guild.id}): ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function leaveAllGuilds() {
|
||||||
|
// Skip the normal guildDelete handler, it depends on state that isn't built in shutdown mode
|
||||||
|
client.removeAllListeners('guildDelete');
|
||||||
|
statusChannel = await client.channels.fetch(statusChannelId).catch(e => console.error('Unable to fetch status channel', e));
|
||||||
|
const logStatus = async msg => {
|
||||||
|
console.log(msg);
|
||||||
|
if (statusChannel) await statusChannel.send(msg).catch(e => console.error(e));
|
||||||
|
};
|
||||||
|
// Load each guild's configured channels from the database so we know where to say goodbye
|
||||||
|
// If the database can't be read, abort without leaving anything so the shutdown can be retried
|
||||||
|
try {
|
||||||
|
await fn.collectionBuilders.guildInfos(client);
|
||||||
|
} catch (e) {
|
||||||
|
await logStatus(`Shutdown aborted, unable to load guild infos from the database: ${e}`);
|
||||||
|
client.destroy();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
// Don't leave the server the status channel lives in until the end, so messages can still be sent
|
||||||
|
const guilds = [...client.guilds.cache.values()]
|
||||||
|
.sort((a, b) => (a.id === statusChannel?.guildId) - (b.id === statusChannel?.guildId));
|
||||||
|
await logStatus(`Shutting down: leaving ${guilds.length} guild(s)...`);
|
||||||
|
let farewellCount = 0;
|
||||||
|
for (const guild of guilds) {
|
||||||
|
// Once the bot leaves the dev server it can't post there anymore, so say goodbye first
|
||||||
|
if (guild.id === statusChannel?.guildId) await logStatus(`Leaving my final guild: ${guild.name} (${guild.id}). Goodbye, and thanks for all the trees. 🌳`);
|
||||||
|
const farewellChannel = await sendFarewell(guild);
|
||||||
|
if (farewellChannel) farewellCount++;
|
||||||
|
const farewellNote = farewellChannel ? `farewell sent in #${farewellChannel.name}` : 'no farewell sent';
|
||||||
|
await guild.leave()
|
||||||
|
.then(() => {
|
||||||
|
const msg = `I've left a guild: ${guild.name} (${guild.id}) -- ${farewellNote}`;
|
||||||
|
return guild.id === statusChannel?.guildId ? console.log(msg) : logStatus(msg);
|
||||||
|
})
|
||||||
|
.catch(e => logStatus(`Failed to leave guild: ${guild.name} (${guild.id}) -- ${e}`));
|
||||||
|
}
|
||||||
|
console.log(`Finished leaving guilds, sent ${farewellCount} farewell(s). Goodbye!`);
|
||||||
|
client.destroy();
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
client.once('ready', async () => {
|
client.once('ready', async () => {
|
||||||
|
if (shuttingDown) return leaveAllGuilds();
|
||||||
fn.collectionBuilders.slashCommands(client);
|
fn.collectionBuilders.slashCommands(client);
|
||||||
fn.collectionBuilders.dotCommands(client);
|
fn.collectionBuilders.dotCommands(client);
|
||||||
fn.collectionBuilders.setvalidCommands(client);
|
fn.collectionBuilders.setvalidCommands(client);
|
||||||
|
|||||||
@ -79,13 +79,17 @@ module.exports = {
|
|||||||
database: process.env.DBNAME,
|
database: process.env.DBNAME,
|
||||||
port: process.env.DBPORT
|
port: process.env.DBPORT
|
||||||
});
|
});
|
||||||
db.connect((err) => {
|
|
||||||
if (err) throw `Error connecting to the database: ${err.message}`;
|
|
||||||
});
|
|
||||||
// Get a server's tree information from the database
|
// Get a server's tree information from the database
|
||||||
const query = 'SELECT * FROM guild_info';
|
const query = 'SELECT * FROM guild_info';
|
||||||
// TODO run this query and return a promise then structure the output into a GuildInfo object. resolve with { "status": , "data": guildInfo }
|
// TODO run this query and return a promise then structure the output into a GuildInfo object. resolve with { "status": , "data": guildInfo }
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
// Reject instead of throwing so callers can handle a failed connection
|
||||||
|
db.connect((err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(`Error connecting to the database: ${err.message}`);
|
||||||
|
db.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
db.query(query, (err, res) => {
|
db.query(query, (err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user