diff --git a/.env.sample b/.env.sample deleted file mode 100644 index 22dea61..0000000 --- a/.env.sample +++ /dev/null @@ -1,29 +0,0 @@ -TOKEN= -GUILD_ID= -ADMIN_ID= -CLIENT_ID= -SENIOR_ADMIN_ID= - -/* GAME SERVER */ -TZ= - - -/* PRISM */ -PRISM_IP= -PRISM_PORT= -PRISM_USRNAME= -PRISM_USRPW= - -/* FTP */ -FTP_HOST= -FTP_USER= -FTP_PASS= - -/* Channels */ -CH_BANS_PRIV= -CH_BANS_PUB= - -CH_CMDS_PRIV= -CH_CMDS_PUB= - -CH_JOIN_PRIV= diff --git a/README.md b/README.md new file mode 100644 index 0000000..15c27ab --- /dev/null +++ b/README.md @@ -0,0 +1,226 @@ +# Tommy Bot + +Creator: @MaxZK [R-DEV]Max_ + +Maintainer: @emilekm [R-CON]cassius23 + +## Requirements + +- Discord server +- FTP server +- HTTP server +- Node.js + +If you're using Windows you might need to follow the installation instructions for [node-gyp](https://github.com/nodejs/node-gyp?tab=readme-ov-file#on-windows). + +## Running + +```sh +# Install dependencies +npm install +# Run the bot +npm start +``` + +## Features + +Below is a list of features the bot provides along with configuration for each of the features. + +The full configuration can be found in `config.yaml.sample`. +Copy the file to `config.yaml` and fill in the required fields. + +### PRISM + +PRISM is used for running in-game commands, reading chat and alerts. + +The general channel is for all chat messages coming into PRISM. +There is a special feed for teamkills, which you can direct to a specific channel. + +```yaml +prism: + auth: + ip: + port: + username: + password: + generalChannelID: + teamkillChannelID: +``` + +### Demos + +Demos are uploaded using FTP at the round end. After upload the bot will post a message with the demo links. + +Additionally the bot will upload JSON files produced by the server at the round end. + +```yaml +demos: + channelID: + ftp: + host: + username: + password: + + # URL where tracker viewer can be accesseded + # Domain needs to be the same as the one used for prdemo (for CORS) + # Example: https://demos.myserver.gg/realitytracker/ + trackerViewerUrl: + + # source is the path where the files can be found + # destination is the path where the files will be uploaded via FTP + # url is the URL where the files can be accessed on the internet + + bf2: + # Example: /pr/server/mods/pr/demos/ + source: + # Example: demos/bf2/ + destination: + # Example: https://demos.myserver.gg/bf2/ + url: + + pr: + # Example: /pr/server/demos/ + source: + # Example: demos/pr/ + destination: + # Example: https://demos.myserver.gg/pr/ + url: + + json: + # Example: /pr/server/json/ + source: + # Example: demos/json/ + destination: +``` + +### Logs + +Join, commands and ban logs are read from files and posted to Discord channels. + +Additionally tickets log is used to determine winner of the round. + +- `bans` - `mods/pr/settings/banlist_info.log` +- `commands` - `admin/logs/commandlog.log` +- `joins` - `admin/logs/joinlog.log` +- `tickets` - `admin/logs/tickets.log` + +Paths need to be absolute. + +```yaml +logs: + bans: + # {SV_DIR}/mods/pr/settings/banlist_info.log + path: + publicChannelID: + privateChannelID: + commands: + # {SV_DIR}/admin/logs/ra_adminlog.txt + path: + publicChannelID: + privateChannelID: + joinlog: + # {SV_DIR}/admin/logs/joinlog.log + path: + privateChannelID: + tickets: + # {SV_DIR}/admin/logs/tickets.log + path: +``` + +### Server information + +Server information is fetched from PRSPY and posted as two channels names. + +First channel is the map name, second contains other details: gamemode, layer and player count. + +It is recommended to create a voice channel that no one can join, but everyone can see. + +```yaml +prspy: + # PRSPY server ID + # Open your server on PRSPY and grab the ID from the URL + # This ID changes on IP or port change (and probably some other things) + # Example: ceab9bd17f51d08acc4da77120574bd57e248c98 + id: + mapChannelID: + detailsChannelID: +``` + +## Interactive features + +Commands can render buttons for users to interact with the bot or can have a direct action. +Most commands side effect is some kind of log/message on Discord. +Most of them have two types: public and private - first providing less information that the latter. + +### ~~Admin Hash ID~~ + +*This command is currently disabled, this functionality is poorly implemented and needs to be reworked. **Contributions are welcome**.* + +### Contact admin + +**Command**: `/contactadmin` + +This command will render 3 buttons: + +- Admin Application +- Ban Appeal +- Report Incident + +These 3 buttons will open a form where the user can fill in the required information. + +The channel where the form is posted needs to be a Forum channel. +A sent form will be posted to the configured channel as a Post. +Specified tags will be assigned to the post. + +It is common to create one Forum channel and direct all forms to it with different tags. + +```yaml +contactadmin: + # The role that should be tagged when a form is posted + adminRoleID: + application: + public: + channelID: + tagIDs: [] + private: + channelID: + tagIDs: [] + appeal: + public: + channelID: + tagIDs: [] + private: + channelID: + tagIDs: [] + report: + public: + channelID: + tagIDs: [] + private: + channelID: + tagIDs: [] +``` + +### Ban and unban player + +**Commands**: +- `/prban [hashid] [prname] [durationvalue] [durationformat] [reason] ` +- `/prunban [hashid] [reason]` + +This command uses PRISM to ban/unban a player. + +It posts a message to two configured channels. + +Configuration: +```yaml +prban: + firsChannelID: + secondChannelID: +prunban: + firsChannelID: + secondChannelID: +``` + +### Run admin command on the server + +**Command**: `/prprism [command]` diff --git a/assets/hash-id.gif b/assets/hash-id.gif new file mode 100644 index 0000000..d840990 Binary files /dev/null and b/assets/hash-id.gif differ diff --git a/bot.js b/bot.js index 9d3e3b2..ee48fdd 100644 --- a/bot.js +++ b/bot.js @@ -1,11 +1,10 @@ -import dotenv from "dotenv"; -dotenv.config(); - import fs from "fs"; import { Client, GatewayIntentBits, Events, Collection } from "discord.js"; +import config from "./config.js"; import { getAdmins } from "./helpers/getAdmins.js"; + const client = new Client({ intents: [ GatewayIntentBits.Guilds, @@ -15,7 +14,7 @@ const client = new Client({ ], }); -client.login(process.env.TOKEN); +client.login(config.discord.token); client.once(Events.ClientReady, () => { client.commands = new Collection(); diff --git a/commands/information/adminhashid.js b/commands/information/adminhashid.js index c7b3bdf..7e9430d 100644 --- a/commands/information/adminhashid.js +++ b/commands/information/adminhashid.js @@ -14,7 +14,7 @@ export default { "Prompt buttons for admins to enter their hash corectly...." ), async execute(interaction) { - const file = new AttachmentBuilder("logs/images/flags/hash-id.gif"); + const file = new AttachmentBuilder("assets/hash-id.gif"); const embed = new EmbedBuilder() .setColor("#0074ba") .setTitle("🔷 Admin Hash-ID") diff --git a/commands/information/contactadmin.js b/commands/information/contactadmin.js index 6a06a73..116417a 100644 --- a/commands/information/contactadmin.js +++ b/commands/information/contactadmin.js @@ -12,14 +12,14 @@ export default { .setName("contactadmin") .setDescription("Prompt buttons for Ban Appeals, Admin Application and Reports"), async execute(interaction) { - const file = new AttachmentBuilder("logs/images/flags/hash-id.gif"); + const file = new AttachmentBuilder("assets/hash-id.gif"); const embed = new EmbedBuilder() .setColor("#e98f27") .setTitle("🔶 Contact Admins") .setDescription(` **Click** one of the **buttons** below to **either**:\n - > 🔵 **Apply** for an admin role on our Project Reality server.\n> - > 🟢 **Appeal** a ban from our Project Reality server.\n> + > 🔵 **Apply** for an admin role on our Project Reality server.\n> + > 🟢 **Appeal** a ban from our Project Reality server.\n> > 🔴 **Report** an incident that happened on our Discord or Project Reality servers\n\n If you are having issues finding your Hash-ID check the .GIF image bellow to learn how to find it.`) .setImage("attachment://hash-id.gif"); @@ -40,8 +40,8 @@ export default { ); await interaction.reply({ embeds: [embed], - components: [row], + components: [row], files: [file] }); }, -}; \ No newline at end of file +}; diff --git a/commands/moderation/prban.js b/commands/moderation/prban.js index 9990a41..6e63fbe 100644 --- a/commands/moderation/prban.js +++ b/commands/moderation/prban.js @@ -1,7 +1,7 @@ import { SlashCommandBuilder, AttachmentBuilder, EmbedBuilder } from "discord.js"; -import { ServerCommands } from "../../functions/handlePRISM.js"; - +import config from "../../config.js"; +import { ServerCommands } from "../../functions/handlePRISM.js"; function sleep(ms) { return new Promise((resolve) => { @@ -79,8 +79,8 @@ export default { .setTimestamp(new Date()) .setFooter({ text: "DISCORD" }); await interaction.reply({ embeds: [embedReply] }); - await interaction.member.guild.channels.cache.get("995387208947204257").send({ embeds: [embedReply] }); - await interaction.member.guild.channels.cache.get("995520998554218557").send({ embeds: [embedReply] }); + await interaction.member.guild.channels.cache.get(config.prban.firstChannelID).send({ embeds: [embedReply] }); + await interaction.member.guild.channels.cache.get(config.prban.secondChannelID).send({ embeds: [embedReply] }); } else { const file = new AttachmentBuilder(attachment.attachment); console.log(file.attachment.split("/")[-1]); @@ -92,8 +92,8 @@ export default { .setTimestamp(new Date()) .setFooter({ text: "DISCORD" }); await interaction.reply({ embeds: [embedReply], files: [file] }); - await interaction.member.guild.channels.cache.get("995387208947204257").send({ embeds: [embedReply], files: [file] }); - await interaction.member.guild.channels.cache.get("995520998554218557").send({ embeds: [embedReply], files: [file] }); + await interaction.member.guild.channels.cache.get(config.prban.firstChannelID).send({ embeds: [embedReply], files: [file] }); + await interaction.member.guild.channels.cache.get(config.prban.secondChannelID).send({ embeds: [embedReply], files: [file] }); } }, }; diff --git a/commands/moderation/prprism.js b/commands/moderation/prprism.js index fce58ee..d29722f 100644 --- a/commands/moderation/prprism.js +++ b/commands/moderation/prprism.js @@ -5,14 +5,14 @@ export default { data: new SlashCommandBuilder() .setName("prprism") .setDescription("Execute a command from PRISM") - .addStringOption(subcommand => subcommand - .setName("hashid") + .addStringOption(option => option + .setName("command") .setDescription("Command as if you typing it in PRISM or in-game") .setRequired(true)), async execute(interaction) { - writeSayToPrism(`${interaction.options.getString("hashid")} - Discord User ${interaction.user.username}`); + writeSayToPrism(`${interaction.options.getString("command")} - Discord User ${interaction.user.username}`); await interaction.reply({ - content: `addKeyToBanList ${interaction.options.getString("hashid")} ${interaction.options.getString("duration")} ${interaction.options.getString("reason")}`, + content: `Ran command \`${interaction.options.getString("command")}\` using PRISM.`, ephemeral: true }); }, diff --git a/commands/moderation/prunban.js b/commands/moderation/prunban.js index 9002cb3..6612cb9 100644 --- a/commands/moderation/prunban.js +++ b/commands/moderation/prunban.js @@ -1,4 +1,6 @@ import { SlashCommandBuilder, EmbedBuilder } from "discord.js"; + +import config from "../../config.js"; import { ServerCommands } from "../../functions/handlePRISM.js"; export default { @@ -27,7 +29,7 @@ export default { .setTimestamp(new Date()) .setFooter({ text: "DISCORD" }); await interaction.reply({ embeds: [embedReply] }); - await interaction.member.guild.channels.cache.get("995387208947204257").send({ embeds: [embedReply] }); - await interaction.member.guild.channels.cache.get("995520998554218557").send({ embeds: [embedReply] }); + await interaction.member.guild.channels.cache.get(config.prunban.firstChannelID).send({ embeds: [embedReply] }); + await interaction.member.guild.channels.cache.get(config.prunban.secondChannelID).send({ embeds: [embedReply] }); }, }; diff --git a/config.js b/config.js index 56a6692..dd79686 100644 --- a/config.js +++ b/config.js @@ -1,40 +1,3 @@ -import dotenv from "dotenv"; -dotenv.config(); +import config from "./config/index.js"; -// This is for testing purposes -const defaultTextCh = process.env.CH_TESTING; - -export const channels = { - bans: { - priv: defaultTextCh || process.env.CH_BANS_PRIV || "995520998554218557", - pub: defaultTextCh || process.env.CH_BANS_PUB || "995387208947204257", - }, - commands: { - priv: defaultTextCh || process.env.CH_CMDS_PRIV || "995520998554218557", - pub: defaultTextCh || process.env.CH_CMDS_PUB || "995387208947204257", - }, - join: { - priv: defaultTextCh || process.env.CH_JOIN_PRIV || "995521059119960144" - } -}; - -export const logs = { - bans: process.env.LOGS_BANS || "logs/banlist_info.log", - commands: process.env.LOGS_CMDS || "logs/ra_adminlog.txt", - joins: process.env.LOGS_JOIN || "logs/joinlog.log", - tickets: process.env.LOGS_TICKETS || "logs/tickets.log", -}; - -const serverDir = process.env.PRBF2_SV_DIR; - -export default { - timezone: process.env.TZ || "+02:00", - serverDir: serverDir, - prspySvID: process.env.PRSPY_SV_ID, - bf2DemosDir: process.env.BF2_DEMOS_DIR || `${serverDir}/mods/pr/demos/`, - prDemosDir: process.env.PR_DEMOS_DIR || `${serverDir}/demos/`, - chatlogsDir: process.env.CHATLOGS_DIR || `${serverDir}/admin/logs/`, - jsonDir: process.env.JSON_DIR || `${serverDir}/json/`, - channels, - logs, -}; +export default config; diff --git a/config.yaml.sample b/config.yaml.sample new file mode 100644 index 0000000..c1c81d3 --- /dev/null +++ b/config.yaml.sample @@ -0,0 +1,118 @@ +discord: + token: + clientID: + guildID: + + +server: + # Host timezone (used to accurately report time to Discord) + timezone: "+00:00" + + +prism: + auth: + ip: + port: + username: + password: + generalChannelID: + teamkillChannelID: + + +demos: + channelID: + ftp: + host: + username: + password: + + # URL where tracker viewer can be accesseded + # Domain needs to be the same as the one used for prdemo (for CORS) + # Example: https://demos.myserver.gg/realitytracker/ + trackerViewerUrl: + + # source is the path where the files can be found + # destination is the path where the files will be uploaded via FTP + # url is the URL where the files can be accessed on the internet + + bf2: + # Example: /pr/server/mods/pr/demos/ + source: + # Example: demos/bf2/ + destination: + # Example: https://demos.myserver.gg/bf2/ + url: + + pr: + # Example: /pr/server/demos/ + source: + # Example: demos/pr/ + destination: + # Example: https://demos.myserver.gg/pr/ + url: + + json: + # Example: /pr/server/json/ + source: + # Example: demos/json/ + destination: + + +logs: + bans: + # {SV_DIR}/mods/pr/settings/banlist_info.log + path: + publicChannelID: + privateChannelID: + commands: + # {SV_DIR}/admin/logs/ra_adminlog.txt + path: + publicChannelID: + privateChannelID: + joinlog: + # {SV_DIR}/admin/logs/joinlog.log + path: + privateChannelID: + tickets: + # {SV_DIR}/admin/logs/tickets.log + path: + + +prspy: + # PRSPY server ID + # Open your server on PRSPY and grab the ID from the URL + # This ID changes on IP or port change (and probably some other things) + # Example: ceab9bd17f51d08acc4da77120574bd57e248c98 + id: + mapChannelID: + detailsChannelID: + + +contactadmin: + # The role that should be tagged when a form is posted + adminRoleID: + application: + public: + channelID: + tagIDs: [] + # Example: + # tagIDs: + # - "123456789012345678" + # - "123456789012345678" + private: + channelID: + tagIDs: [] + appeal: + public: + channelID: + tagIDs: [] + private: + channelID: + tagIDs: [] + report: + public: + channelID: + tagIDs: [] + private: + channelID: + tagIDs: [] diff --git a/config/config.schema.json b/config/config.schema.json new file mode 100644 index 0000000..bd3ecb0 --- /dev/null +++ b/config/config.schema.json @@ -0,0 +1,380 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "definitions": { + "BanInfo": { + "additionalProperties": false, + "properties": { + "firstChannelID": { + "type": "string" + }, + "secondChannelID": { + "type": "string" + } + }, + "required": [ + "firstChannelID", + "secondChannelID" + ], + "type": "object" + }, + "ContactAdmin": { + "additionalProperties": false, + "properties": { + "adminRoleID": { + "type": "string" + }, + "appeal": { + "$ref": "#/definitions/FormConfig" + }, + "application": { + "$ref": "#/definitions/FormConfig" + }, + "report": { + "$ref": "#/definitions/FormConfig" + } + }, + "required": [ + "adminRoleID", + "appeal", + "application", + "report" + ], + "type": "object" + }, + "Demo": { + "additionalProperties": false, + "properties": { + "destination": { + "type": "string" + }, + "source": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "destination", + "source", + "url" + ], + "type": "object" + }, + "Demos": { + "additionalProperties": false, + "properties": { + "bf2": { + "$ref": "#/definitions/Demo" + }, + "channelID": { + "type": "string" + }, + "ftp": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "host", + "password", + "username" + ], + "type": "object" + }, + "json": { + "additionalProperties": false, + "properties": { + "destination": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "required": [ + "destination", + "source" + ], + "type": "object" + }, + "pr": { + "$ref": "#/definitions/Demo" + }, + "trackerViewerUrl": { + "type": "string" + } + }, + "required": [ + "bf2", + "channelID", + "ftp", + "json", + "pr", + "trackerViewerUrl" + ], + "type": "object" + }, + "Discord": { + "additionalProperties": false, + "properties": { + "clientID": { + "type": "string" + }, + "guildID": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "required": [ + "clientID", + "guildID", + "token" + ], + "type": "object" + }, + "FormConfig": { + "additionalProperties": false, + "properties": { + "private": { + "additionalProperties": false, + "properties": { + "channelID": { + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "channelID", + "tags" + ], + "type": "object" + }, + "public": { + "additionalProperties": false, + "properties": { + "channelID": { + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "channelID", + "tags" + ], + "type": "object" + } + }, + "required": [ + "private", + "public" + ], + "type": "object" + }, + "Log": { + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + }, + "privateChannelID": { + "type": "string" + }, + "publicChannelID": { + "type": "string" + } + }, + "required": [ + "path", + "privateChannelID", + "publicChannelID" + ], + "type": "object" + }, + "Logs": { + "additionalProperties": false, + "properties": { + "bans": { + "$ref": "#/definitions/Log" + }, + "commands": { + "$ref": "#/definitions/Log" + }, + "joins": { + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + }, + "privateChannelID": { + "type": "string" + } + }, + "required": [ + "path", + "privateChannelID" + ], + "type": "object" + }, + "tickets": { + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + } + }, + "required": [ + "path" + ], + "type": "object" + } + }, + "required": [ + "bans", + "commands", + "joins", + "tickets" + ], + "type": "object" + }, + "PRSPY": { + "additionalProperties": false, + "properties": { + "detailsChannelID": { + "type": "string" + }, + "id": { + "type": "string" + }, + "mapChannelID": { + "type": "string" + } + }, + "required": [ + "detailsChannelID", + "id", + "mapChannelID" + ], + "type": "object" + }, + "Prism": { + "additionalProperties": false, + "properties": { + "auth": { + "$ref": "#/definitions/PrismAuth" + }, + "generalChannelID": { + "type": "string" + }, + "teamkillChannelID": { + "type": "string" + } + }, + "required": [ + "auth", + "generalChannelID", + "teamkillChannelID" + ], + "type": "object" + }, + "PrismAuth": { + "additionalProperties": false, + "properties": { + "ip": { + "type": "string" + }, + "password": { + "type": "string" + }, + "port": { + "type": "number" + }, + "username": { + "type": "string" + } + }, + "required": [ + "ip", + "password", + "port", + "username" + ], + "type": "object" + }, + "Server": { + "additionalProperties": false, + "properties": { + "timezone": { + "type": "string" + } + }, + "required": [ + "timezone" + ], + "type": "object" + } + }, + "properties": { + "contactadmin": { + "$ref": "#/definitions/ContactAdmin" + }, + "demos": { + "$ref": "#/definitions/Demos" + }, + "discord": { + "$ref": "#/definitions/Discord" + }, + "logs": { + "$ref": "#/definitions/Logs" + }, + "prban": { + "$ref": "#/definitions/BanInfo" + }, + "prism": { + "$ref": "#/definitions/Prism" + }, + "prspy": { + "$ref": "#/definitions/PRSPY" + }, + "prunban": { + "$ref": "#/definitions/BanInfo" + }, + "server": { + "$ref": "#/definitions/Server" + } + }, + "required": [ + "contactadmin", + "demos", + "discord", + "logs", + "prban", + "prism", + "prspy", + "prunban", + "server" + ], + "type": "object" +} + diff --git a/config/index.js b/config/index.js new file mode 100644 index 0000000..6338075 --- /dev/null +++ b/config/index.js @@ -0,0 +1,17 @@ +// @ts-nocheck +import { fileURLToPath } from "url"; +import path from 'path'; +import { readFileSync } from 'fs'; +import { parse } from 'yaml'; +import { Ajv } from 'ajv'; +import * as schema from './config.schema.json' assert { type: "json" }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const pathToConfig = path.join(__dirname, "..", "config.yaml"); +const config = parse(readFileSync(pathToConfig, 'utf8')); +const ajv = new Ajv(); +ajv.addSchema(schema, 'config'); +if (!ajv.validate('config', config)) { + console.error("Invalid config file", ajv.errors); + process.exit(1); +} +export default config; diff --git a/config/index.ts b/config/index.ts new file mode 100644 index 0000000..3ff358e --- /dev/null +++ b/config/index.ts @@ -0,0 +1,125 @@ +// @ts-nocheck +import { fileURLToPath } from "url"; +import path from 'path'; +import { readFileSync } from 'fs'; +import { parse } from 'yaml' +import { Ajv } from 'ajv'; +import * as schema from './config.schema.json' assert { type: "json" }; + +interface Discord { + token: string; + clientID: string; + guildID: string; +} + +interface Server { + timezone: string; +} + +interface PrismAuth { + ip: string; + port: number; + username: string; + password: string; +} + +interface Prism { + auth: PrismAuth; + generalChannelID: string; + teamkillChannelID: string; +} + +interface Demo { + source: string; + destination: string; + url: string; +} + +interface Demos { + channelID: string; + ftp: { + host: string; + username: string; + password: string; + }; + trackerViewerUrl: string; + bf2: Demo; + pr: Demo; + json: { + source: string; + destination: string; + }; +} + +interface Log { + path: string; + publicChannelID: string; + privateChannelID: string; +} + +interface Logs { + bans: Log; + commands: Log; + joins: { + path: string; + privateChannelID: string; + }; + tickets: { + path: string; + } +} + +interface PRSPY { + id: string; + mapChannelID: string; + detailsChannelID: string; +} + +interface FormConfig { + public: { + channelID: string; + tags: string[]; + } + private: { + channelID: string; + tags: string[]; + } +} + +interface ContactAdmin { + adminRoleID: string; + application: FormConfig; + appeal: FormConfig; + report: FormConfig; +} + +interface BanInfo { + firstChannelID: string; + secondChannelID: string; +} + +interface Config { + discord: Discord; + server: Server; + prism: Prism; + demos: Demos; + logs: Logs; + prspy: PRSPY; + contactadmin: ContactAdmin; + prban: BanInfo; + prunban: BanInfo; +} + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const pathToConfig = path.join(__dirname, "..", "config.yaml"); +const config: Config = parse(readFileSync(pathToConfig, 'utf8')); + +const ajv = new Ajv(); +ajv.addSchema(schema, 'config'); + +if (!ajv.validate('config', config)) { + console.error("Invalid config file", ajv.errors); + process.exit(1); +} + +export default config; diff --git a/functions/handleCommands.js b/functions/handleCommands.js index fc6e504..8489e11 100644 --- a/functions/handleCommands.js +++ b/functions/handleCommands.js @@ -2,8 +2,10 @@ import { REST } from "@discordjs/rest"; import { Routes } from "discord-api-types/v9"; import fs from "fs"; -const clientId = process.env.CLIENT_ID; -const guildId = process.env.GUILD_ID; +import config from "../config.js"; + +const clientID = config.discord.clientID +const guildID = config.discord.guildID; export default (client) => { @@ -20,14 +22,14 @@ export default (client) => { } const rest = new REST({ version: "9" - }).setToken(process.env.TOKEN); + }).setToken(config.discord.token); (async () => { try { console.log("\x1b[42m", "==================================== \n BOT RESTARTED! \n ====================================", "\x1b[0m"); console.log("Started refreshing application (/) commands."); await rest.put( - Routes.applicationGuildCommands(clientId, guildId), + Routes.applicationGuildCommands(clientID, guildID), { body: client.commandArray }, diff --git a/functions/handleInfo.js b/functions/handleInfo.js index fbbcdde..ae7e8b3 100644 --- a/functions/handleInfo.js +++ b/functions/handleInfo.js @@ -1,12 +1,7 @@ -import dotenv from "dotenv"; -dotenv.config(); - import request from "request"; -import locals from "../localization.json" assert { type: "json"}; -import config from "../config.js"; - -//Discord +import config from "../config.js"; +import locals from "../localization.json" assert { type: "json"}; export default (client) => { client.handleInfo = async () => { @@ -17,7 +12,7 @@ export default (client) => { var info = JSON.parse(body); let mafiaInfo = info.servers.find((info2) => { try { - return info2.serverId.includes(config.prspySvID); + return info2.serverId.includes(config.prspy.id); } catch { return false; } @@ -27,17 +22,8 @@ export default (client) => { var gameModes = locals.gameModes[mafiaInfo.properties.gametype].short; var layers = locals.layers[mafiaInfo.properties.bf2_mapsize].short; - //client.channels.cache.get('1031262929275863060').setName('Players: '+numplayers+'/100') - //client.channels.cache.get('1031263100420235366').setName('Map: '+mapName) - //client.channels.cache.get(' TO CHANGE').setName(gameModes+', '+layers) //used to be 1031263231240573028 - - - client.channels.cache.get("1031262929275863060").setName("│Map: " + mapName); - client.channels.cache.get("1031263100420235366").setName("│" + gameModes + ", " + layers + " | (" + numplayers + "/100)"); - - - - console.log(mapName); + client.channels.cache.get(config.prspy.mapChannelID).setName("│Map: " + mapName); + client.channels.cache.get(config.prspy.detailsChannelID).setName("│" + gameModes + ", " + layers + " | (" + numplayers + "/100)"); } } catch (e) { console.log("Error HandleInfo: " + e); diff --git a/functions/handlePRISM.js b/functions/handlePRISM.js index 16c48c9..cf7cb0e 100644 --- a/functions/handlePRISM.js +++ b/functions/handlePRISM.js @@ -1,6 +1,3 @@ -import dotenv from "dotenv"; -dotenv.config(); - import net from "net"; import crypto from "crypto"; import fs from "fs"; @@ -8,6 +5,9 @@ import fs from "fs"; import rand from "csprng"; import { EmbedBuilder } from "discord.js"; +import config from "../config.js"; +import { gunGameWinnerCache } from "./handleTrackersDemos.js"; + const netClient = new net.Socket(); // hash sums @@ -22,7 +22,7 @@ const MSG_END = "\x04\x00"; export default (client) => { client.handlePRISM = async () => { - const netConnect = () => { netClient.connect(process.env.PRISM_PORT, process.env.PRISM_IP); }; + const netConnect = () => { netClient.connect(config.prism.auth.port, config.prism.auth.ip); }; try { netClient.once("connect", () => { console.log("Connected to PRISM API"); @@ -86,7 +86,7 @@ export const ServerCommands = { }; const login1 = () => { - writeToClient("login1", "1" + MSG_FIELD + process.env.PRISM_USRNAME + MSG_FIELD + theCCK); + writeToClient("login1", "1" + MSG_FIELD + config.prism.auth.username + MSG_FIELD + theCCK); }; const login2 = (passHash, serverChallenge) => { @@ -94,9 +94,9 @@ const login2 = (passHash, serverChallenge) => { const saltedpass = crypto.createHash("sha1"); const challengedigest = crypto.createHash("sha1"); - passwordhash.update(process.env.PRISM_USRPW); + passwordhash.update(config.prism.auth.password); saltedpass.update(passHash + MSG_START + passwordhash.digest("hex")); - challengedigest.update(process.env.PRISM_USRNAME + MSG_FIELD + theCCK + MSG_FIELD + serverChallenge + MSG_FIELD + saltedpass.digest("hex")); + challengedigest.update(config.prism.auth.username + MSG_FIELD + theCCK + MSG_FIELD + serverChallenge + MSG_FIELD + saltedpass.digest("hex")); writeToClient("login2", challengedigest.digest("hex")); }; @@ -189,8 +189,8 @@ const messageHandler = (client, messages) => { var tkString = fields[fields.length - 1].split(" "); - client.channels.cache.get("1022258448508928031").send(formatedFields); - //client.channels.cache.get('1022258448508928031').send("`"+fields+"`"); + client.channels.cache.get(config.prism.generalChannelID).send(formatedFields); + //client.channels.cache.get(config.prism.generalChannelID).send("`"+fields+"`"); if (tkString[5] == "m]") { tkString = fields[fields.length - 1].split(" "); //console.log(fields[fields.length-1].split(' ')) @@ -206,12 +206,12 @@ const messageHandler = (client, messages) => { .setFooter({ text: "IN-GAME" }); - client.channels.cache.get("1033130972264276018").send({ content: "`" + fields[fields.length - 1].split(" ") + "`", embeds: [adminLogPost] }); + client.channels.cache.get(config.prism.teamkillChannelID).send({ content: "`" + fields[fields.length - 1].split(" ") + "`", embeds: [adminLogPost] }); } else if (dataLenght[dataLenght.length - 1].includes("is victorious!") == true) { var ggWinner = dataLenght[dataLenght.length - 1].split(" "); console.log("GUNGAME WINNER::::" + ggWinner[1].slice(0, -2)); - fs.writeFile("logs/gungame_winner.txt", ggWinner[1].slice(0, -2), function(err) { + fs.writeFile(gunGameWinnerCache, ggWinner[1].slice(0, -2), function(err) { if (err) { // append failed } else { diff --git a/functions/handleTrackersDemos.js b/functions/handleTrackersDemos.js index 9d390dd..ad5c602 100644 --- a/functions/handleTrackersDemos.js +++ b/functions/handleTrackersDemos.js @@ -1,16 +1,14 @@ -import dotenv from "dotenv"; -dotenv.config(); - import fs from "fs"; import pather from "path"; +import { join as joinPath } from "path"; import chokidar from "chokidar"; import Tail from "always-tail"; import { createCanvas, loadImage } from "canvas"; import ftp from "basic-ftp"; -import locals from "../localization.json" assert { type: "json"}; import config from "../config.js"; +import locals from "../localization.json" assert { type: "json"}; import { EmbedBuilder, @@ -22,13 +20,13 @@ import { const flagsDir = "assets/flags/"; -const gunGameWinnerCache = "cache/gungame_winner.txt"; +export const gunGameWinnerCache = "cache/gungame_winner.txt"; const jsonFormatedCache = "cache/json_formated/"; const imagesCache = "cache/images/"; export default (client) => { client.handleTrackersDemos = async () => { - var ticketsLog = config.logs.tickets; + var ticketsLog = config.logs.tickets.path; if (!fs.existsSync(ticketsLog)) fs.writeFileSync(ticketsLog, ""); var tailTickets = new Tail(ticketsLog, "\n"); @@ -52,18 +50,18 @@ export default (client) => { }); //chatlogPath watcherChat - var watcherChat = chokidar.watch(config.chatlogsDir, { - ignored: ["]/^./", "demos/index.php"], - persistent: true, - }); - var chatlogPath = "none"; - watcherChat.on("add", (path2) => { - chatlogPath = pather.basename(path2, ".txt"); - console.log(`File ${chatlogPath}.txt has been cached`); - }); + // var watcherChat = chokidar.watch(config.chatlogsDir, { + // ignored: ["]/^./", "demos/index.php"], + // persistent: true, + // }); + // var chatlogPath = "none"; + // watcherChat.on("add", (path2) => { + // chatlogPath = pather.basename(path2, ".txt"); + // console.log(`File ${chatlogPath}.txt has been cached`); + // }); //demoPath watcherDemo - var watcherDemo = chokidar.watch(config.bf2DemosDir, { + var watcherDemo = chokidar.watch(config.demos.bf2.source, { ignored: ["]/^./", "demos/index.php"], persistent: true, }); @@ -73,7 +71,7 @@ export default (client) => { console.log(`File ${demoPath}.bf2demo has been cached`); }); - var watcher = chokidar.watch(config.jsonDir, { + var watcher = chokidar.watch(config.demos.json.source, { ignored: "/^./", persistent: true, }); @@ -98,8 +96,8 @@ export default (client) => { var demoPathFormat = fileName1.replace("tracker", "demo"); fs.rename( - config.bf2DemosDir + demoPath + ".bf2demo", - config.bf2DemosDir + demoPathFormat + ".bf2demo", + config.demos.bf2.source + demoPath + ".bf2demo", + config.demos.bf2.source + demoPathFormat + ".bf2demo", function(err) { if (err) console.log("ERROR: " + err); } @@ -265,26 +263,28 @@ export default (client) => { const file = new AttachmentBuilder(imagesCache + fileName1 + ".png"); //const filecl = new AttachmentBuilder('logs/chatlogs/'+chatlogPath+'.txt'); const filetracker = new AttachmentBuilder( - config.prDemosDir + fileName1 + ".PRdemo" + config.demos.pr.source + fileName1 + ".PRdemo" ); var row = new ActionRowBuilder().addComponents( new ButtonBuilder() .setLabel("Download Battle Recorder") .setStyle(ButtonStyle.Link) .setURL( - "https://www.prmafia.online/br/demos/" + demoPathFormat + ".bf2demo" + config.demos.bf2.url + demoPathFormat + ".bf2demo" ), new ButtonBuilder() .setLabel("Download Tracker") .setStyle(ButtonStyle.Link) .setURL( - "https://www.prmafia.online/br/trackers/" + fileName1 + ".PRdemo" + config.demos.pr.url + fileName1 + ".PRdemo" ), new ButtonBuilder() .setLabel("View Tracker") .setStyle(ButtonStyle.Link) .setURL( - "https://www.prmafia.online/br/realitytracker_master/index.html?demo=../trackers/" + + config.demos.trackerViewerUrl + + "index.html?demo=" + + config.demos.pr.url + fileName1 + ".PRdemo" ) @@ -295,21 +295,21 @@ export default (client) => { clientFTP.ftp.verbose = true; try { await clientFTP.access({ - host: process.env.FTP_HOST, - user: process.env.FTP_USER, - password: process.env.FTP_PASS, + host: config.demos.ftp.host, + user: config.demos.ftp.user, + password: config.demos.ftp.password, }); await clientFTP.uploadFrom( jsonFormatedCache + fileName1 + ".json", - "br/json_formated/" + fileName1 + ".json" + joinPath(config.demos.json.destination, fileName1) + ".json" ); await clientFTP.uploadFrom( - config.prDemosDir + fileName1 + ".PRdemo", - "br/trackers/" + fileName1 + ".PRdemo" + joinPath(config.demos.pr.source, fileName1) + ".PRdemo", + joinPath(config.demos.pr.destination, fileName1) + ".PRdemo" ); await clientFTP.uploadFrom( - config.bf2DemosDir + demoPathFormat + ".bf2demo", - "br/demos/" + demoPathFormat + ".bf2demo" + joinPath(config.demos.bf2.source, demoPathFormat) + ".bf2demo", + joinPath(config.demos.bf2.destination, demoPathFormat) + ".bf2demo" ); clientFTP.close(); } catch (err) { @@ -318,7 +318,7 @@ export default (client) => { clientFTP.close(); console.log("\x1b[36m", "Ready for next round!", "\x1b[0m"); await client.channels.cache - .get("995387003409539073") + .get(config.demos.channelID) .send({ embeds: [roundEmbed], components: [row], diff --git a/functions/logs/bans.js b/functions/logs/bans.js index b3c4326..15a2587 100644 --- a/functions/logs/bans.js +++ b/functions/logs/bans.js @@ -1,7 +1,7 @@ import { EmbedBuilder } from "discord.js"; +import config from "../../config.js"; import { decideIssuerType, descriptionLine, obfuscateIP, flagFromIP, fullName } from "./utils.js"; import { UserType } from "./interfaces.js"; -import config from "../../config.js"; var Duration; (function (Duration) { Duration["Permanent"] = "perm"; @@ -69,7 +69,7 @@ export const parseBanLine = (line) => { duration = Number(groups.duration); } const out = { - date: new Date(groups.date + "T" + groups.time + config.timezone), + date: new Date(groups.date + "T" + groups.time + config.server.timezone), body: groups.body, issuer: { typ: decideIssuerType(groups), diff --git a/functions/logs/bans.test.js b/functions/logs/bans.test.js index 6c1b1a6..9d189cc 100644 --- a/functions/logs/bans.test.js +++ b/functions/logs/bans.test.js @@ -17,7 +17,7 @@ test("parseBanLine", () => { "tag": "", "typ": 0, }, - "date": new Date("2023-04-02T21:13:00.000" + config.timezone), + "date": new Date("2023-04-02T21:13:00.000" + config.server.timezone), "duration": 10800, "body": "No mic! We advise you to get the WO MIC app on your phone and connect it to your PC, google it for more info!", } @@ -25,7 +25,7 @@ test("parseBanLine", () => { in: "[2023-04-02 20:34] c79068163db043379abacb66ed6ab6df [TAG] some_user 192.168.240.229 No mic! We advise you to get the WO MIC app on your phone and connect it to your PC, google it for more info! banned by KIA rPoXoTauJIo (10800)", out: { "body": "No mic! We advise you to get the WO MIC app on your phone and connect it to your PC, google it for more info!", - "date": new Date("2023-04-02T20:34:00.000" + config.timezone), + "date": new Date("2023-04-02T20:34:00.000" + config.server.timezone), "duration": 10800, "issuer": { "name": "rPoXoTauJIo", diff --git a/functions/logs/bans.test.ts b/functions/logs/bans.test.ts index c86ba51..9935b8d 100644 --- a/functions/logs/bans.test.ts +++ b/functions/logs/bans.test.ts @@ -18,7 +18,7 @@ test("parseBanLine", () => { "tag": "", "typ": 0, }, - "date": new Date("2023-04-02T21:13:00.000" + config.timezone), + "date": new Date("2023-04-02T21:13:00.000" + config.server.timezone), "duration": 10800, "body": "No mic! We advise you to get the WO MIC app on your phone and connect it to your PC, google it for more info!", } @@ -26,7 +26,7 @@ test("parseBanLine", () => { in: "[2023-04-02 20:34] c79068163db043379abacb66ed6ab6df [TAG] some_user 192.168.240.229 No mic! We advise you to get the WO MIC app on your phone and connect it to your PC, google it for more info! banned by KIA rPoXoTauJIo (10800)", out: { "body": "No mic! We advise you to get the WO MIC app on your phone and connect it to your PC, google it for more info!", - "date": new Date("2023-04-02T20:34:00.000" + config.timezone), + "date": new Date("2023-04-02T20:34:00.000" + config.server.timezone), "duration": 10800, "issuer": { "name": "rPoXoTauJIo", diff --git a/functions/logs/bans.ts b/functions/logs/bans.ts index 303b7b1..1c646b9 100644 --- a/functions/logs/bans.ts +++ b/functions/logs/bans.ts @@ -1,9 +1,10 @@ import { EmbedBuilder } from "discord.js"; -import { decideIssuerType, descriptionLine, obfuscateIP, flagFromIP, fullName } from "./utils.js"; -import { Embeds, User, UserDetailed, UserType } from "./interfaces.js"; import config from "../../config.js"; +import { decideIssuerType, descriptionLine, obfuscateIP, flagFromIP, fullName } from "./utils.js"; +import { Embeds, User, UserDetailed, UserType } from "./interfaces.js"; + enum Duration { Permanent = "perm", Round = "round", @@ -89,7 +90,7 @@ export const parseBanLine = (line: string): BanData | null => { } const out: BanData = { - date: new Date(groups.date + "T" + groups.time + config.timezone), + date: new Date(groups.date + "T" + groups.time + config.server.timezone), body: groups.body, issuer: { diff --git a/functions/logs/commands/parser.js b/functions/logs/commands/parser.js index cec0d9d..6fe2ce6 100644 --- a/functions/logs/commands/parser.js +++ b/functions/logs/commands/parser.js @@ -11,7 +11,7 @@ export const parseCommandLine = (line) => { const groups = match.groups; const out = { command: groups.command, - date: new Date(groups.date + "T" + groups.time + config.timezone), + date: new Date(groups.date + "T" + groups.time + config.server.timezone), issuer: { typ: decideIssuerType(groups), name: groups.prism || groups.server || groups.i_name, diff --git a/functions/logs/commands/parser.test.js b/functions/logs/commands/parser.test.js index 08889ba..d232b34 100644 --- a/functions/logs/commands/parser.test.js +++ b/functions/logs/commands/parser.test.js @@ -5,7 +5,7 @@ test("parseCommandLine", () => { { in: "[2023-04-01 10:11] !INIT performed by 'TAG name': ", out: { - "date": new Date("2023-04-01T10:11:00.000" + config.timezone), + "date": new Date("2023-04-01T10:11:00.000" + config.server.timezone), "body": "", "command": "INIT", "issuer": { @@ -23,14 +23,14 @@ test("parseCommandLine", () => { "name": "Shil", "typ": 0, }, - "date": new Date("2023-04-14T20:23:00.000" + config.timezone), + "date": new Date("2023-04-14T20:23:00.000" + config.server.timezone), } }, { in: "[2023-04-01 15:30] MAPVOTERESULT performed by '[POV] ARC*fecht_niko': Vote finished: Aas: 32 | Ins: 11", out: { "body": "Vote finished: Aas: 32 | Ins: 11", "command": "MAPVOTERESULT", - "date": new Date("2023-04-01T15:30:00.000" + config.timezone), + "date": new Date("2023-04-01T15:30:00.000" + config.server.timezone), "issuer": { "name": "ARC*fecht_niko", "tag": "[POV]", diff --git a/functions/logs/commands/parser.test.ts b/functions/logs/commands/parser.test.ts index 2c76957..ae30300 100644 --- a/functions/logs/commands/parser.test.ts +++ b/functions/logs/commands/parser.test.ts @@ -6,7 +6,7 @@ test("parseCommandLine", () => { { in: "[2023-04-01 10:11] !INIT performed by 'TAG name': ", out: { - "date": new Date("2023-04-01T10:11:00.000" + config.timezone), + "date": new Date("2023-04-01T10:11:00.000" + config.server.timezone), "body": "", "command": "INIT", "issuer": { @@ -24,14 +24,14 @@ test("parseCommandLine", () => { "name": "Shil", "typ": 0, }, - "date": new Date("2023-04-14T20:23:00.000" + config.timezone), + "date": new Date("2023-04-14T20:23:00.000" + config.server.timezone), } }, { in: "[2023-04-01 15:30] MAPVOTERESULT performed by '[POV] ARC*fecht_niko': Vote finished: Aas: 32 | Ins: 11", out: { "body": "Vote finished: Aas: 32 | Ins: 11", "command": "MAPVOTERESULT", - "date": new Date("2023-04-01T15:30:00.000" + config.timezone), + "date": new Date("2023-04-01T15:30:00.000" + config.server.timezone), "issuer": { "name": "ARC*fecht_niko", "tag": "[POV]", diff --git a/functions/logs/commands/parser.ts b/functions/logs/commands/parser.ts index ce0ab1e..cd998a0 100644 --- a/functions/logs/commands/parser.ts +++ b/functions/logs/commands/parser.ts @@ -25,7 +25,7 @@ export const parseCommandLine = (line: string): CommandData | null => { const out: CommandData = { command: groups.command, - date: new Date(groups.date + "T" + groups.time + config.timezone), + date: new Date(groups.date + "T" + groups.time + config.server.timezone), issuer: { typ: decideIssuerType(groups), name: groups.prism || groups.server || groups.i_name, diff --git a/functions/logs/index.js b/functions/logs/index.js index 2caa2ec..fd458d3 100644 --- a/functions/logs/index.js +++ b/functions/logs/index.js @@ -1,12 +1,12 @@ import fs from "fs"; import Tail from "always-tail"; +import config from "../../config.js"; import { prepareEmbeds as prepareBanEmbeds, parseBanLine } from "./bans.js"; import { parseCommandLine } from "./commands/parser.js"; import { parseJoinLine, prepareEmbeds as prepareJoinEmbeds } from "./join.js"; import { prepareEmbeds as prepareCommandEmbeds } from "./commands/embeds.js"; -import { channels, logs } from "../../config.js"; export const watchBanlist = (client) => { - const filenameBans = logs.bans; + const filenameBans = config.logs.bans.path; if (!fs.existsSync(filenameBans)) fs.writeFileSync(filenameBans, ""); const tailBans = new Tail(filenameBans, "\n"); @@ -17,10 +17,10 @@ export const watchBanlist = (client) => { } const { priv, pub } = prepareBanEmbeds(ban); if (priv) { - client.channels.cache.get(channels.bans.priv).send({ embeds: [priv] }); + client.channels.cache.get(config.logs.bans.privateChannelID).send({ embeds: [priv] }); } if (pub) { - client.channels.cache.get(channels.bans.pub).send({ embeds: [pub] }); + client.channels.cache.get(config.logs.bans.publicChannelID).send({ embeds: [pub] }); } }); tailBans.on("error", function (error) { @@ -29,7 +29,7 @@ export const watchBanlist = (client) => { tailBans.watch(); }; export const watchCommands = (client) => { - const filenameAdmin = logs.commands; + const filenameAdmin = config.logs.commands.path; if (!fs.existsSync(filenameAdmin)) fs.writeFileSync(filenameAdmin, ""); const tailAdmins = new Tail(filenameAdmin, "\n"); @@ -50,10 +50,10 @@ export const watchCommands = (client) => { } const { priv, pub } = prepareCommandEmbeds(command); if (priv) { - client.channels.cache.get(channels.commands.priv).send({ embeds: [priv] }); + client.channels.cache.get(config.logs.commands.privateChannelID).send({ embeds: [priv] }); } if (pub) { - client.channels.cache.get(channels.commands.pub).send({ embeds: [pub] }); + client.channels.cache.get(config.logs.commands.publicChannelID).send({ embeds: [pub] }); } }); tailAdmins.on("error", function (error) { @@ -62,7 +62,7 @@ export const watchCommands = (client) => { tailAdmins.watch(); }; export const watchJoin = (client) => { - const filenameJoin = logs.joins; + const filenameJoin = config.logs.joins.path; if (!fs.existsSync(filenameJoin)) fs.writeFileSync(filenameJoin, ""); const tailJoin = new Tail(filenameJoin, "\n"); @@ -73,7 +73,7 @@ export const watchJoin = (client) => { } const { priv } = prepareJoinEmbeds(join); if (priv) { - client.channels.cache.get(channels.join.priv).send({ embeds: [priv] }); + client.channels.cache.get(config.logs.joins.privateChannelID).send({ embeds: [priv] }); } }); tailJoin.on("error", function (error) { diff --git a/functions/logs/index.ts b/functions/logs/index.ts index 662b5e3..a404655 100644 --- a/functions/logs/index.ts +++ b/functions/logs/index.ts @@ -1,15 +1,16 @@ import fs from "fs"; import Tail from "always-tail"; +import config from "../../config.js"; + import { prepareEmbeds as prepareBanEmbeds, parseBanLine } from "./bans.js"; import { parseCommandLine } from "./commands/parser.js"; import { parseJoinLine, prepareEmbeds as prepareJoinEmbeds } from "./join.js"; import { prepareEmbeds as prepareCommandEmbeds } from "./commands/embeds.js"; import { Client, TextChannel } from "discord.js"; -import { channels, logs } from "../../config.js"; export const watchBanlist = (client: Client) => { - const filenameBans = logs.bans; + const filenameBans = config.logs.bans.path; if (!fs.existsSync(filenameBans)) fs.writeFileSync(filenameBans, ""); const tailBans = new Tail(filenameBans, "\n"); @@ -22,11 +23,11 @@ export const watchBanlist = (client: Client) => { const { priv, pub } = prepareBanEmbeds(ban); if (priv) { - (client.channels.cache.get(channels.bans.priv) as TextChannel).send({ embeds: [priv] }); + (client.channels.cache.get(config.logs.bans.privateChannelID) as TextChannel).send({ embeds: [priv] }); } if (pub) { - (client.channels.cache.get(channels.bans.pub) as TextChannel).send({ embeds: [pub] }); + (client.channels.cache.get(config.logs.bans.publicChannelID) as TextChannel).send({ embeds: [pub] }); } }); @@ -39,7 +40,7 @@ export const watchBanlist = (client: Client) => { }; export const watchCommands = (client: Client) => { - const filenameAdmin = logs.commands; + const filenameAdmin = config.logs.commands.path; if (!fs.existsSync(filenameAdmin)) fs.writeFileSync(filenameAdmin, ""); const tailAdmins = new Tail(filenameAdmin, "\n"); @@ -64,11 +65,11 @@ export const watchCommands = (client: Client) => { const { priv, pub } = prepareCommandEmbeds(command); if (priv) { - (client.channels.cache.get(channels.commands.priv) as TextChannel).send({ embeds: [priv] }); + (client.channels.cache.get(config.logs.commands.privateChannelID) as TextChannel).send({ embeds: [priv] }); } if (pub) { - (client.channels.cache.get(channels.commands.pub) as TextChannel).send({ embeds: [pub] }); + (client.channels.cache.get(config.logs.commands.publicChannelID) as TextChannel).send({ embeds: [pub] }); } }); @@ -80,7 +81,7 @@ export const watchCommands = (client: Client) => { }; export const watchJoin = (client: Client) => { - const filenameJoin = logs.joins; + const filenameJoin = config.logs.joins.path; if (!fs.existsSync(filenameJoin)) fs.writeFileSync(filenameJoin, ""); const tailJoin = new Tail(filenameJoin, "\n"); @@ -93,7 +94,7 @@ export const watchJoin = (client: Client) => { const { priv } = prepareJoinEmbeds(join); if (priv) { - (client.channels.cache.get(channels.join.priv) as TextChannel).send({ embeds: [priv] }); + (client.channels.cache.get(config.logs.joins.privateChannelID) as TextChannel).send({ embeds: [priv] }); } }); diff --git a/functions/logs/interfaces.js b/functions/logs/interfaces.js index ff50d3e..77df5fa 100644 --- a/functions/logs/interfaces.js +++ b/functions/logs/interfaces.js @@ -3,7 +3,7 @@ export var UserType; UserType[UserType["Player"] = 0] = "Player"; UserType[UserType["Prism"] = 1] = "Prism"; UserType[UserType["Server"] = 2] = "Server"; -})(UserType = UserType || (UserType = {})); +})(UserType || (UserType = {})); export const dateFormat = "YYYY-MM-DD"; export const dateTimeFormat = dateFormat + " " + "HH:mm:ss"; export var DiscordTimeFormat; @@ -15,4 +15,4 @@ export var DiscordTimeFormat; DiscordTimeFormat["DateTime"] = "f"; DiscordTimeFormat["LongDateTime"] = "F"; DiscordTimeFormat["Relative"] = "R"; -})(DiscordTimeFormat = DiscordTimeFormat || (DiscordTimeFormat = {})); +})(DiscordTimeFormat || (DiscordTimeFormat = {})); diff --git a/functions/logs/join.js b/functions/logs/join.js index e30b945..2b07111 100644 --- a/functions/logs/join.js +++ b/functions/logs/join.js @@ -1,8 +1,8 @@ import { EmbedBuilder } from "discord.js"; import dayjs from "dayjs"; +import config from "../../config.js"; import { descriptionLine, flagFromIP, prepareDiscordDate } from "./utils.js"; import { DiscordTimeFormat, UserType } from "./interfaces.js"; -import config from "../../config.js"; const regex = /\[(?(\d{4})-(\d{2})-(\d{2}))\s(?