Add status role menu+heartbeat+impr CI+logging
All checks were successful
voidbot Production Dockerization / build (push) Successful in 53s
All checks were successful
voidbot Production Dockerization / build (push) Successful in 53s
This commit is contained in:
parent
5600af9e58
commit
6fb2a3f4e0
31
.github/workflows/docker-image.yml
vendored
31
.github/workflows/docker-image.yml
vendored
@ -1,7 +1,12 @@
|
|||||||
name: Voidbot Dockerization
|
name: voidbot Production Dockerization
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
merge:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DHUB_UNAME: ${{ secrets.DHUB_UNAME }}
|
DHUB_UNAME: ${{ secrets.DHUB_UNAME }}
|
||||||
@ -11,19 +16,21 @@ jobs:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: self-hosted
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- name: Pull latest from Git
|
||||||
|
run: |
|
||||||
|
cd /root/voidbot
|
||||||
|
git pull
|
||||||
|
git checkout $GITHUB_HEAD_REF
|
||||||
- name: Build the Docker image
|
- name: Build the Docker image
|
||||||
run: docker build . --file Dockerfile --tag v0idf1sh/voidbot
|
run: |
|
||||||
|
cd /root/voidbot
|
||||||
|
docker build . --file Dockerfile --tag v0idf1sh/voidbot
|
||||||
- name: Log into Docker Hub
|
- name: Log into Docker Hub
|
||||||
run: docker login -u $DHUB_UNAME -p $DHUB_PWORD
|
run: docker login -u $DHUB_UNAME -p $DHUB_PWORD
|
||||||
- name: Push image to Docker Hub
|
- name: Push image to Docker Hub
|
||||||
run: docker push v0idf1sh/voidbot
|
run: |
|
||||||
- name: Set up a skeleton .env file
|
cd /root/voidbot
|
||||||
run: echo "TOKEN=${{secrets.TOKEN}}" > .env && echo "BOTID=${{ secrets.BOTID }}" >> .env
|
docker push v0idf1sh/voidbot
|
||||||
- name: Install modules
|
|
||||||
run: npm i
|
|
||||||
- name: Refresh commands with Discord
|
|
||||||
run: node modules/_deploy-global.js
|
|
@ -1,8 +1,8 @@
|
|||||||
FROM node:16
|
FROM node:18
|
||||||
RUN mkdir -p /usr/src/app
|
RUN mkdir -p /usr/src/app
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
COPY . .
|
COPY . .
|
||||||
CMD [ "node", "main.js" ]
|
CMD ["/bin/sh", "-c", "node main.js 2> /logs/$(date +%Y-%m-%d_%H-%M-%S)-error.txt 1> /logs/$(date +%Y-%m-%d_%H-%M-%S)-status.txt"]
|
@ -11,7 +11,7 @@
|
|||||||
"rules": "1. Show respect\n2. No politics\n3. No spam or self-promotion (server invites, advertisements, etc) without permission from a staff member. This includes DMing fellow members.\n4. No age-restricted or obscene content. This includes text, images, or links featuring nudity, sex, hard violence, or other graphically disturbing content.\n5. If you see something against the rules or something that makes you feel unsafe, let staff know. We want this server to be a welcoming space!",
|
"rules": "1. Show respect\n2. No politics\n3. No spam or self-promotion (server invites, advertisements, etc) without permission from a staff member. This includes DMing fellow members.\n4. No age-restricted or obscene content. This includes text, images, or links featuring nudity, sex, hard violence, or other graphically disturbing content.\n5. If you see something against the rules or something that makes you feel unsafe, let staff know. We want this server to be a welcoming space!",
|
||||||
"rulesFooter": "Use the Accept Rules button to gain access to the rest of the server.",
|
"rulesFooter": "Use the Accept Rules button to gain access to the rest of the server.",
|
||||||
"roleMenuTitle": "Role Menu",
|
"roleMenuTitle": "Role Menu",
|
||||||
"treeRoleMenu": "Use the buttons below to give yourself roles.\n\n``💧`` - <@&1069416740389404763>: Get notifications when the tree is ready to be watered.\n``🍎`` - <@&1073698485376921602>: Get notifications when fruit is falling from the tree.",
|
"roleMenuDesc": "Use the buttons below to give yourself roles.\n\n``💧`` - <@&1069416740389404763>: Get notifications when the tree is ready to be watered.\n``🍎`` - <@&1073698485376921602>: Get notifications when fruit is falling from the tree.\n``📟`` - <@&1140098947306750073>: Get notifications when Silvanus or Silvanus FE are down and for scheduled maintenance.",
|
||||||
"roleMenuFooter": "Tip: Tap the button again to remove the role."
|
"roleMenuFooter": "Tip: Tap the button again to remove the role."
|
||||||
},
|
},
|
||||||
"emoji": {
|
"emoji": {
|
||||||
@ -20,11 +20,13 @@
|
|||||||
"confirm": "☑️",
|
"confirm": "☑️",
|
||||||
"cancel": "❌",
|
"cancel": "❌",
|
||||||
"water": "💧",
|
"water": "💧",
|
||||||
"fruit": "🍎"
|
"fruit": "🍎",
|
||||||
|
"status": "📟"
|
||||||
},
|
},
|
||||||
"roleIds": {
|
"roleIds": {
|
||||||
"member": "1048328885118435368",
|
"member": "1048328885118435368",
|
||||||
"waterPings": "1069416740389404763",
|
"waterPings": "1069416740389404763",
|
||||||
"fruitPings": "1073698485376921602"
|
"fruitPings": "1073698485376921602",
|
||||||
|
"statusPings": "1140098947306750073"
|
||||||
}
|
}
|
||||||
}
|
}
|
15
main.js
15
main.js
@ -4,6 +4,8 @@
|
|||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
const token = process.env.TOKEN;
|
const token = process.env.TOKEN;
|
||||||
|
const heartbeatUrl = process.env.HEARTBEAT_URL;
|
||||||
|
const sendHeartbeat = typeof heartbeatUrl === 'string';
|
||||||
|
|
||||||
// Discord.JS
|
// Discord.JS
|
||||||
const { Client, GatewayIntentBits } = require('discord.js');
|
const { Client, GatewayIntentBits } = require('discord.js');
|
||||||
@ -28,6 +30,14 @@ client.once('ready', () => {
|
|||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error("Error sending status message: " + err);
|
console.error("Error sending status message: " + err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Heartbeat Timer
|
||||||
|
if (sendHeartbeat) {
|
||||||
|
setInterval(() => {
|
||||||
|
fn.sendHeartbeat(heartbeatUrl);
|
||||||
|
}, 30000);
|
||||||
|
if (isDev) console.log("Heartbeat interval set.");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// slash-commands
|
// slash-commands
|
||||||
@ -58,6 +68,11 @@ client.on('interactionCreate', async interaction => {
|
|||||||
console.error("Error handling fruit ping button: " + err);
|
console.error("Error handling fruit ping button: " + err);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case 'statuspingrole':
|
||||||
|
await fn.buttonHandlers.statusPing(interaction).catch(err => {
|
||||||
|
console.error("Error handling status ping button: " + err);
|
||||||
|
});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ const isDev = process.env.isDev;
|
|||||||
|
|
||||||
// filesystem
|
// filesystem
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
|
|
||||||
// Discord.js
|
// Discord.js
|
||||||
const Discord = require('discord.js');
|
const Discord = require('discord.js');
|
||||||
@ -41,11 +42,12 @@ const functions = {
|
|||||||
this.buttons.acceptRules()
|
this.buttons.acceptRules()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
treeRoleMenu() {
|
roleMenu() {
|
||||||
return new ActionRowBuilder()
|
return new ActionRowBuilder()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
this.buttons.waterPing(),
|
this.buttons.waterPing(),
|
||||||
this.buttons.fruitPing()
|
this.buttons.fruitPing(),
|
||||||
|
this.buttons.statusPing()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
@ -66,6 +68,12 @@ const functions = {
|
|||||||
.setCustomId('fruitpingrole')
|
.setCustomId('fruitpingrole')
|
||||||
.setLabel(strings.emoji.fruit)
|
.setLabel(strings.emoji.fruit)
|
||||||
.setStyle(ButtonStyle.Primary);
|
.setStyle(ButtonStyle.Primary);
|
||||||
|
},
|
||||||
|
statusPing() {
|
||||||
|
return new ButtonBuilder()
|
||||||
|
.setCustomId('statuspingrole')
|
||||||
|
.setLabel(strings.emoji.status)
|
||||||
|
.setStyle(ButtonStyle.Primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -107,12 +115,12 @@ const functions = {
|
|||||||
.setFooter({ text: strings.embeds.rulesFooter });
|
.setFooter({ text: strings.embeds.rulesFooter });
|
||||||
return { embeds: [embed], components: [actionRow] };
|
return { embeds: [embed], components: [actionRow] };
|
||||||
},
|
},
|
||||||
treeRoleMenu() {
|
roleMenu() {
|
||||||
const actionRow = functions.builders.actionRows.treeRoleMenu();
|
const actionRow = functions.builders.actionRows.roleMenu();
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(strings.embeds.color)
|
.setColor(strings.embeds.color)
|
||||||
.setTitle(strings.embeds.roleMenuTitle)
|
.setTitle(strings.embeds.roleMenuTitle)
|
||||||
.setDescription(strings.embeds.treeRoleMenu)
|
.setDescription(strings.embeds.roleMenuDesc)
|
||||||
.setFooter({ text: strings.embeds.roleMenuFooter });
|
.setFooter({ text: strings.embeds.roleMenuFooter });
|
||||||
return { embeds: [embed], components: [actionRow] };
|
return { embeds: [embed], components: [actionRow] };
|
||||||
}
|
}
|
||||||
@ -148,11 +156,33 @@ const functions = {
|
|||||||
}
|
}
|
||||||
await interaction.reply(functions.builders.embeds.info("Roles updated!")).catch(err => console.error(err));
|
await interaction.reply(functions.builders.embeds.info("Roles updated!")).catch(err => console.error(err));
|
||||||
},
|
},
|
||||||
|
async statusPing(interaction) {
|
||||||
|
const role = await functions.roles.fetchRole(interaction.guild, strings.roleIds.statusPings);
|
||||||
|
if (interaction.member.roles.cache.some(role => role.id == strings.roleIds.statusPings)) {
|
||||||
|
functions.roles.takeRole(interaction.member, role);
|
||||||
|
} else {
|
||||||
|
functions.roles.giveRole(interaction.member, role);
|
||||||
|
}
|
||||||
|
await interaction.reply(functions.builders.embeds.info("Roles updated!")).catch(err => console.error(err));
|
||||||
|
},
|
||||||
async acceptRules(interaction) {
|
async acceptRules(interaction) {
|
||||||
const role = await functions.roles.fetchRole(interaction.guild, strings.roleIds.member);
|
const role = await functions.roles.fetchRole(interaction.guild, strings.roleIds.member);
|
||||||
functions.roles.giveRole(interaction.member, role).catch(err => console.error(err));
|
functions.roles.giveRole(interaction.member, role).catch(err => console.error(err));
|
||||||
await interaction.reply(functions.builders.embeds.info("Roles updated!")).catch(err => console.error(err));
|
await interaction.reply(functions.builders.embeds.info("Roles updated!")).catch(err => console.error(err));
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async sendHeartbeat(url) {
|
||||||
|
if (isDev) console.log("Heartbeat Sent: " + url);
|
||||||
|
https.get(url, async (response) => {
|
||||||
|
let data = '';
|
||||||
|
|
||||||
|
response.on('data', (chunk) => data += chunk);
|
||||||
|
|
||||||
|
response.on('end', () => {
|
||||||
|
parsedData = JSON.parse(data);
|
||||||
|
if ( !(parsedData.ok) ) console.error("Heartbeat failed");
|
||||||
|
});
|
||||||
|
}).on("error", (error) => console.error(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,6 @@ module.exports = {
|
|||||||
.setDescription('Send the role selection menu in the current channel'),
|
.setDescription('Send the role selection menu in the current channel'),
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
await interaction.deferReply().catch(err => console.error(err));
|
await interaction.deferReply().catch(err => console.error(err));
|
||||||
await interaction.editReply(fn.builders.embeds.treeRoleMenu()).catch(err => console.error(err));
|
await interaction.editReply(fn.builders.embeds.roleMenu()).catch(err => console.error(err));
|
||||||
},
|
},
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user