0.2.0
This commit is contained in:
parent
1a4339eb9b
commit
92dc208b65
7 changed files with 161 additions and 14 deletions
11
CHANGELOG.md
Normal file
11
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
## 0.2.0
|
||||||
|
|
||||||
|
- Moved all configuration to `config/config.toml`, contains:
|
||||||
|
+ join gate
|
||||||
|
+ guild aliases
|
||||||
|
- Now you can see what guilds is your bot in
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
|
||||||
|
- Initial commit
|
||||||
11
package-lock.json
generated
11
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "csinsol",
|
"name": "csinsol",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "csinsol",
|
"name": "csinsol",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^24.3.0",
|
"@types/node": "^24.3.0",
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
"discord.js": "^14.21.0",
|
"discord.js": "^14.21.0",
|
||||||
"dotenv": "^17.2.1",
|
"dotenv": "^17.2.1",
|
||||||
"luxon": "^3.7.1",
|
"luxon": "^3.7.1",
|
||||||
|
"toml": "^3.0.0",
|
||||||
"tsx": "^4.20.4"
|
"tsx": "^4.20.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -790,6 +791,12 @@
|
||||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toml": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ts-mixer": {
|
"node_modules/ts-mixer": {
|
||||||
"version": "6.0.4",
|
"version": "6.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "csinsol",
|
"name": "csinsol",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"author": "Sakuragasaki46",
|
"author": "Sakuragasaki46",
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
"discord.js": "^14.21.0",
|
"discord.js": "^14.21.0",
|
||||||
"dotenv": "^17.2.1",
|
"dotenv": "^17.2.1",
|
||||||
"luxon": "^3.7.1",
|
"luxon": "^3.7.1",
|
||||||
|
"toml": "^3.0.0",
|
||||||
"tsx": "^4.20.4"
|
"tsx": "^4.20.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
85
src/bot.ts
85
src/bot.ts
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, Events, GatewayIntentBits, GuildMember, Interaction } from 'discord.js';
|
import { ChatInputCommandInteraction, Events, GatewayIntentBits, Guild, GuildMember, Interaction } from 'discord.js';
|
||||||
import { MyClient } from './client';
|
import { MyClient } from './client';
|
||||||
import commands from './commands';
|
import commands from './commands';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
@ -13,6 +13,8 @@ for (let command of commands) {
|
||||||
client.addCommand(command);
|
client.addCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const guildDetail = !!process.env.GUILD_DETAIL_SHOW;
|
||||||
|
|
||||||
client.on(Events.InteractionCreate, async (interaction: Interaction) => {
|
client.on(Events.InteractionCreate, async (interaction: Interaction) => {
|
||||||
if (interaction instanceof ChatInputCommandInteraction) {
|
if (interaction instanceof ChatInputCommandInteraction) {
|
||||||
const { commandName } = interaction;
|
const { commandName } = interaction;
|
||||||
|
|
@ -40,16 +42,75 @@ client.on(Events.GuildMemberAdd, async (member: GuildMember) => {
|
||||||
const { joinedAt } = member;
|
const { joinedAt } = member;
|
||||||
if (joinedAt === null) return;
|
if (joinedAt === null) return;
|
||||||
|
|
||||||
|
const rules = client.config.getRules(member.guild.id) || [];
|
||||||
const hours = (joinedAt.getUTCHours() * 60 + joinedAt.getUTCMinutes() + 120) % 1440;
|
const hours = (joinedAt.getUTCHours() * 60 + joinedAt.getUTCMinutes() + 120) % 1440;
|
||||||
if (hours < 540) {
|
const age = Math.floor((joinedAt.getTime() - createdAt.getTime()) / 10800);
|
||||||
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} kicked: Join at night not allowed`);
|
const ops: Record<string, (x: number) => boolean> = {
|
||||||
await member.kick();
|
"age <": x => age < x,
|
||||||
return;
|
"age >=": x => age >= x,
|
||||||
}
|
"now <": x => hours < x,
|
||||||
if (joinedAt.getTime() - createdAt.getTime() < 10800000) {
|
"now >=": x => hours >= x
|
||||||
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} kicked: Account too young`);
|
};
|
||||||
await member.kick();
|
for (let rule of rules.filter(x => x.type === 'join')) {
|
||||||
return;
|
let { action, where, message = void 0, private_message = null } = rule;
|
||||||
|
let privMessage = private_message || message;
|
||||||
|
|
||||||
|
let result: boolean;
|
||||||
|
try {
|
||||||
|
let matches = where.match(/^([a-z]+) *([<=>]+) *([0-9]+) *$/);
|
||||||
|
if (!matches) continue;
|
||||||
|
let op = `${matches[1]} ${matches[2]}`;
|
||||||
|
let opf = ops[op];
|
||||||
|
if (!opf) continue;
|
||||||
|
let rval = parseInt(matches[3]);
|
||||||
|
result = opf(rval);
|
||||||
|
} catch(ex) {
|
||||||
|
console.warn(`malformed rule skipped: '${rule}'`)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
const actionMessage = ({
|
||||||
|
kick: 'kicked', ban:'banned',
|
||||||
|
'24h': 'muted for 24 hours', '3d': 'muted for 3 days','7d': 'muted for 7 days',
|
||||||
|
})[action];
|
||||||
|
|
||||||
|
// apply the rule
|
||||||
|
if (message) try {
|
||||||
|
// try messaging the user
|
||||||
|
|
||||||
|
await member.user.send({
|
||||||
|
content: `Sei statə espulsə da **${member.guild.name}**: ${message}`
|
||||||
|
});
|
||||||
|
} catch(ex) { }
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch(action) {
|
||||||
|
case 'kick':
|
||||||
|
await member.kick(message);
|
||||||
|
break;
|
||||||
|
case 'ban':
|
||||||
|
await member.ban({ reason: message, deleteMessageSeconds: 0 });
|
||||||
|
break;
|
||||||
|
case '24h':
|
||||||
|
await member.timeout(24 * 3600000, message);
|
||||||
|
break;
|
||||||
|
case '3d':
|
||||||
|
await member.timeout(3 * 24 * 3600000, message);
|
||||||
|
break;
|
||||||
|
case '7d':
|
||||||
|
await member.timeout(7 * 24 * 3600000, message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn(`unknown action: ${action}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} ${actionMessage}: ${privMessage}`);
|
||||||
|
} catch (ex) {
|
||||||
|
console.error(chalk.red(`Member: ${chalk.white(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} not ${actionMessage}: ${ex}\x1b[0m`));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} accepted`);
|
console.info(`Member: ${chalk.green(member.user.id)} ${chalk.grey(`(@${member.user.username})`)} accepted`);
|
||||||
|
|
@ -58,5 +119,9 @@ client.on(Events.GuildMemberAdd, async (member: GuildMember) => {
|
||||||
|
|
||||||
client.once(Events.ClientReady, (c) => {
|
client.once(Events.ClientReady, (c) => {
|
||||||
console.log(`Logged in as ${c.user.tag}`);
|
console.log(`Logged in as ${c.user.tag}`);
|
||||||
|
console.log(`Currently in ${chalk.bold(c.guilds.cache.size)} guilds` + (guildDetail? ':' : `; rerun with GUILD_DETAIL_SHOW=1 for details`));
|
||||||
|
if (guildDetail) {
|
||||||
|
console.log(c.guilds.cache.map((x: Guild) => `* ${chalk.bold(x.name)} ${chalk.grey('(ID: ')}${chalk.green(x.id)}${chalk.grey(`, ${x.memberCount} members)`)}`).join('\n'));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,27 @@
|
||||||
import { Client, ClientOptions, Collection } from "discord.js";
|
import { Client, ClientOptions, Collection } from "discord.js";
|
||||||
import { CommandInfo } from "./commands";
|
import { CommandInfo } from "./commands";
|
||||||
|
import { ConfigFile } from "./configFile";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class MyClient extends Client {
|
export class MyClient extends Client {
|
||||||
commands: Collection<string, CommandInfo>;
|
commands: Collection<string, CommandInfo>;
|
||||||
|
config: ConfigFile;
|
||||||
|
|
||||||
constructor (opts: ClientOptions) {
|
constructor (opts: ClientOptions) {
|
||||||
super(opts);
|
super(opts);
|
||||||
this.commands = new Collection();
|
this.commands = new Collection();
|
||||||
|
this.config = new ConfigFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
override async login(token?: string): Promise<string> {
|
||||||
|
await this.config.load();
|
||||||
|
return super.login(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommand (command: CommandInfo) {
|
addCommand (command: CommandInfo) {
|
||||||
this.commands.set(command.data.name, command);
|
this.commands.set(command.data.name, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ const nodejsVersion = process.versions.node;
|
||||||
|
|
||||||
const data = new SlashCommandBuilder()
|
const data = new SlashCommandBuilder()
|
||||||
.setName('version')
|
.setName('version')
|
||||||
.setDescription('Informaz. sul bot');
|
.setDescription('Informazioni sul bot');
|
||||||
|
|
||||||
async function execute (interaction: ChatInputCommandInteraction) {
|
async function execute (interaction: ChatInputCommandInteraction) {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
|
||||||
53
src/configFile.ts
Normal file
53
src/configFile.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import toml from "toml";
|
||||||
|
|
||||||
|
type ConfigGuildRule = {
|
||||||
|
type: "join",
|
||||||
|
action: "kick" | "ban" | "24h" | "3d" | "7d",
|
||||||
|
where: string,
|
||||||
|
message?: string,
|
||||||
|
private_message?: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export class ConfigFile{
|
||||||
|
guilds?: {
|
||||||
|
aliases?: Record<string, string>,
|
||||||
|
rules?: Record<string, ConfigGuildRule[]>
|
||||||
|
}
|
||||||
|
globals?: {
|
||||||
|
timezone?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async load () {
|
||||||
|
let content = await fs.readFile("config/config.toml", "utf-8");
|
||||||
|
|
||||||
|
let data = toml.parse(content);
|
||||||
|
|
||||||
|
this.globals = data.globals;
|
||||||
|
this.guilds = data.guilds;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRules (guildId: string) : ConfigGuildRule[] | null {
|
||||||
|
if(!this?.guilds?.rules) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let aliases = this?.guilds?.aliases || {};
|
||||||
|
for(let key in this.guilds.rules) {
|
||||||
|
if (key.startsWith('@')) {
|
||||||
|
key = aliases[key.slice(1)];
|
||||||
|
if (!key) continue;
|
||||||
|
}
|
||||||
|
if (key === guildId) {
|
||||||
|
return this.guilds.rules[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue