mirror of
https://github.com/thedrewen/protojx-manager.git
synced 2026-03-21 09:48:56 +01:00
Compare commits
9 Commits
v1.0.0-bet
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9565a9552 | ||
| 0504e8262d | |||
| 978d21a120 | |||
| 9cadfb2734 | |||
| 5b3167bf14 | |||
| 7f9468bc99 | |||
| 86a7429711 | |||
| 43b7bdd8b4 | |||
| 58ecaf3c4c |
17
.env.example
17
.env.example
@@ -1,5 +1,18 @@
|
||||
TOKEN=
|
||||
CLIENT_ID=
|
||||
# Discord Bot Configuration
|
||||
TOKEN=your_discord_bot_token_here
|
||||
CLIENT_ID=your_discord_client_id_here
|
||||
|
||||
# Custom Emojis
|
||||
EMOJI_STATUS_ONLINE=<a:online:1432684754276323431>
|
||||
EMOJI_STATUS_OFFLINE=<a:offline:1432684900175183882>
|
||||
|
||||
# Database Configuration
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_USERNAME=postgres
|
||||
DB_PASSWORD=your_database_password_here
|
||||
DB_DATABASE=protojx_manager
|
||||
DB_LOGGING=false
|
||||
|
||||
# Environment
|
||||
NODE_ENV=development
|
||||
@@ -9,8 +9,9 @@ A status bot and other features for protojx.
|
||||
| Description | Status |
|
||||
|-------------|--------|
|
||||
| /status command | 🌐 |
|
||||
| Number of services down in the bot's status. | ✅ |
|
||||
| Number of services down in the bot's status. | 🌐 |
|
||||
| Notification system in case of downtime. | ➖ |
|
||||
| Ability to create persistent status messages that update automatically. | ➖ |
|
||||
| Deployment workflow on Raspberry Pi. | ➖ |
|
||||
|
||||
- 🌐 -> In production
|
||||
|
||||
1511
package-lock.json
generated
1511
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/Under-scape/discordbot-ts-template#readme",
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.9.2",
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -31,6 +32,9 @@
|
||||
"cron": "^4.3.3",
|
||||
"discord.js": "^14.24.1",
|
||||
"dotenv": "^17.2.2",
|
||||
"ping": "^1.0.0"
|
||||
"pg": "^8.16.3",
|
||||
"ping": "^1.0.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"typeorm": "^0.3.27"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ApplicationIntegrationType, ChatInputCommandInteraction, CommandInteraction, InteractionContextType, SlashCommandBuilder } from "discord.js";
|
||||
import { ApplicationIntegrationType, ButtonInteraction, ButtonStyle, ChatInputCommandInteraction, CommandInteraction, ComponentType, ContainerBuilder, InteractionContextType, MessageFlags, SlashCommandBuilder } from "discord.js";
|
||||
import { CommandDefinition } from "../../type";
|
||||
|
||||
export default {
|
||||
const cmd : CommandDefinition = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('ping')
|
||||
.setDescription('Pong again!')
|
||||
@@ -14,6 +15,35 @@ export default {
|
||||
InteractionContextType.PrivateChannel
|
||||
),
|
||||
async execute(interaction : ChatInputCommandInteraction) {
|
||||
await interaction.reply(`🏓 Latency is ${Date.now() - interaction.createdTimestamp}ms. API Latency : ${interaction.client.ws.ping}ms`);
|
||||
}
|
||||
|
||||
const container = new ContainerBuilder()
|
||||
.addTextDisplayComponents((textDisplay) => textDisplay.setContent(`🏓 Latency is ${Date.now() - interaction.createdTimestamp}ms. API Latency : ${interaction.client.ws.ping}ms`))
|
||||
.addSeparatorComponents((s) => s)
|
||||
.addSectionComponents((section) =>
|
||||
section
|
||||
.addTextDisplayComponents((textDisplay) =>
|
||||
textDisplay
|
||||
.setContent('Oh, that\'s a beautiful button!')
|
||||
)
|
||||
.setButtonAccessory((button) =>
|
||||
button
|
||||
.setCustomId('testClick')
|
||||
.setLabel('Click Me !')
|
||||
.setStyle(ButtonStyle.Success)
|
||||
)
|
||||
)
|
||||
|
||||
// await interaction.reply();
|
||||
await interaction.reply({
|
||||
components: [container],
|
||||
flags: MessageFlags.IsComponentsV2
|
||||
})
|
||||
},
|
||||
buttons: [
|
||||
{id: 'testClick', handle: (interaction : ButtonInteraction) => {
|
||||
interaction.reply({content: 'Ho !', flags: [MessageFlags.Ephemeral]})
|
||||
}}
|
||||
]
|
||||
}
|
||||
|
||||
export default cmd;
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ApplicationIntegrationType, ChatInputCommandInteraction, CommandInteraction, EmbedBuilder, InteractionContextType, SlashCommandBuilder } from "discord.js";
|
||||
import ping from "ping";
|
||||
import statusService from "../../services/status.service";
|
||||
import { CommandDefinition } from "../../type";
|
||||
|
||||
export default {
|
||||
const cmd : CommandDefinition = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('status')
|
||||
.setDescription('Give statut of servers.')
|
||||
@@ -31,3 +32,5 @@ export default {
|
||||
await interaction.editReply({embeds: [embed]});
|
||||
}
|
||||
}
|
||||
|
||||
export default cmd;
|
||||
19
src/data-source.ts
Normal file
19
src/data-source.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import "reflect-metadata"
|
||||
import { DataSource } from "typeorm"
|
||||
import { configDotenv } from "dotenv"
|
||||
|
||||
configDotenv()
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: "postgres",
|
||||
host: process.env.DB_HOST || "localhost",
|
||||
port: parseInt(process.env.DB_PORT || "5432"),
|
||||
username: process.env.DB_USERNAME || "postgres",
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
synchronize: process.env.NODE_ENV !== "production", // false en production
|
||||
logging: process.env.DB_LOGGING === "true",
|
||||
entities: ["./entity/**/*.js"],
|
||||
migrations: ["./migration/**/*.js"],
|
||||
subscribers: ["./subscriber/**/*.js"],
|
||||
})
|
||||
13
src/entity/Guilds.ts
Normal file
13
src/entity/Guilds.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||
|
||||
@Entity()
|
||||
export class Guild {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
guild_id: string;
|
||||
|
||||
@Column()
|
||||
persistent_message_id: string;
|
||||
}
|
||||
38
src/index.ts
38
src/index.ts
@@ -1,11 +1,21 @@
|
||||
import { Client, Collection, Events, GatewayIntentBits, MessageFlags } from "discord.js";
|
||||
import { ButtonInteraction, ChatInputCommandInteraction, Client, Collection, Events, GatewayIntentBits, MessageFlags, SlashCommandBuilder } from "discord.js";
|
||||
import { configDotenv } from "dotenv";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import statusService from "./services/status.service";
|
||||
|
||||
import "reflect-metadata";
|
||||
import { AppDataSource } from "./data-source";
|
||||
import { CommandDefinition } from "./type";
|
||||
|
||||
configDotenv();
|
||||
|
||||
AppDataSource.initialize()
|
||||
.then(() => {
|
||||
console.log("Data Source initialized !")
|
||||
})
|
||||
.catch((error) => console.log(error));
|
||||
|
||||
const client = new Client({
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
@@ -15,8 +25,7 @@ const client = new Client({
|
||||
]
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
client.commands = new Collection();
|
||||
const commands = new Collection<string, CommandDefinition>();
|
||||
|
||||
const foldersPath = path.join(__dirname, 'commands');
|
||||
const commandFolders = fs.readdirSync(foldersPath);
|
||||
@@ -29,8 +38,7 @@ for (const folder of commandFolders) {
|
||||
const command = require(filePath);
|
||||
const commandModule = command.default || command;
|
||||
if ('data' in commandModule && 'execute' in commandModule) {
|
||||
// @ts-expect-error
|
||||
client.commands.set(commandModule.data.name, commandModule);
|
||||
commands.set(commandModule.data.name, commandModule);
|
||||
} else {
|
||||
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
|
||||
}
|
||||
@@ -38,10 +46,26 @@ for (const folder of commandFolders) {
|
||||
}
|
||||
|
||||
client.on(Events.InteractionCreate, async interaction => {
|
||||
|
||||
if(interaction.isButton()) {
|
||||
|
||||
const id = interaction.customId;
|
||||
|
||||
commands.forEach((value, key) => {
|
||||
if(value.buttons) {
|
||||
const button = value.buttons.filter((b) => b.id == id);
|
||||
if(button.length == 1) {
|
||||
button[0]?.handle(interaction);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
// @ts-expect-error
|
||||
const command = interaction.client.commands.get(interaction.commandName);
|
||||
const command = commands.get(interaction.commandName);
|
||||
|
||||
if (!command) {
|
||||
console.error(`No command matching ${interaction.commandName} was found.`);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ping from "ping";
|
||||
import * as cron from 'cron';
|
||||
import { ActivityType, Client } from "discord.js";
|
||||
import { Host } from "../type";
|
||||
|
||||
export class StatusService {
|
||||
|
||||
|
||||
3
src/type.d.ts
vendored
3
src/type.d.ts
vendored
@@ -1 +1,2 @@
|
||||
type Host = { host: string, name: string, alive: boolean, type: 'ping' | 'website' };
|
||||
export type Host = { host: string, name: string, alive: boolean, type: 'ping' | 'website' };
|
||||
export type CommandDefinition = { data: SlashCommandBuilder, execute: (interaction: ChatInputCommandInteraction) => void, buttons?: { id: string, handle: (interaction: ButtonInteraction) => void}[]};
|
||||
@@ -24,7 +24,8 @@
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true
|
||||
"preserveConstEnums": true,
|
||||
"strictPropertyInitialization": false
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
Reference in New Issue
Block a user