Goodbye<3
Some checks failed
Silvanus Production Dockerization / build (push) Failing after 2m13s

This commit is contained in:
Skylar Grant 2026-10-09 22:43:36 -04:00
parent f9bb94a4a1
commit 486ed80d31
3 changed files with 82 additions and 8 deletions

View File

@ -1,9 +1,9 @@
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 }}
@ -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
View File

@ -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);

View File

@ -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);