Give member Plus Server role on join

This commit is contained in:
Kalle
2022-08-07 10:27:13 +03:00
parent e04f573029
commit 627fae49b1
5 changed files with 443 additions and 386 deletions

View File

@@ -1,5 +1,5 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { GuildMemberRoleManager } from "discord.js";
import { CacheType, CommandInteraction, GuildMember } from "discord.js";
import ids from "../ids";
import type { BotCommand } from "../types";
import { isPlusTierRoleId, plusTierToRoleId, usersWithAccess } from "../utils";
@@ -15,43 +15,74 @@ export const accessCommand: BotCommand = {
"Get the corresponding Plus Server membership role if you have access"
),
execute: async ({ interaction }) => {
const { users } = await usersWithAccess();
const usersPlusTier = users[interaction.user.id];
await givePlusRoleToMember({
interaction,
member: interaction.member as GuildMember,
});
},
};
if (!usersPlusTier) {
return interaction.reply({
content: "You currently don't have access",
ephemeral: true,
});
}
export async function givePlusRoleToMember({
interaction,
member,
}: {
interaction?: CommandInteraction<CacheType>;
member: GuildMember;
}) {
const { users } = await usersWithAccessCached();
const usersPlusTier = users[member.id];
const targetRoleId = plusTierToRoleId(usersPlusTier);
if (!targetRoleId) {
throw new Error(`No role for plus tier ${usersPlusTier}`);
}
if (!usersPlusTier && interaction) {
return interaction.reply({
content: "You currently don't have access",
ephemeral: true,
});
}
const roleManager = interaction.member?.roles as GuildMemberRoleManager;
const usersRoleIds = roleManager.cache.map((r) => r.id);
const alreadyHasRole = usersRoleIds.some((id) => id === targetRoleId);
const targetRoleId = plusTierToRoleId(usersPlusTier);
if (!targetRoleId) {
throw new Error(`No role for plus tier ${usersPlusTier}`);
}
if (alreadyHasRole) {
return interaction.reply({
content: `You have access to +${usersPlusTier} and already have the role for it`,
ephemeral: true,
});
}
const roleManager = member.roles;
const usersRoleIds = roleManager.cache.map((r) => r.id);
const alreadyHasRole = usersRoleIds.some((id) => id === targetRoleId);
const roleIdsToDelete = usersRoleIds.filter(isPlusTierRoleId);
if (alreadyHasRole && interaction) {
return interaction.reply({
content: `You have access to +${usersPlusTier} and already have the role for it`,
ephemeral: true,
});
}
for (const roleIdToDelete of roleIdsToDelete) {
await roleManager.remove(roleIdToDelete);
}
const roleIdsToDelete = usersRoleIds.filter(isPlusTierRoleId);
await roleManager.add(targetRoleId);
for (const roleIdToDelete of roleIdsToDelete) {
await roleManager.remove(roleIdToDelete);
}
await roleManager.add(targetRoleId);
if (interaction) {
return interaction.reply({
content: `Gave the role giving access to +${usersPlusTier}`,
ephemeral: true,
});
},
};
}
}
let cachedAt: Date | null = null;
let usersWithAccessCache: ReturnType<typeof usersWithAccess> | null = null;
async function usersWithAccessCached() {
// fetch fresh data every hour because votings end at the hour
if (
!cachedAt ||
!usersWithAccessCache ||
cachedAt.getHours() !== new Date().getHours()
) {
cachedAt = new Date();
usersWithAccessCache = usersWithAccess();
}
return usersWithAccessCache;
}

View File

@@ -0,0 +1,9 @@
import { GuildMember } from "discord.js";
import { givePlusRoleToMember } from "./commands/access";
import ids from "./ids";
export async function handleMemberJoin(member: GuildMember) {
if (member.guild.id !== ids.guilds.plusServer) return;
await givePlusRoleToMember({ member });
}

View File

@@ -1,13 +1,13 @@
// Require the necessary discord.js classes
import { Client, Intents } from "discord.js";
import { Client, GatewayIntentBits } from "discord.js";
import "dotenv/config";
import invariant from "tiny-invariant";
import { commandsMap } from "./commands";
import { handleMemberJoin } from "./handleMemberJoin";
invariant(process.env["BOT_TOKEN"], "DISCORD_TOKEN must be set");
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS],
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers],
});
client.once("ready", () => {
@@ -15,6 +15,8 @@ client.once("ready", () => {
console.log("Ready!");
});
client.on("guildMemberAdd", handleMemberJoin);
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;

File diff suppressed because it is too large Load Diff

View File

@@ -7,14 +7,13 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@discordjs/builders": "^0.15.0",
"@discordjs/rest": "^0.5.0",
"discord-api-types": "^0.36.0",
"discord.js": "^13.8.1",
"@discordjs/rest": "^1.0.1",
"discord-api-types": "^0.37.1",
"discord.js": "^14.1.2",
"dotenv": "^16.0.1",
"tiny-invariant": "^1.2.0",
"ts-node": "^10.8.1",
"tsconfig-paths": "^4.0.0",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.0",
"typescript": "^4.7.4"
}
}