Initial commit 0.1.0

This commit is contained in:
Yusur 2025-08-19 15:26:40 +02:00
commit 1a4339eb9b
10 changed files with 1104 additions and 0 deletions

62
src/bot.ts Normal file
View file

@ -0,0 +1,62 @@
import { ChatInputCommandInteraction, Events, GatewayIntentBits, GuildMember, Interaction } from 'discord.js';
import { MyClient } from './client';
import commands from './commands';
import chalk from 'chalk';
export const client = new MyClient({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers]
});
for (let command of commands) {
client.addCommand(command);
}
client.on(Events.InteractionCreate, async (interaction: Interaction) => {
if (interaction instanceof ChatInputCommandInteraction) {
const { commandName } = interaction;
let command = client.commands.get(commandName);
if (command === void 0) {
console.error(`${chalk.red(`Command not found: ${chalk.bold(`/${commandName}`)}`)}`);
await interaction.reply({
content: `Comando non esistente: **/${commandName}**`,
ephemeral: true
});
return;
}
try {
await command.execute(interaction);
} catch (ex) {
console.error(`${chalk.red('Error in command')} ${chalk.bold(`/${commandName}`)}`);
console.error(ex);
}
}
});
// join gate
client.on(Events.GuildMemberAdd, async (member: GuildMember) => {
const { createdAt } = member.user;
const { joinedAt } = member;
if (joinedAt === null) return;
const hours = (joinedAt.getUTCHours() * 60 + joinedAt.getUTCMinutes() + 120) % 1440;
if (hours < 540) {
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} kicked: Join at night not allowed`);
await member.kick();
return;
}
if (joinedAt.getTime() - createdAt.getTime() < 10800000) {
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} kicked: Account too young`);
await member.kick();
return;
}
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} accepted`);
return;
});
client.once(Events.ClientReady, (c) => {
console.log(`Logged in as ${c.user.tag}`);
});

17
src/client.ts Normal file
View file

@ -0,0 +1,17 @@
import { Client, ClientOptions, Collection } from "discord.js";
import { CommandInfo } from "./commands";
export class MyClient extends Client {
commands: Collection<string, CommandInfo>;
constructor (opts: ClientOptions) {
super(opts);
this.commands = new Collection();
}
addCommand (command: CommandInfo) {
this.commands.set(command.data.name, command);
}
}

28
src/commands/index.ts Normal file
View file

@ -0,0 +1,28 @@
import { ChatInputCommandInteraction, MessageFlags, SlashCommandBuilder, SlashCommandOptionsOnlyBuilder } from "discord.js";
import version from "./version";
import { version as packageVersion } from '../../package.json';
export type CommandInfo = {data: SlashCommandOptionsOnlyBuilder, execute: (interaction: ChatInputCommandInteraction) => Promise<void>};
function fakeCommand(name: string, description?: string) {
const data = new SlashCommandBuilder()
.setName(name)
.setDescription(description? `[WIP] ${description}` : `[Comando non implementato]`);
async function execute(interaction: ChatInputCommandInteraction) {
await interaction.reply({
content: `Comando non implementato! (Versione: ${packageVersion})`,
flags: MessageFlags.Ephemeral
});
}
return { data, execute };
}
const commands = [
version
];
export default commands;

25
src/commands/version.ts Normal file
View file

@ -0,0 +1,25 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import { version as packageVersion } from '../../package.json';
import { version as discordjsVersion } from '../../node_modules/discord.js/package.json';
const nodejsVersion = process.versions.node;
const data = new SlashCommandBuilder()
.setName('version')
.setDescription('Informaz. sul bot');
async function execute (interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
await interaction.followUp({
content: `
* **Versione bot**: ${packageVersion}
* **Versione discord.js**: ${discordjsVersion}
* **Versione node.js**: ${nodejsVersion}
`.trim()
});
}
export default { data, execute };

7
src/init.ts Normal file
View file

@ -0,0 +1,7 @@
import { config } from 'dotenv';
export default function init () {
config();
}

8
src/main.ts Normal file
View file

@ -0,0 +1,8 @@
import { client } from './bot';
import init from './init';
init();
client.login(process.env.TOKEN);

48
src/register.ts Normal file
View file

@ -0,0 +1,48 @@
import init from "./init";
import commands from "./commands";
import { REST, Routes } from "discord.js";
init();
function registerGlobal(rest: REST, clientId: string, commands: any) {
rest.put(Routes.applicationCommands(clientId), { body: commands })
.then(() => { console.log(`Successfully registered ${commands.length} / commands globally. Please wait until 2 hours before they are updated`); })
.catch(console.error);
}
function registerLocal(rest: REST, clientId: string, commands: any, guilds: string[]){
for (const guildId of guilds) {
rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands })
.then(() => { console.log(`Successfully registered ${commands.length} / commands in guild ${guildId}`); })
.catch(console.error);
}
}
if (process.env.GUILD_IDS === void 0) {
console.warn('GUILD_IDS not set, registering commands globally');
}
if (process.env.TOKEN === void 0) {
throw new Error('TOKEN not set');
}
if (process.env.CLIENT_ID === void 0) {
throw new Error('CLIENT_ID not set');
}
const commandsJson: object[] = [];
for (let com of commands) {
commandsJson.push(com.data.toJSON());
}
const clientId = process.env.CLIENT_ID;
const guilds = (process.env.GUILD_IDS ?? '').trim().split(/[\s,;:]+/).filter(x => x.length > 0);
const rest = new REST({ version: '10' }).setToken(process.env.TOKEN);
if (guilds.length === 0){
registerGlobal(rest, clientId, commandsJson);
} else {
registerLocal(rest, clientId, commandsJson, guilds);
}