better structure

main
Benjamin Kraft 9 months ago
parent f65d169505
commit f965eaacde
  1. 44
      src/bot.ts
  2. 16
      src/command.ts
  3. 15
      src/commands/add.ts
  4. 7
      src/deploy-commands.ts
  5. 4
      src/index.ts
  6. 92
      src/player.ts

@ -1,24 +1,24 @@
import {Client, Collection, Events, GatewayIntentBits, Interaction, Message} from "discord.js"
import {Client, Collection, Events, GatewayIntentBits, Interaction} from "discord.js"
import {Player} from "./player";
import fs from "node:fs";
import {Command} from "./command";
import path from "node:path";
import {Command, loadCommands} from "./command";
export class UEMEloBot extends Client {
players: Player[] = []
fileName = "players.json"
commands: Collection<string, Command> = new Collection<string, Command>();
commands = new Collection<string, Command>();
constructor() {
super({intents: [GatewayIntentBits.Guilds]});
this.once(Events.ClientReady, this.onReady);
this.on(Events.InteractionCreate, this.onInteractionCreate);
this.parsePlayersFromFile();
this.loadCommands().then(async () => {
loadCommands().then(async commands => {
this.commands = commands;
const token = await this.login();
console.log(`Discord Token: ${token}`);
setInterval(this.updateStartElo.bind(this), 5000);
setInterval(this.updatePlayers.bind(this), 30 * 60 * 1000);
await this.addPlayer("benjo", "tgm");
await this.addPlayer("unclebenss", "euw");
await this.addPlayer("moché", "EUw");
@ -29,7 +29,7 @@ export class UEMEloBot extends Client {
if (!interaction.isChatInputCommand())
return;
let commandName = interaction.commandName;
let command = this.commands.ensure(commandName, () => this.commands.get("help") as Command);
let command = this.commands.get(commandName) as Command;
await command.execute(interaction);
}
@ -39,9 +39,7 @@ export class UEMEloBot extends Client {
try {
this.players = [];
for (let obj of JSON.parse(fileContent)){
let p = new Player(obj.account);
if (obj.hasOwnProperty("startElo"))
p.startElo = obj.startElo;
let p = Player.Load(obj);
this.players.push(p);
console.log(`Parsed player: ${p}`);
}
@ -52,13 +50,15 @@ export class UEMEloBot extends Client {
}
savePlayersToFile(){
fs.writeFileSync(this.fileName, JSON.stringify(this.players));
fs.writeFileSync(this.fileName, JSON.stringify(this.players, null, 4));
}
async updateStartElo(){
async updatePlayers(){
for (let p of this.players){
await p.updateFullName();
await p.updateCurrentElo();
if (!p.startElo){
p.startElo = await p.fetchCurrentElo();
p.startElo = p.currentElo;
console.log(`Updated start elo for ${p}`);
}
}
@ -66,40 +66,28 @@ export class UEMEloBot extends Client {
}
async addPlayer(gameName: string, tag: string){
let player = await Player.Create(gameName, tag) as Player;
let player = await Player.TryCreateFrom(gameName, tag) as Player;
if (player === undefined)
return;
if (this.players.find(p => p.account.puuid === player.account.puuid)){
if (this.players.find(p => p.puuid === player.puuid)){
console.error(`${player} already registered!`);
return;
}
this.players.push(player);
console.log(`Added ${player}!`);
this.savePlayersToFile();
}
async loadCommands(){
const commandFiles = fs.readdirSync(path.join(__dirname, "commands")).filter(file => file.endsWith('.js'));
for (const file of commandFiles){
const module = await import(`./commands/${file}`);
const cmd = module.default;
if (cmd instanceof Command)
this.commands.set(cmd.data.name, cmd);
}
}
async onReady(readyClient: Client<true>){
console.log(`Logged in as ${readyClient.user.tag}`);
}
stop(){
this.destroy().then(() => {
console.log("Bot stopped!");
console.log("Logged out!");
process.exit(0);
});
}

@ -1,4 +1,6 @@
import {Interaction, SlashCommandBuilder} from "discord.js";
import {Collection, Interaction, SlashCommandBuilder} from "discord.js";
import fs from "node:fs";
import path from "node:path";
export abstract class Command {
data: SlashCommandBuilder
@ -9,3 +11,15 @@ export abstract class Command {
abstract execute(interaction: Interaction): Promise<void>;
}
export async function loadCommands(){
let commands = new Collection<string, Command>();
const commandFiles = fs.readdirSync(path.join(__dirname, "commands")).filter(file => file.endsWith('.js'));
for (const file of commandFiles){
const module = await import(`./commands/${file}`);
const cmd = module.default;
if (cmd instanceof Command)
commands.set(cmd.data.name, cmd);
}
return commands;
}

@ -0,0 +1,15 @@
import {Interaction} from "discord.js";
import {Command} from "../command";
class Add extends Command {
constructor() {
super("add", "add a player");
}
async execute(interaction: Interaction) {
if (interaction.isRepliable())
await interaction.reply("Pong!");
}
}
export default new Add();

@ -1,4 +1,6 @@
import {REST, Routes} from 'discord.js';
import {loadCommands} from "./command";
require("dotenv").config();
let token = process.env["DISCORD_TOKEN"] as string;
@ -7,4 +9,7 @@ let guildId = process.env["GUILD_ID"] as string;
const rest = new REST().setToken(token);
rest.put(Routes.applicationGuildCommands(clientId, guildId), {body: [require("./commands/ping").data.toJSON()]});
loadCommands().then(async commands => {
let cmdData = Array.from(commands.values()).map(cmd => cmd.data.toJSON());
await rest.put(Routes.applicationGuildCommands(clientId, guildId), {body: cmdData});
});

@ -1,11 +1,7 @@
import {Command} from "./command";
require("dotenv").config();
import {UEMEloBot} from "./bot";
import readline from "readline";
import Ping from "./commands/ping";
readline.createInterface({input: process.stdin}).on('line', async line => {
if (line == "stop")
client.stop();

@ -5,25 +5,72 @@ const riotAPI = new RiotAPI(process.env["RIOT_API_KEY"] as string);
export class Player {
account: AccountDTO
puuid: string
gameName?: string
tagLine?: string
startElo?: Elo
currentElo?: Elo
constructor(account: AccountDTO) {
this.account = account;
constructor(puuid: string) {
this.puuid = puuid;
}
async fetchCurrentElo(): Promise<Elo | undefined> {
let entries = await riotAPI.league.getEntriesBySummonerId({
region: PlatformId.EUW1,
summonerId: (await riotAPI.summoner.getByPUUID({
region: PlatformId.EUW1,
puuid: this.account.puuid
})).id
static Load(raw: any): Player {
let p = new Player(raw.puuid);
p.startElo = raw.startElo;
p.gameName = raw.gameName;
p.tagLine = raw.tagLine;
return p;
}
static async TryCreateFrom(gameName: string, tagLine: string) {
let account: AccountDTO;
try {
account = await riotAPI.account.getByRiotId({
region: PlatformId.EUROPE,
gameName: gameName,
tagLine: tagLine
});
} catch (error) {
console.error(`Riot ID not found: ${gameName}#${tagLine}!`);
return;
}
let p = new Player(account.puuid);
p.gameName = account.gameName;
p.tagLine = account.tagLine;
await p.updateCurrentElo();
p.startElo = p.currentElo;
return p;
}
async updateFullName(){
const account = await riotAPI.account.getByPUUID({
region: PlatformId.EUROPE,
puuid: this.puuid
});
this.gameName = account.gameName;
this.tagLine = account.tagLine;
}
async updateCurrentElo() {
let entries;
try {
entries = await riotAPI.league.getEntriesBySummonerId({
region: PlatformId.EUW1,
summonerId: (await riotAPI.summoner.getByPUUID({
region: PlatformId.EUW1,
puuid: this.puuid
})).id
});
} catch (error){
console.error(await(error as Response).json());
return;
}
let soloQ = entries.find(e => e.queueType == "RANKED_SOLO_5x5");
if (soloQ && ((soloQ.wins + soloQ.losses) >= 5)){
return {
this.currentElo = {
tier: soloQ.tier,
rank: soloQ.rank,
points: soloQ.leaguePoints
@ -32,24 +79,17 @@ export class Player {
}
toString() {
return `${this.account.gameName}#${this.account.tagLine}`;
return `${this.gameName}#${this.tagLine}`;
}
static async Create(gameName: string, tag: string) {
let account: AccountDTO;
try {
account = await riotAPI.account.getByRiotId({
region: PlatformId.EUROPE,
gameName: gameName,
tagLine: tag
});
} catch (error) {
console.error(`Riot ID not found: ${gameName}#${tag}!`);
return;
// noinspection JSUnusedGlobalSymbols
toJSON(){
return {
puuid: this.puuid,
gameName: this.gameName,
tagLine: this.tagLine,
startElo: this.startElo
}
let p = new Player(account);
p.startElo = await p.fetchCurrentElo();
return p;
}
}

Loading…
Cancel
Save