Skip to content
This repository has been archived by the owner on Oct 12, 2024. It is now read-only.

Commit

Permalink
Context menu
Browse files Browse the repository at this point in the history
  • Loading branch information
RealEthanPlayzDev committed Feb 8, 2024
1 parent ded62ca commit 76fa2a0
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 68 deletions.
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@
"typescript": "^5.1.6"
},
"dependencies": {
"@discord-player/extractor": "^4.3.1",
"@discord-player/extractor": "^4.4.6",
"@discordjs/opus": "^0.9.0",
"@discordjs/voice": "^0.14.0",
"@prisma/client": "^5.2.0",
"@discordjs/voice": "^0.16.0",
"@prisma/client": "^5.9.1",
"@types/ms": "^0.7.32",
"axios": "^1.6.3",
"chalk": "4.0.0",
"discord-player": "6.5.0",
"discord.js": "^14.6.0",
"discord-player": "^6.6.7",
"discord.js": "^14.14.1",
"dotenv": "^16.0.3",
"holodex.js": "^2.0.5",
"libsodium-wrappers": "^0.7.10",
"moment": "^2.29.4",
"ms": "^2.1.3",
"noblox.js": "4.14.0",
"play-dl": "^1.9.6",
"noblox.js": "^4.15.1",
"play-dl": "^1.9.7",
"soundcloud-scraper": "^5.0.3",
"spotify-url-info": "^3.2.3",
"youtube-sr": "^4.3.4",
"ytdl-core": "^4.11.2"
"spotify-url-info": "^3.2.12",
"youtube-sr": "^4.3.10",
"ytdl-core": "^4.11.5"
}
}
22 changes: 22 additions & 0 deletions src/contextmenu/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type {
Awaitable,
MessageContextMenuCommandInteraction,
UserContextMenuCommandInteraction,
ContextMenuCommandBuilder,
} from "discord.js";
import type { MeteoriumClient } from "../util/MeteoriumClient";

// User context menus
export * as userinfo from "./user/UserInfo";

export type MeteoriumUserContextMenuAction = {
InteractionData: Pick<ContextMenuCommandBuilder, "toJSON">;
Callback(interaction: UserContextMenuCommandInteraction<"cached">, client: MeteoriumClient): Awaitable<any>;
Init?(client: MeteoriumClient): Awaitable<void>;
};

export type MeteoriumMessageContextMenuAction = {
InteractionData: Pick<ContextMenuCommandBuilder, "toJSON">;
Callback(interaction: MessageContextMenuCommandInteraction<"cached">, client: MeteoriumClient): Awaitable<any>;
Init?(client: MeteoriumClient): Awaitable<void>;
};
108 changes: 108 additions & 0 deletions src/contextmenu/user/UserInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { GuildMember, ContextMenuCommandBuilder, User, ApplicationCommandType } from "discord.js";
import type { MeteoriumUserContextMenuAction } from "..";
import { MeteoriumEmbedBuilder } from "../../util/MeteoriumEmbedBuilder";

