From 8e156d61c1834da12e9116f2cdc4255d3c5e97ae Mon Sep 17 00:00:00 2001 From: Rene Kievits Date: Sun, 22 Jun 2025 18:05:52 +0200 Subject: [PATCH] update --- .env.example | 1 + src/discord/discordClient.js | 13 +++++++++++- src/features/blacklist.js | 2 ++ src/features/showRoleMembers.js | 35 +++++++++++++++++++++++++++++++++ src/tasks/eventReminder.js | 26 +++++++++++------------- 5 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 src/features/showRoleMembers.js diff --git a/.env.example b/.env.example index bc5a4e5..aef5097 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ BOT_TOKEN= CLIENT_ID= +SERVER_ID= diff --git a/src/discord/discordClient.js b/src/discord/discordClient.js index 8fc328a..a2a26c0 100644 --- a/src/discord/discordClient.js +++ b/src/discord/discordClient.js @@ -35,6 +35,8 @@ const { const { startBirthdayCheckCron } = require('../tasks/checkBirthday') const { startEventCheckCron } = require('../tasks/eventReminder') +const { showRoleMembers } = require("../features/showRoleMembers") + const rest = new REST({ version: '10' }).setToken(process.env.BOT_TOKEN) const client = new Client({ @@ -214,7 +216,8 @@ client.on('interactionCreate', async interaction => { } break } case 'static-delete': { - + } case 'showrole': { + await showRoleMembers(interaction) break } case 'static-show': { @@ -305,6 +308,14 @@ const connectDiscord = async () => { .setDescription('The in-game name of the player') .setRequired(true) ), + new SlashCommandBuilder() + .setName('showrole') + .setDescription('Shows all users with a given role') + .addRoleOption(option => + option.setName('role') + .setDescription('The role to look up') + .setRequired(true) + ), /* new SlashCommandBuilder() .setName('static-create') .setDescription('Create a new static with a voice and text channel just for your members.') diff --git a/src/features/blacklist.js b/src/features/blacklist.js index 251b392..1d70ea1 100644 --- a/src/features/blacklist.js +++ b/src/features/blacklist.js @@ -29,6 +29,8 @@ const createBlacklistEmbeds = (playerEntries, maxChars = 30) => { let fieldCount = 0 let pageIndex = 1 + playerEntries.sort((a, b) => a[0].localeCompare(b[0])) + playerEntries.forEach(([playerName, reason]) => { let splitReason = [] while (reason.length > maxChars) { diff --git a/src/features/showRoleMembers.js b/src/features/showRoleMembers.js new file mode 100644 index 0000000..23a007a --- /dev/null +++ b/src/features/showRoleMembers.js @@ -0,0 +1,35 @@ +const { AttachmentBuilder } = require('discord.js') + +async function showRoleMembers(interaction) { + const role = interaction.options.getRole('role') + + if (!role || !interaction.guild) { + return interaction.reply({ content: 'Invalid role or guild.', ephemeral: true }) + } + + await interaction.deferReply({ ephemeral: true }) + + // Fetch all guild members (may require enabling GUILD_MEMBERS intent) + await interaction.guild.members.fetch() + + const membersWithRole = interaction.guild.members.cache + .filter(member => member.roles.cache.has(role.id)) + .map(member => member.user.tag) + + if (membersWithRole.length === 0) { + return interaction.editReply(`No users found with the role **${role.name}**.`) + } + + const MAX_LENGTH = 2000 + let output = `Users with role **${role.name}**:\n` + membersWithRole.join('\n') + + if (output.length > MAX_LENGTH) { + const buffer = Buffer.from(membersWithRole.join('\n')) + const file = new AttachmentBuilder(buffer, { name: `${role.name}_members.txt` }) + return interaction.editReply({ content: `Too many users. See the attached file.`, files: [file] }) + } + + return interaction.editReply(output) +} + +module.exports = { showRoleMembers } diff --git a/src/tasks/eventReminder.js b/src/tasks/eventReminder.js index 40abc77..34dbf70 100644 --- a/src/tasks/eventReminder.js +++ b/src/tasks/eventReminder.js @@ -6,20 +6,17 @@ let eventCache = [] const FetchEvents = async () => { const res = await ReadEvents() - eventCache = res } -const convertToISO = (time, date) => { - const utcDate = new Date(`${date}T${time}`) - utcDate.setHours(utcDate.getHours()) - return utcDate.toISOString().split('.')[0] -} - const convertToUTC = (time) => { const [hours, minutes, seconds] = time.split(':').map(Number) const date = new Date() - date.setUTCHours(hours - 1, minutes, seconds) + + const berlinTime = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), hours, minutes, seconds)) + const berlinOffset = berlinTime.toLocaleString('en-US', { timeZone: 'Europe/Berlin', hourCycle: 'h23', hour: 'numeric' }) - hours + + date.setUTCHours(hours - berlinOffset, minutes, seconds) return date.toISOString().split('.')[0] } @@ -28,11 +25,11 @@ const isReminderTime = (eventStartUTC) => { const [eventHours, eventMinutes] = eventStartUTC.split('T')[1].split(':').map(Number) const eventStartDateTime = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), eventHours, eventMinutes)) const reminderTime = new Date(eventStartDateTime.getTime() - 15 * 60 * 1000) - console.log(now, reminderTime, eventStartDateTime) + return now >= reminderTime && now < eventStartDateTime } -const getDayOfWeek = () => new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate())).toLocaleDateString('en-US', { weekday: 'long' }) +const getDayOfWeek = () => new Date().toLocaleDateString('en-US', { timeZone: 'Europe/Berlin', weekday: 'long' }) const startEventCheckCron = async (client) => { cron.schedule('45 * * * *', async () => { @@ -53,12 +50,12 @@ const startEventCheckCron = async (client) => { const embed = new EmbedBuilder() .setTitle(event_name) - .setDescription(`${event_name} starts at **${start_time} CEST** and ends at **${end_time} CEST**. \n ${roleId ? `<@&${roleId}>` : 'No role assigned'} \n`) + .setDescription(`${event_name} starts at **${start_time} Germany Time** and ends at **${end_time} Germany Time**. \n ${roleId ? `<@&${roleId}>` : 'No role assigned'} \n`) .addFields( { name: 'Day of Week', value: day_of_week ? day_of_week : 'Daily', inline: true }, { name: 'Compare Time', - value: `[Click here to compare event time to your local time](https://www.timeanddate.com/worldclock/fixedtime.html?iso=${convertToISO(start_time, new Date().toISOString().split('T')[0])}&msg=${encodeURIComponent(event_name)})`, + value: `[Click here to compare event time to your local time](https://www.timeanddate.com/worldclock/fixedtime.html?iso=${convertToUTC(start_time)}&msg=${encodeURIComponent(event_name)})`, inline: true } ) @@ -69,7 +66,8 @@ const startEventCheckCron = async (client) => { }) } }) - cron.schedule('0 7 * * *', async () => { + + cron.schedule('0 5 * * *', async () => { for (const [_, oauthGuild] of await client.guilds.fetch()) { const guild = await oauthGuild.fetch() const channel = (await guild.channels.fetch()).find(ch => ch.name === 'reminder') @@ -90,8 +88,6 @@ const startEventCheckCron = async (client) => { }) } - - module.exports = { startEventCheckCron, }