diff --git a/example.env b/example.env index 2935b3b..7838f53 100644 --- a/example.env +++ b/example.env @@ -10,6 +10,9 @@ MONGO_DB_NAME = NAME # Register a bot here: https://discord.com/developers BOT_TOKEN = TOKEN +# Hypixel API Key | /api new on hypixel +HYPIXEL_API_KEY = KEY + # CalmChatBot CALM_BOT_IP = IP CALM_BOT_PORT = PORT diff --git a/src/commands/staff.ts b/src/commands/staff.ts new file mode 100644 index 0000000..759c7b1 --- /dev/null +++ b/src/commands/staff.ts @@ -0,0 +1,57 @@ +import { GuildEmoji, Message, MessageEmbed } from "discord.js"; +import Client from "../structures/Client"; +import HypixelApi from "../utils/api/HypixelApi"; +import { IPlayer } from "../utils/api/Interfaces" + +module.exports = { + name: "staff", + description: "Displays all online Calm Guild Staff", + category: "Utility", + usage: "staff", + run: async function run(client: Client, message: Message) { + const guildStaff = await HypixelApi.getGuildStaff(); + if (!guildStaff) { + return message.channel.send("Error: To prevent ratelimiting this command is on cooldown. Please wait a little bit and then try again."); + } + + let onlineEmote: GuildEmoji | string, offlineEmote: GuildEmoji | string; + if(message.guild.id === "501501905508237312") { + onlineEmote = client.emojis.cache.find(e => e.id === "805656441704546324") + offlineEmote = client.emojis.cache.find(e => e.id === "805656538127401000"); + } else { + onlineEmote = "🟢"; + offlineEmote = "🔴"; + } + + const tmp = await message.channel.send("Please wait while we fetch data from the api. This could take some time."); + + let online = Array(); + let offline = Array(); + + for (const member in guildStaff) { + const player = await HypixelApi.getPlayerFromUUID(guildStaff[member].uuid); + + if (player.lastLogin > player.lastLogout) { + online.push(player); + } else { + offline.push(player); + } + } + + let embedDesc = ""; + online.forEach((player) => { + embedDesc += "`" + player.displayname + "` " + onlineEmote + "\n"; + }) + offline.forEach((player) => { + embedDesc += "`" + player.displayname + "` " + offlineEmote + "\n"; + }) + + + const embed = new MessageEmbed(); + embed.setTitle("Guild Staff"); + embed.setDescription(embedDesc); + await tmp.delete(); + await message.channel.send(embed) + }, +}; + diff --git a/src/data/calm/staffuuids.ts b/src/data/calm/staffuuids.ts new file mode 100644 index 0000000..0d33994 --- /dev/null +++ b/src/data/calm/staffuuids.ts @@ -0,0 +1,14 @@ +export const staffUUID = [ + "3a3c9d90-ab98-47b4-bc5d-73196a65e1d9", // hopez + "5791af76-b724-4f9b-90e7-e7869f1e1aa0", // ohLaike + "6984b889-5ff1-4e10-b549-76751169c91a", // Guitarking257 + "78d0f4bb-658e-4e9c-96ad-be5742a65c94", // Partaken + "3c36c369-c7fc-4305-8fd2-3055c9024d9c", // kiyeo + "c1f69253-3be0-4aae-b37d-ab100e5d3af6", // minik_ + "433b142d-bf96-4db0-9f16-10f7f7912565", // Nitwu + "3028e941-3ecc-4d2b-afed-bbdadc8aaa75", // Purplest + "79990cdf-6357-48f7-8437-565102010d74", // SkillBeatsAll + "a919ee94-adfc-4f0a-af98-20d79409b86d", // InstinctChan + "bf412996-c1e4-424b-880d-1d5788628e95", // Dayfruits + "5ef697d9-35e1-4fe8-a3bb-5a2715cfb02b", // myopic +]; \ No newline at end of file diff --git a/src/utils/api/HypixelApi.ts b/src/utils/api/HypixelApi.ts new file mode 100644 index 0000000..8bbf0ce --- /dev/null +++ b/src/utils/api/HypixelApi.ts @@ -0,0 +1,59 @@ +if (process.env.NODE_ENV !== "production") require("dotenv").config(); +import axios from "axios"; +import * as Interface from "../api/Interfaces"; +const KEY = process.env.HYPIXEL_API_KEY; +const CALM_GUILD_ID = "5af718d40cf2cbe7a9eeb063"; + +let APIUsage = 0; +let APILastUsed = 0; + +export default { + getGuildStaff: async function (): Promise { + if (!canUseKey()) return undefined; + const res = await axios.get(`https://api.hypixel.net/guild?key=${KEY}&id=${CALM_GUILD_ID}`); + if (res.status !== 200) return undefined; + + const guild = res.data.guild; + let guildStaffRanks = []; + + guild.ranks.forEach((rank) => { + if (rank.priority >= 4) { + guildStaffRanks.push(rank.name); + } + }); + + let staffMembers = []; + (guild.members as Interface.IGuildMember[]).forEach((member) => { + if (guildStaffRanks.includes(member.rank) || member.rank === "Guild Master") staffMembers.push(member); + }); + + return staffMembers as Interface.IGuildMember[]; + }, + + getPlayerFromUUID: async function (uuid: string): Promise { + if(!canUseKey()) return undefined; + const res = await axios.get(`https://api.hypixel.net/player?key=${KEY}&uuid=${uuid}`); + if(res.status !== 200) return undefined; + return res.data.player; + }, +}; + + + +// Make sure we don't get ratelimited because we love rate limits +function canUseKey(): boolean { + const date = new Date(); + if (APILastUsed < date.getMinutes()) { + APIUsage = 1; + APILastUsed = date.getMinutes(); + return true; + } else { + if (APIUsage > 120) { + return false; + } else { + APIUsage++; + return true; + } + } +} + diff --git a/src/utils/api/Interfaces.ts b/src/utils/api/Interfaces.ts new file mode 100644 index 0000000..d8e148a --- /dev/null +++ b/src/utils/api/Interfaces.ts @@ -0,0 +1,14 @@ +export interface IGuildMember{ + uuid: string, + rank: string, + joined: number, + questParticipation: number, + expHistory: Record +} + +export interface IPlayer { + displayname: string, + uuid: string, + lastLogin: number, + lastLogout: number +} \ No newline at end of file