export const ContextMenuAction: MeteoriumUserContextMenuAction = {
InteractionData: new ContextMenuCommandBuilder().setName("UserInfo").setType(ApplicationCommandType.User),
async Callback(interaction) {
const Embed = new MeteoriumEmbedBuilder(undefined, interaction.user);
const ParsedUser = await interaction.guild.members
.fetch(interaction.targetUser.id)
.catch(() => interaction.targetUser);

if (ParsedUser instanceof GuildMember) {
// User status and is client device parsing
let UserStatus = "Unknown";
if (ParsedUser.presence && ParsedUser.presence["status"]) {
const ClientStatus = `Desktop: ${ParsedUser.presence.clientStatus?.desktop || "N/A"} | Mobile: ${
ParsedUser.presence.clientStatus?.mobile || "N/A"
} | Web: ${ParsedUser.presence.clientStatus?.web || "N/A"}`;
if (ParsedUser.presence.status === "dnd") {
UserStatus = `do not disturb - ${ClientStatus}`;
} else {
UserStatus = `${ParsedUser.presence.status} - ${ClientStatus}`;
}
}

Embed.setDescription(String(ParsedUser))
.setTitle(ParsedUser.user.tag)
.setAuthor({
name: "Guild member",
url: `https://discordapp.com/users/${ParsedUser.user.id}`,
})
.setThumbnail(ParsedUser.user.displayAvatarURL())
.setColor(ParsedUser.displayColor ? ParsedUser.displayColor : [0, 153, 255])
.addFields([
{ name: "Status", value: UserStatus },
{ name: "UserId", value: ParsedUser.user.id },
{
name: "Joined Discord at",
value: `<t:${Math.round(ParsedUser.user.createdTimestamp / 1000)}:f>\n${
ParsedUser.user.createdAt
}\n(<t:${Math.round(ParsedUser.user.createdTimestamp / 1000)}:R>)`,
},
]);

if (ParsedUser?.joinedTimestamp) {
Embed.addFields([
{
name: "Joined this server at",
value: `<t:${Math.round(ParsedUser.joinedTimestamp / 1000)}:f>\n(<t:${Math.round(
ParsedUser.joinedTimestamp / 1000,
)}:R>)`,
},
]);
}

if (ParsedUser?.premiumSince && ParsedUser?.premiumSinceTimestamp) {
Embed.addFields([
{
name: "Server Nitro Booster",
value: `${
ParsedUser.premiumSince
? `Booster since <t:${Math.round(
ParsedUser.premiumSinceTimestamp / 1000,
)}:f> (<t:${Math.round(ParsedUser.premiumSinceTimestamp / 1000)}:R>)`
: "Not a booster"
}`,
},
]);
}

Embed.addFields([
{
name: `Roles (${
ParsedUser.roles.cache.filter((role) => role.name !== "@everyone").size
} in total without @everyone)`,
value: ParsedUser.roles.cache.filter((role) => role.name !== "@everyone").size
? (() =>
ParsedUser.roles.cache
.filter((role) => role.name !== "@everyone")
.sort((role1, role2) => role2.rawPosition - role1.rawPosition)
.map((role) => role)
.join(", "))()
: "———",
},
]);
} else if (ParsedUser instanceof User) {
Embed.setDescription(String(ParsedUser))
.setTitle(ParsedUser.tag)
.setAuthor({
name: "User",
url: `https://discordapp.com/users/${ParsedUser.id}`,
})
.setThumbnail(ParsedUser.displayAvatarURL())
.addFields([
{ name: "UserId", value: ParsedUser.id },
{
name: "Joined Discord at",
value: `<t:${Math.round(ParsedUser.createdTimestamp / 1000)}:f>\n${
ParsedUser.createdAt
}\n(<t:${Math.round(ParsedUser.createdTimestamp / 1000)}:R>)`,
},
]);
}

return await interaction.reply({ embeds: [Embed] });
},
};
30 changes: 22 additions & 8 deletions src/events/ready.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { MeteoriumEvent } from ".";
import { ActivityType, REST, Routes, codeBlock } from "discord.js";
import {
ActivityType,
REST,
RESTPostAPIChatInputApplicationCommandsJSONBody,
RESTPostAPIContextMenuApplicationCommandsJSONBody,
Routes,
codeBlock,
} from "discord.js";
import moment from "moment";
import { inspect } from "util";
import { MeteoriumEmbedBuilder } from "../util/MeteoriumEmbedBuilder";
Expand All @@ -8,20 +15,27 @@ export const Event: MeteoriumEvent<"ready"> = {
async Callback(client) {
const readyNS = client.Logging.GetNamespace("Events/ready");
const StartTime = moment().format("DD-MM-YYYY hh:mm:ss:SSS A Z");
const CommandsMapped = client.Commands.map((Command) => Command.InteractionData.toJSON());

readyNS.info("Registering global slash commands at Discord");
await client.application.commands.set(CommandsMapped); // Global slash commands
const MergedApplicationCommands: Array<
RESTPostAPIChatInputApplicationCommandsJSONBody | RESTPostAPIContextMenuApplicationCommandsJSONBody
> = [];
client.Commands.forEach((command) => MergedApplicationCommands.push(command.InteractionData.toJSON()));
client.ContextMenuActions.forEach((contextMenuAction) =>
MergedApplicationCommands.push(contextMenuAction.InteractionData.toJSON()),
);

readyNS.info("Registering guild slash commands at Discord");
readyNS.info("Registering global application commands at Discord");
await client.application.commands.set(MergedApplicationCommands); // Global application commands

readyNS.info("Registering guild application commands at Discord");
const Rest = new REST({ version: "10" });
Rest.setToken(client.token);
client.Config.InteractionFirstDeployGuildIds.forEach(async (guildId) => {
readyNS.info(`Registering guild slash commands -> ${guildId}`);
readyNS.info(`Registering guild application commands -> ${guildId}`);
await Rest.put(Routes.applicationGuildCommands(client.Config.DiscordApplicationId, guildId), {
body: CommandsMapped,
body: MergedApplicationCommands,
}).catch((e) => {
readyNS.error(`Failed while registering guild slash commands for guild ${guildId}:\n${e}`);
readyNS.error(`Failed while registering guild application commands for guild ${guildId}:\n${e}`);
});
});

Expand Down
34 changes: 25 additions & 9 deletions src/util/MeteoriumClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PrismaClient } from "@prisma/client";

import * as Commands from "../commands";
import * as Events from "../events";
import * as ContextMenuActions from "../contextmenu";
import { MeteoriumLogging } from "./MeteoriumLogging";

const ParseDotEnvConfig = () => {
Expand All @@ -31,6 +32,10 @@ const ParseDotEnvConfig = () => {
export class MeteoriumClient extends Client<true> {
public Config = ParseDotEnvConfig();
public Commands = new Collection<string, Commands.MeteoriumCommand>();
public ContextMenuActions = new Collection<
string,
ContextMenuActions.MeteoriumUserContextMenuAction | ContextMenuActions.MeteoriumMessageContextMenuAction
>();
public Database = new PrismaClient();
public DiscordPlayer = new Player(this);
public LyricsExtractor = lyricsExtractor(this.Config.GeniusAPIKey);
Expand All @@ -44,6 +49,18 @@ export class MeteoriumClient extends Client<true> {
loginNS.info("Loading discord-player default extractors");
this.DiscordPlayer.extractors.loadDefault();

loginNS.info("Registering events");
for (const [Name, { Event }] of Object.entries(Events)) {
loginNS.debug(`Registering event -> ${Name} ${Event}`);
if (Event.Once) {
// @ts-ignore
this.once(Name, (...args) => Event.Callback(this, ...args));
} else {
// @ts-ignore
this.on(Name, (...args) => Event.Callback(this, ...args));
}
}

loginNS.info("Registering commands");
this.Commands.clear();
for (const [Name, { Command }] of Object.entries(Commands)) {
Expand All @@ -55,16 +72,15 @@ export class MeteoriumClient extends Client<true> {
this.Commands.set(Name, Command);
}

loginNS.info("Registering events");
for (const [Name, { Event }] of Object.entries(Events)) {
loginNS.debug(`Registering event -> ${Name} ${Event}`);
if (Event.Once) {
// @ts-ignore
this.once(Name, (...args) => Event.Callback(this, ...args));
} else {
// @ts-ignore
this.on(Name, (...args) => Event.Callback(this, ...args));
loginNS.info("Registering context menu actions");
this.ContextMenuActions.clear();
for (const [Name, { ContextMenuAction }] of Object.entries(ContextMenuActions)) {
loginNS.debug(`Registering context menu action -> ${Name} ${ContextMenuAction}`);
if (ContextMenuAction.Init) {
loginNS.debug(`Running command init -> ${Name} ${ContextMenuAction}`);
await ContextMenuAction.Init(this);
}
this.ContextMenuActions.set(Name, ContextMenuAction);
}

// Shard logging
Expand Down
Loading

0 comments on commit 76fa2a0

Please sign in to comment.