big update of structure
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
2f1cdbbaf6
commit
9b2ddc35fa
9
index.ts
9
index.ts
@ -1,13 +1,12 @@
|
|||||||
import express, { Application } from "express"
|
|
||||||
import { config } from "./server/configuration"
|
import { config } from "./server/configuration"
|
||||||
import DiscordAdapter from "./server/discordAdapter"
|
|
||||||
import Routes from "./server/routes"
|
|
||||||
import Server from "./server/server"
|
import Server from "./server/server"
|
||||||
|
import { ExtendedClient } from "./server/structures/client"
|
||||||
|
|
||||||
const server = Server.init(config.port)
|
const server = Server.init(config.port)
|
||||||
|
|
||||||
server.start(() => {
|
server.start(() => {
|
||||||
console.log(`Server running on port ${server.getPort()}`)
|
console.log(`Server running on port ${server.getPort()}`)
|
||||||
new Routes().setRoutes(server.getApp())
|
//const discordAdapter = new DiscordAdapter()
|
||||||
const discordAdapter = new DiscordAdapter()
|
const client = new ExtendedClient()
|
||||||
|
client.start()
|
||||||
})
|
})
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import RegistrationHandler from "./RegistrationHandler"
|
|
||||||
|
|
||||||
export default class MuteHandler {
|
|
||||||
public mute(player: string): boolean {
|
|
||||||
const register = RegistrationHandler.Instance
|
|
||||||
const binding = register.getNameRegisteredForSteamUser(player)
|
|
||||||
console.log(`Performing mute wizardry on ${player}, ${JSON.stringify(binding)}`)
|
|
||||||
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
public unmute(player: string): boolean {
|
|
||||||
const register = RegistrationHandler.Instance
|
|
||||||
const binding = register.getNameRegisteredForSteamUser(player)
|
|
||||||
console.log(`Performing unmute wizardry on ${player}`)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
public unmuteAll(): boolean {
|
|
||||||
const register = RegistrationHandler.Instance
|
|
||||||
const binding = register.getAllMappings()
|
|
||||||
|
|
||||||
console.log(`Performing unmute wizardry on all players`)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
import { GuildMember } from "discord.js"
|
|
||||||
import { Maybe, userNameBinding } from "./interfaces"
|
|
||||||
|
|
||||||
export default class RegistrationHandler {
|
|
||||||
private userRegister: userNameBinding[] = []
|
|
||||||
private static _instance: RegistrationHandler
|
|
||||||
public constructor() {
|
|
||||||
console.log('Setup RegistrationHandler')
|
|
||||||
}
|
|
||||||
public static get Instance() {
|
|
||||||
return this._instance || (this._instance = new this())
|
|
||||||
}
|
|
||||||
|
|
||||||
public register(discordUser: GuildMember, steamname: string): boolean {
|
|
||||||
try {
|
|
||||||
|
|
||||||
const binding: userNameBinding = {
|
|
||||||
Steam: steamname,
|
|
||||||
DiscordUser: discordUser
|
|
||||||
}
|
|
||||||
console.log(`Trying to register ${JSON.stringify(binding)}`)
|
|
||||||
let alreadyPresentBinding = this.userRegister.find(x => x.DiscordUser.user.username == binding.DiscordUser.user.username)
|
|
||||||
if (alreadyPresentBinding) {
|
|
||||||
console.log(`Binding already present: ${JSON.stringify(alreadyPresentBinding)}, overwriting.`)
|
|
||||||
alreadyPresentBinding = binding
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.userRegister.push(binding)
|
|
||||||
console.log(`Binding successfully added.`)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
public getAllMappings(): userNameBinding[] {
|
|
||||||
return this.userRegister
|
|
||||||
}
|
|
||||||
public removeUser(discordUser: GuildMember): void {
|
|
||||||
this.userRegister = this.userRegister.filter(x => x.DiscordUser.user.id !== discordUser.user.id)
|
|
||||||
}
|
|
||||||
public getNameRegisteredForDiscordUser(discordUser: GuildMember): Maybe<userNameBinding> {
|
|
||||||
return this.userRegister.find(x => x.DiscordUser.user.id == discordUser.user.id)
|
|
||||||
}
|
|
||||||
public getNameRegisteredForSteamUser(steamUser: string): Maybe<userNameBinding> {
|
|
||||||
return this.userRegister.find(x => x.Steam == steamUser)
|
|
||||||
}
|
|
||||||
public listRegisteredMembers(): string {
|
|
||||||
const output = this.userRegister.map(x => `${x.DiscordUser.user.username} : ${x.Steam}\n`)
|
|
||||||
return output.join()
|
|
||||||
}
|
|
||||||
private printHelpText(): string { return "" }
|
|
||||||
private buildHelpText(): string { return "" }
|
|
||||||
}
|
|
8
server/commands/listEvents.ts
Normal file
8
server/commands/listEvents.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { Command } from '../structures/command'
|
||||||
|
export default new Command({
|
||||||
|
name: 'list',
|
||||||
|
description: 'Lists upcoming events',
|
||||||
|
run: async ({ interaction }) => {
|
||||||
|
interaction.reply('Hello')
|
||||||
|
}
|
||||||
|
})
|
@ -1,91 +0,0 @@
|
|||||||
import { REST } from '@discordjs/rest'
|
|
||||||
import { Routes } from 'discord-api-types/v9'
|
|
||||||
import { config } from './configuration'
|
|
||||||
import { Client, CommandInteraction, Intents, } from 'discord.js'
|
|
||||||
import { discordCommand } from './interfaces'
|
|
||||||
import eventHandler from './eventHandler'
|
|
||||||
import fs from 'fs'
|
|
||||||
|
|
||||||
export default class DiscordAdapter {
|
|
||||||
private rest: REST
|
|
||||||
private client: Client
|
|
||||||
private eventFilePath = `${__dirname}/events`
|
|
||||||
|
|
||||||
public constructor() {
|
|
||||||
this.rest = new REST({ version: '9' }).setToken(config.token)
|
|
||||||
this.client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_SCHEDULED_EVENTS] })
|
|
||||||
this.registerEventCallback().then(() => {
|
|
||||||
this.client.login(config.token)
|
|
||||||
})
|
|
||||||
this.registerCommands(this.commandList)
|
|
||||||
}
|
|
||||||
public async registerCommands(pCommands: discordCommand[]) {
|
|
||||||
try {
|
|
||||||
console.log('Refreshing slash commands')
|
|
||||||
await this.rest.put(Routes.applicationGuildCommands(config.client_id, config.guild_id), { body: pCommands })
|
|
||||||
console.log('Successfully refreshed slash commands')
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`Error refreshing slash commands: ${error}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async importFile(filepath: string): Promise<any> {
|
|
||||||
console.debug(`Importing ${filepath}`)
|
|
||||||
const imported = await import(filepath)
|
|
||||||
console.debug(`Imported ${JSON.stringify(imported)}`)
|
|
||||||
return imported
|
|
||||||
}
|
|
||||||
public async registerEventCallback() {
|
|
||||||
try {
|
|
||||||
const eventFiles = fs.readdirSync(this.eventFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'));
|
|
||||||
for (const file of eventFiles) {
|
|
||||||
const filePath = `${this.eventFilePath}/${file}`
|
|
||||||
const event = await this.importFile(filePath)
|
|
||||||
if (event.once) {
|
|
||||||
console.log(`Registering once ${file}`)
|
|
||||||
this.client.once(event.name, (...args: any[]) => event.execute(...args))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(`Registering on ${file}`)
|
|
||||||
this.client.on(event.name, (...args: any[]) => event.execute(...args))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(this.client.eventNames())
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async showNext(interaction: CommandInteraction): Promise<void> {
|
|
||||||
const guild = interaction.guild
|
|
||||||
if (!guild) {
|
|
||||||
console.log(`There is no guild here`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = new eventHandler().getNextEvent(guild)
|
|
||||||
await interaction.reply(output)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
public async listEvents(interaction: CommandInteraction): Promise<void> {
|
|
||||||
const guild = interaction.guild
|
|
||||||
if (!guild) {
|
|
||||||
console.log(`There is no guild here`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = new eventHandler().listAllEvents(guild)
|
|
||||||
await interaction.reply(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
public commandList: discordCommand[] = [
|
|
||||||
{
|
|
||||||
name: "shownext",
|
|
||||||
description: "Shows next Events",
|
|
||||||
performCommand: this.showNext
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "listevents",
|
|
||||||
description: "Lists all Events",
|
|
||||||
performCommand: this.listEvents
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,5 +1,3 @@
|
|||||||
import { CommandInteraction, GuildMember } from "discord.js"
|
|
||||||
import RegistrationHandler from "./RegistrationHandler"
|
|
||||||
|
|
||||||
export type Maybe<T> = T | undefined
|
export type Maybe<T> = T | undefined
|
||||||
export interface Player {
|
export interface Player {
|
||||||
@ -12,13 +10,3 @@ export interface localized_string {
|
|||||||
english: string
|
english: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export interface userNameBinding {
|
|
||||||
Steam: string,
|
|
||||||
DiscordUser: GuildMember
|
|
||||||
}
|
|
||||||
export interface discordCommand {
|
|
||||||
name: string,
|
|
||||||
description: string
|
|
||||||
options?: any[]
|
|
||||||
performCommand(interaction: CommandInteraction, registration: RegistrationHandler): Promise<void>
|
|
||||||
}
|
|
||||||
|
0
server/logger.ts
Normal file
0
server/logger.ts
Normal file
@ -1,36 +0,0 @@
|
|||||||
import express from "express";
|
|
||||||
import MuteHandler from "./MuteHandler";
|
|
||||||
|
|
||||||
export default class Routes {
|
|
||||||
public constructor(
|
|
||||||
private muteHandler = new MuteHandler()
|
|
||||||
) { }
|
|
||||||
|
|
||||||
public setRoutes(app: express.Application): void {
|
|
||||||
app.route('').get(this.landingPage.bind(this))
|
|
||||||
app.route('/').get(this.landingPage.bind(this))
|
|
||||||
app.route('/mute').post(this.mutePlayer.bind(this))
|
|
||||||
app.route('/unmute/all').post(this.unmuteAll.bind(this))
|
|
||||||
app.route('/unmute/:id').post(this.unmutePlayer.bind(this))
|
|
||||||
}
|
|
||||||
private async mutePlayer(req: express.Request, res: express.Response): Promise<void> {
|
|
||||||
const playerName = req.body.name
|
|
||||||
console.log(`Muting player ${playerName}`)
|
|
||||||
this.muteHandler.mute(playerName)
|
|
||||||
res.status(200).json()
|
|
||||||
}
|
|
||||||
private async unmuteAll(_: express.Request, res: express.Response): Promise<void> {
|
|
||||||
console.log(`Unmuting all players`)
|
|
||||||
this.muteHandler.unmuteAll()
|
|
||||||
res.status(200).json()
|
|
||||||
}
|
|
||||||
private async unmutePlayer(req: express.Request, res: express.Response): Promise<void> {
|
|
||||||
const playerName = req.body.name
|
|
||||||
console.log(`Unmuting player ${playerName}`)
|
|
||||||
this.muteHandler.unmute(playerName)
|
|
||||||
res.status(200).json()
|
|
||||||
}
|
|
||||||
private async landingPage(_: express.Request, res: express.Response): Promise<void> {
|
|
||||||
res.send('Hello World')
|
|
||||||
}
|
|
||||||
}
|
|
76
server/structures/client.ts
Normal file
76
server/structures/client.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import { ApplicationCommandDataResolvable, Client, Collection, Intents } from "discord.js";
|
||||||
|
import { CommandType } from "../types/commandTypes";
|
||||||
|
import fs from 'fs'
|
||||||
|
import { config } from "../configuration";
|
||||||
|
|
||||||
|
export class ExtendedClient extends Client {
|
||||||
|
private eventFilePath = `${__dirname}/../events`
|
||||||
|
private commandFilePath = `${__dirname}/../commands`
|
||||||
|
private commands: Collection<string, CommandType> = new Collection()
|
||||||
|
public constructor() {
|
||||||
|
super({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_SCHEDULED_EVENTS] })
|
||||||
|
}
|
||||||
|
public start() {
|
||||||
|
const promises = []
|
||||||
|
promises.push(this.registerSlashCommands())
|
||||||
|
promises.push(this.registerEventCallback())
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
this.login(config.token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
private async importFile(filepath: string): Promise<any> {
|
||||||
|
console.debug(`Importing ${filepath}`)
|
||||||
|
const imported = await import(filepath)
|
||||||
|
console.debug(`Imported ${JSON.stringify(imported)}`)
|
||||||
|
return imported
|
||||||
|
}
|
||||||
|
public async registerCommands(cmds: ApplicationCommandDataResolvable[], guildId: string) {
|
||||||
|
if (guildId) {
|
||||||
|
this.guilds.cache.get(guildId)?.commands.set(cmds)
|
||||||
|
console.log(`Registering commands to ${guildId}`)
|
||||||
|
} else {
|
||||||
|
this.application?.commands.set(cmds)
|
||||||
|
console.log(`Registering global commands`)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
public async registerSlashCommands() {
|
||||||
|
try {
|
||||||
|
const slashCommands: ApplicationCommandDataResolvable[] = []
|
||||||
|
const commandFiles = fs.readdirSync(this.commandFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'))
|
||||||
|
for (const commandFile of commandFiles) {
|
||||||
|
const command = await this.importFile(commandFile)
|
||||||
|
if (!command.name) return
|
||||||
|
console.debug(command)
|
||||||
|
this.commands.set(command.name, command)
|
||||||
|
slashCommands.push(command)
|
||||||
|
}
|
||||||
|
this.on("ready", (client: Client) => {
|
||||||
|
console.log(`Ready processed ${client}`)
|
||||||
|
this.registerCommands(slashCommands, process.env.guildId ?? "")
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Error refreshing slash commands: ${error}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async registerEventCallback() {
|
||||||
|
try {
|
||||||
|
const eventFiles = fs.readdirSync(this.eventFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'));
|
||||||
|
for (const file of eventFiles) {
|
||||||
|
const filePath = `${this.eventFilePath}/${file}`
|
||||||
|
const event = await this.importFile(filePath)
|
||||||
|
if (event.once) {
|
||||||
|
console.log(`Registering once ${file}`)
|
||||||
|
this.once(event.name, (...args: any[]) => event.execute(...args))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(`Registering on ${file}`)
|
||||||
|
this.on(event.name, (...args: any[]) => event.execute(...args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(this.eventNames())
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
server/structures/command.ts
Normal file
7
server/structures/command.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { CommandType } from "../types/commandTypes";
|
||||||
|
|
||||||
|
export class Command {
|
||||||
|
constructor(commandOptions: CommandType) {
|
||||||
|
Object.assign(this, commandOptions)
|
||||||
|
}
|
||||||
|
}
|
6
server/types/clients.ts
Normal file
6
server/types/clients.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { ApplicationCommandDataResolvable } from "discord.js"
|
||||||
|
|
||||||
|
export interface RegisterCommandOptions {
|
||||||
|
guildId?: string
|
||||||
|
commands: ApplicationCommandDataResolvable[]
|
||||||
|
}
|
17
server/types/commandTypes.ts
Normal file
17
server/types/commandTypes.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { PermissionResolvable, ChatInputApplicationCommandData, CommandInteraction, CommandInteractionOptionResolver, GuildMember } from "discord.js";
|
||||||
|
import { ExtendedClient } from "../structures/client";
|
||||||
|
|
||||||
|
export interface ExtendedInteraction extends CommandInteraction {
|
||||||
|
member: GuildMember
|
||||||
|
}
|
||||||
|
interface RunOptions {
|
||||||
|
clients: ExtendedClient
|
||||||
|
interaction: ExtendedInteraction
|
||||||
|
args: CommandInteractionOptionResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunFunction = (options: RunOptions) => any
|
||||||
|
export type CommandType = {
|
||||||
|
userPermissions?: PermissionResolvable[]
|
||||||
|
run: RunFunction
|
||||||
|
} & ChatInputApplicationCommandData
|
@ -1,91 +0,0 @@
|
|||||||
import { GuildMember } from "discord.js"
|
|
||||||
import RegistrationHandler from "../server/RegistrationHandler"
|
|
||||||
|
|
||||||
const guildMember: GuildMember = <GuildMember><unknown>{
|
|
||||||
guild: {
|
|
||||||
id: 'guild_id',
|
|
||||||
name: 'Bot Playground',
|
|
||||||
icon: null,
|
|
||||||
features: [],
|
|
||||||
commands: { permissions: [], guild: [] },
|
|
||||||
members: { guild: [] },
|
|
||||||
channels: { guild: [] },
|
|
||||||
bans: { guild: [] },
|
|
||||||
roles: { guild: [] },
|
|
||||||
presences: {},
|
|
||||||
voiceStates: { guild: [] },
|
|
||||||
stageInstances: { guild: [] },
|
|
||||||
invites: { guild: [] },
|
|
||||||
deleted: false,
|
|
||||||
available: true,
|
|
||||||
shardId: 0,
|
|
||||||
splash: null,
|
|
||||||
banner: null,
|
|
||||||
description: null,
|
|
||||||
verificationLevel: 'NONE',
|
|
||||||
vanityURLCode: null,
|
|
||||||
nsfwLevel: 'DEFAULT',
|
|
||||||
discoverySplash: null,
|
|
||||||
memberCount: 2,
|
|
||||||
large: false,
|
|
||||||
applicationId: null,
|
|
||||||
afkTimeout: 300,
|
|
||||||
afkChannelId: null,
|
|
||||||
systemChannelId: 'channel_id',
|
|
||||||
premiumTier: 'NONE',
|
|
||||||
premiumSubscriptionCount: 0,
|
|
||||||
explicitContentFilter: 'DISABLED',
|
|
||||||
mfaLevel: 'NONE',
|
|
||||||
joinedTimestamp: 1636540056755,
|
|
||||||
defaultMessageNotifications: 'ALL_MESSAGES',
|
|
||||||
systemChannelFlags: { bitfield: 0 },
|
|
||||||
maximumMembers: 250000,
|
|
||||||
maximumPresences: null,
|
|
||||||
approximateMemberCount: null,
|
|
||||||
approximatePresenceCount: null,
|
|
||||||
vanityURLUses: null,
|
|
||||||
rulesChannelId: null,
|
|
||||||
publicUpdatesChannelId: null,
|
|
||||||
preferredLocale: 'en-US',
|
|
||||||
ownerId: 'ownerID',
|
|
||||||
emojis: { guild: [] },
|
|
||||||
stickers: { guild: [] }
|
|
||||||
},
|
|
||||||
joinedTimestamp: 1636539420924,
|
|
||||||
premiumSinceTimestamp: null,
|
|
||||||
deleted: false,
|
|
||||||
nickname: null,
|
|
||||||
pending: false,
|
|
||||||
_roles: [],
|
|
||||||
user: {
|
|
||||||
id: 'user_id',
|
|
||||||
bot: false,
|
|
||||||
system: false,
|
|
||||||
flags: { bitfield: 256 },
|
|
||||||
username: 'username',
|
|
||||||
discriminator: '0965',
|
|
||||||
avatar: 'avatar_string',
|
|
||||||
banner: undefined,
|
|
||||||
accentColor: undefined
|
|
||||||
},
|
|
||||||
avatar: null
|
|
||||||
}
|
|
||||||
|
|
||||||
const registeredUser = {
|
|
||||||
"Steam": "abc",
|
|
||||||
"DiscordUser": guildMember
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
test(`Instances`, () => {
|
|
||||||
const register = RegistrationHandler.Instance
|
|
||||||
expect(register).toBeDefined()
|
|
||||||
})
|
|
||||||
test(`Registration works`, () => {
|
|
||||||
const register = RegistrationHandler.Instance
|
|
||||||
register.register(<GuildMember>guildMember, "abc")
|
|
||||||
const result = register.getAllMappings()
|
|
||||||
console.log(JSON.stringify(result))
|
|
||||||
expect(result).toBeDefined()
|
|
||||||
expect(result).toEqual([registeredUser])
|
|
||||||
})
|
|
Loading…
Reference in New Issue
Block a user