From f3fe5e400cffc846ded3fb481e8d49a86385ddf2 Mon Sep 17 00:00:00 2001 From: Wolfdragon24 <31204305+Wolfdragon24@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:54:17 +1000 Subject: [PATCH] Update Production Bot from QA Bot (#202) * migrate from insou api to circles for the handbook commands (#128) * migrate from insou api to circles for the handbook commands * remove trailing forward slash in handbook.json * handbook: the handbook is fixed * Update handbook.js commented out a console.log --------- Co-authored-by: tunein Co-authored-by: zcDay1 <113964162+zcDay1@users.noreply.github.com> * prettier formatted * chore(deps): update `renovate` config * chore(deps): update docker/build-push-action action to v4 (#134) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Projects description command feature (#145) * projects-descriptions v1 commit * project-descriptions command v2 commit * linting fixes for project-descriptions.js, and for handbook.js --------- Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> * disable annoying carrotboard pins * rolesPermOverride command is a script or one-time use command to attach every course role with permissions to view and send messages in any text channel with identical name. Please review and test before merging * Revert "rolesPermOverride command is a script or one-time use command to attach every course role with permissions to view and send messages in any text channel with identical name. Please review and test before merging" This reverts commit 2f59c71119d3fbeed31bed148a6e46a8c7f21aa2. * rolesPermOverride command (#152) * rolesPermOverride command is a script or one-time use command to attach every course role with permissions to view and send messages in any text channel with identical name. Please review and test before mergin * BUGGY CODE but still progress over the previous commit, I will come back this evening to fix * rolesPermOverride command: now admin-only command, and I've tested it for various cases regarding if a channel exists, if a role exists for a channel that doesnt exist, if there are two channels with the same name as a role and vice versa, and it works without error --------- Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> * Roles perm override (#153) * rolesPermOverride command is a script or one-time use command to attach every course role with permissions to view and send messages in any text channel with identical name. Please review and test before mergin * BUGGY CODE but still progress over the previous commit, I will come back this evening to fix * rolesPermOverride command: now admin-only command, and I've tested it for various cases regarding if a channel exists, if a role exists for a channel that doesnt exist, if there are two channels with the same name as a role and vice versa, and it works without error * course.js: removed code to create individual user permission overwrites in each channel --------- Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> * Project descriptions (#154) * project-descriptions.js: updated course descriptions written by the directors for 2023 levelling up with Projects Fair Day, and the discord bot CTF flag easter egg entry under this command included too for this event. * made messages ephemeral to prevent chat from being spammed by users. And got rid of link embeds in the messages. * lint update --------- Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> * Dev/course channel fix 3 (#158) * course-chat-fix-2, make new roles where there arent any in /rolespermoverride and also remove individual permission overwrites, and also updates to /course join to catch when there doesn't exist a role for a course and also /course leave to attempt to remove individual permission overwrites along with removing course role PLEASE TEST THOROUGHLY AND INSPECT CODE THOROUGHLY. I wrote this ASAP and haven't got time to properly review it. * Modified functions for course channel fixes * Check for if user only has read perms for overwrite replacing and fix looping over members * Fix to functionality of iteration and editing roles * Fix to initial working state * Fix linting * Additional fixes to ordering and component operations to remove role and individual permissions correctly * Appended filter for both view only perms and view + send messages perms --------- Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> Co-authored-by: Wolfdragon24 * dev/course-channel-fix-5 (#160) * course-chat-fix-2, make new roles where there arent any in /rolespermoverride and also remove individual permission overwrites, and also updates to /course join to catch when there doesn't exist a role for a course and also /course leave to attempt to remove individual permission overwrites along with removing course role PLEASE TEST THOROUGHLY AND INSPECT CODE THOROUGHLY. I wrote this ASAP and haven't got time to properly review it. * Modified functions for course channel fixes * Check for if user only has read perms for overwrite replacing and fix looping over members * Fix to functionality of iteration and editing roles * Fix to initial working state * Fix linting * Additional fixes to ordering and component operations to remove role and individual permissions correctly * Appended filter for both view only perms and view + send messages perms * Appended single channel mode for permissions override * Appended check command for role permissions * Resolved merge conflicts in dev/course-channel-fix-4 --------- Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> Co-authored-by: Wolfdragon24 * Update rolesPermOverride.js double equals updated to triple equals on line 156 * Course Command Fixing - Collection Null Value Error (#162) * Accounting for non-channel returns associated to snowflakes * Utilise cache directly as fetch falls back to a cache call anyway * Dev/upgrade handbook url (#164) * Upgraded handbook url in config.json to use 2024. Also fixed incorrect url links in the handbook.js command. * Fixed eslint warnings * Fixed bug for courses that do not yet have an offering term (Default: "None") (#165) * Upgraded handbook url in config.json to use 2024. Also fixed incorrect url links in the handbook.js command. * Fixed eslint warnings * Fixed equivalent courses urls being listed * Implementation of the Lunch Buddy feature (#167) * update: checking if perms work * Chron job set for every minute, basic embed added and structure for the locations and sub locations created * Updated README * Implemented area voting system * Ran linting and prettier for current changes * Appending location poll for given area, and vote counting for both area and locations * Implemented functional voting system for area and location, creating thread upon completion of set * Used await and cleaned up a bit of code, thread now adds all voters not only the ones who voted for the winning area * Lint fix * Removed promises and adjusted placement of vote function calls * Adjusted thread users, append location vote pings * Linting fixes * Locations Update * Adds "any" option and append additional vote info * Appended code for live run timing * Update to use config file * Allow disabling of feature without editing code and disable * Minor adjustment to readme and npm commands * Appended clarifying comment regarding edge case of only any votes --------- Co-authored-by: mi-mott <98304083+mi-mott@users.noreply.github.com> * [DISC-107] Adding csesocLinks to get CSESoc related links (#170) * completed csesocLinks command * linting * Refactor execute function to use arrow functions * linting * [DISC-109] Adding bot-status for events and member count (#169) * Adding bot-status for events and member count * Fixing lint errors * Adding fixes to how member count is calculated --------- Authored-by: Eric * Update dependency nodemailer to v6.9.9 [SECURITY] (#168) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency axios to v0.28.0 [SECURITY] (#166) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency yaml to v2.2.2 [security] (#147) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency dotenv to v16 (#141) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update actions/checkout action to v4 (#157) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency discordjs-button-pagination to v3 (#140) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Remove unused discord-tictactoe dependency and updated canvas (#173) * fix(deps): update weekly patch updates (#142) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency @discordjs/builders to v1 (#135) * Update dependency @discordjs/builders to v1 * Update to project description choices to utilise object structure (Fix to erroring on dependency update) --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Wolfdragon24 Co-authored-by: Wolfdragon24 <31204305+Wolfdragon24@users.noreply.github.com> * fix(deps): update dependency discord.js to v14 (#139) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update to fix v14 breaking changes (#176) * chore(deps): update actions/setup-node action to v4 (#172) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Nitpick refactor for courses command (#126) * I can finally sleep now * Implementation of suggested modifications * Modification to ensure correct regex form for case-insensitive match --------- Co-authored-by: Wolfdragon24 * fix(deps): update dependency mathjs to v12 (#182) * chore(deps): update docker-github-actions * fix(deps): update dependency mathjs to v12 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency axios to v1 (#181) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency @discordjs/rest to v2 (#179) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency eslint-config-prettier to v9 (#175) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency nodemon to v3 (#183) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update node.js to v20 (#171) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency mathjs to v13 (#184) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * DISC-119-unielectives-review (#188) * working unilectives review * added warning for chartjs dependency * changed to ephemeral reply * removed unneccesary libraries for chartjs * hopefully no npm package conflict dying * npm packages should be fixed * changed web scraper package for robustness * linting * fixed yaml npm issue * JSCode docu * linting * revert config files to og * package-json changes --------- Co-authored-by: addison * [DISC-120] Update eslint dependency and nodejs to v20 * chore(deps): update dependency eslint to v9 * Update to eslint and babel/eslint-parser * Update lock file * Fixes for linting * Modifications to ignore node modules and consider all other files for linting * Force update of node to version 20 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Wolfdragon24 * [DISC-120] Update to prettier and corresponding eslint plugin * chore(deps): update dependency prettier to v3 * Update prettier config to use auto end of line setting * Linting and prettifying * Prettier fixes and running format * Prettier fix * Fix by consolidating updates to prettier and eslint plugin --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Wolfdragon24 * chore(deps): lock file maintenance (#186) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update weekly minor updates (#143) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [DISC-120] Fix to renovate.json file (#190) * [DISC-120] Declare file type for requiring data (#192) * [DISC-120] Adjust data type for file (#193) * Declare file type for requiring data * Use json as opposed to js data file * [DISC-120] Move to using fs for configuration (#194) * Declare file type for requiring data * Use json as opposed to js data file * Replace require to use reading file with fs * Move file to config * Fix spelling error * Append setup command for puppeteer browser * Downloading dependencies and requirements for puppeteer * Modification to installation order * Affirm installation * Revert prior changes and set to use alternate folder for chromium instance * Manually ignore puppeteer config file in eslint * Attempt fix to eslint hanging * [DISC-117] Adding travelguides command (#187) * initial travelguide add subcommand * fixing formatting * fixing syntax error * added get function * linting * completed travelguide command * linting * adding deletion confirmation * linting * migrating travelguide.json to postgres * linting * linting --------- Co-authored-by: Jessica Xu * Modify location and method for chromium install * Alter setup to use chromium base * Update to puppeteer version * Replace secondary node image with puppeteer * Fix capitalisation inconsistency and assume permission set * Reappend entrypoint permission modification * Reset user from image setup * Attempt return to puppeteer user after setup * [DISC-110] Adding Course Chats 1-year "Subscription" (#191) * Added database implementation of user roles when assigned and removed * Added time checking function for expired user_roles and added time assigned column to user_roles table * Added on ready file with cron.js to perform daily check of old_roles * Adding new package cron for scheduling * fixing lint issues * Fixing prettier issues * Package changes * Restoring develop package lock.json and fixing db_ready * Moving guild and roles out of for loop to remove redundant fetching * [DISC-121] Implement Logging for User Rejoining (#199) * Implementation of user join and leave logging and admin command to facilitate replacing old db table * Complete implementation of rejoin notices * Fix to incorrect conflict resolution commit --------- Co-authored-by: imagine-hussain <93496985+imagine-hussain@users.noreply.github.com> Co-authored-by: tunein Co-authored-by: zcDay1 <113964162+zcDay1@users.noreply.github.com> Co-authored-by: AcdSoftCo <106219586+AcdSoftCo@users.noreply.github.com> Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: abiramen <7523422+abiramen@users.noreply.github.com> Co-authored-by: Bigbugman <101852152+Bigbugman@users.noreply.github.com> Co-authored-by: Abraham Assariparambil Earnest <44077482+abe123442@users.noreply.github.com> Co-authored-by: mi-mott <98304083+mi-mott@users.noreply.github.com> Co-authored-by: chlowoee <98923921+chlowoee@users.noreply.github.com> Co-authored-by: ericwu2205 <143063143+ericwu2205@users.noreply.github.com> Co-authored-by: XenocidePC <34413724+XenocidePC@users.noreply.github.com> Co-authored-by: h34312575s <134785889+h34312575s@users.noreply.github.com> Co-authored-by: addison Co-authored-by: Jessica Xu --- commands/admin.js | 85 +++---------------------------------- events/guildMemberAdd.js | 34 +++++++++++++++ events/guildMemberRemove.js | 15 +++++++ lib/database/database.js | 57 ++++++++++++++++++++++++- 4 files changed, 111 insertions(+), 80 deletions(-) create mode 100644 events/guildMemberAdd.js create mode 100644 events/guildMemberRemove.js diff --git a/commands/admin.js b/commands/admin.js index cbb5513e..bea9f98f 100644 --- a/commands/admin.js +++ b/commands/admin.js @@ -2,28 +2,7 @@ const { SlashCommandBuilder } = require("@discordjs/builders"); const { Permissions } = require("discord.js"); const COMMAND_KICKUNVERIFIED = "kickunverified"; -const COMMAND_MIGRATE = "migratecourses"; -const COMMAND_REMOVECOURSEROLES = "nukeremovecourseroles"; - -// yeah i know this code is copy pasted from the other file -// but whatever, the migration command is temporary! -const is_valid_course = (course) => { - const reg_comp_course = /^comp\d{4}$/; - const reg_math_course = /^math\d{4}$/; - const reg_binf_course = /^binf\d{4}$/; - const reg_engg_course = /^engg\d{4}$/; - const reg_seng_course = /^seng\d{4}$/; - const reg_desn_course = /^desn\d{4}$/; - - return ( - reg_comp_course.test(course.toLowerCase()) || - reg_math_course.test(course.toLowerCase()) || - reg_binf_course.test(course.toLowerCase()) || - reg_engg_course.test(course.toLowerCase()) || - reg_seng_course.test(course.toLowerCase()) || - reg_desn_course.test(course.toLowerCase()) - ); -}; +const COMMAND_DROPUSERTABLE = "dropusertable"; module.exports = { data: new SlashCommandBuilder() @@ -36,19 +15,8 @@ module.exports = { ) .addSubcommand((subcommand) => subcommand - .setName(COMMAND_MIGRATE) - .setDescription("Migrates a course role to permission overwrites.") - .addStringOption((option) => - option - .setName("course") - .setDescription("Course role to remove") - .setRequired(true), - ), - ) - .addSubcommand((subcommand) => - subcommand - .setName(COMMAND_REMOVECOURSEROLES) - .setDescription("WARNING: Removes course roles from the server."), + .setName(COMMAND_DROPUSERTABLE) + .setDescription("Deletes the user table and reliant tables."), ), async execute(interaction) { try { @@ -93,50 +61,11 @@ module.exports = { }); }); return await interaction.reply("Removed unverified members."); - } else if (interaction.options.getSubcommand() === COMMAND_MIGRATE) { - const course = interaction.options.getString("course"); - if (!is_valid_course(course)) { - return await interaction.reply("Error: invalid course."); - } - - const role = await interaction.guild.roles.cache.find( - (course_role) => course_role.name.toLowerCase() === course.toLowerCase(), - ); - - if (role === undefined) { - return await interaction.reply("Error: no role exists for course " + course); - } - - const channel = await interaction.guild.channels.cache.find( - (role_channel) => role_channel.name.toLowerCase() === role.name.toLowerCase(), - ); - - if (channel === undefined) { - return await interaction.reply("Error: no channel exists for course " + course); - } - - await interaction.deferReply(); - for (const member of role.members.values()) { - await channel.permissionOverwrites.create(member, { - VIEW_CHANNEL: true, - }); - } - return await interaction.editReply( - "Migrated course role to permission overwrites.", - ); - } else if (interaction.options.getSubcommand() === COMMAND_REMOVECOURSEROLES) { - // get all roles, and find courses which match the regex - const course_roles = await interaction.guild.roles.cache.filter((role) => - is_valid_course(role.name), - ); - - await interaction.deferReply(); - - for (const role of course_roles.values()) { - await role.delete(); - } + } else if (interaction.options.getSubcommand() === COMMAND_DROPUSERTABLE) { + const userDB = global.userDB; + await userDB.drop_table(); - return await interaction.editReply("Removed all course roles."); + return await interaction.editReply("Deleted user table."); } return await interaction.reply("Error: unknown subcommand."); diff --git a/events/guildMemberAdd.js b/events/guildMemberAdd.js new file mode 100644 index 00000000..b690bdea --- /dev/null +++ b/events/guildMemberAdd.js @@ -0,0 +1,34 @@ +const { Events } = require("discord.js"); + +const CSESOC_SERVER_ID = "693779865916276746"; +const REPORT_CHANNEL_ID = "1270283342176059443"; + +module.exports = { + name: Events.GuildMemberAdd, + once: false, + execute(member) { + /** @type {DBuser} */ + const userDB = global.userDB; + + // Get report channel + if (member.user.bot || member.user.system || member.guild.id !== CSESOC_SERVER_ID) return; + + // Get old user info before joining + userDB.get_user_info(member.id).then((user_data) => { + userDB.user_join(member.id).then((joinType) => { + if (joinType === "rejoin") { + // Fetch the channel to output details + const reportChannel = member.guild.channels.cache.get(REPORT_CHANNEL_ID); + + // Fetch formatted date values from joining and leaving events + const joinDate = user_data.joinDate.toLocaleDateString("en-AU"); + const leaveDate = user_data.leaveDate.toLocaleDateString("en-AU"); + + reportChannel.send( + `${member.user} (${member.user.tag}) has rejoined the server. [Last in server: ${leaveDate}, Last joined: ${joinDate}]`, + ); + } + }); + }); + }, +}; diff --git a/events/guildMemberRemove.js b/events/guildMemberRemove.js new file mode 100644 index 00000000..d4376905 --- /dev/null +++ b/events/guildMemberRemove.js @@ -0,0 +1,15 @@ +const { Events } = require("discord.js"); + +module.exports = { + name: Events.GuildMemberRemove, + once: false, + execute(member) { + /** @type {DBuser} */ + const userDB = global.userDB; + + // Get report channel + if (member.user.bot || member.user.system) return; + + userDB.user_leave(member.id); + }, +}; diff --git a/lib/database/database.js b/lib/database/database.js index 37f046c7..323e9440 100644 --- a/lib/database/database.js +++ b/lib/database/database.js @@ -93,7 +93,7 @@ class DBuser { console.log("Running creating user table"); await client.query("BEGIN"); const query = `CREATE TABLE users ( - userid INTEGER PRIMARY KEY, + userid TEXT PRIMARY KEY, joindate DATE NOT NULL, leavedate DATE, userleft BOOLEAN @@ -196,7 +196,7 @@ class DBuser { try { await client.query("BEGIN"); const values = [time, true, userid]; - const query = "UPDATE users SET leavedate = $1 , userleft = $2 where userid = $3"; + const query = "UPDATE users SET leavedate = $1 , userleft = $2 where userid = $3"; await client.query(query, values); await client.query("COMMIT"); @@ -215,6 +215,8 @@ class DBuser { time.setMilliseconds(0); time = time.toISOString(); + let type = "new"; + const client = await this.pool.connect(); try { await client.query("BEGIN"); @@ -227,6 +229,9 @@ class DBuser { query = "UPDATE users SET joindate=$1, userleft=$2 where userid=$3"; values = [time, false, userid]; await client.query(query, values); + + // Report rejoining user to channel + type = "rejoin"; } else { query = "INSERT INTO users (USERID, JOINDATE, LEAVEDATE, USERLEFT) VALUES ($1,$2,$3,$4)"; @@ -241,6 +246,40 @@ class DBuser { client.release(); // console.log("Client released successfully.") } + + return type; + } + + async get_user_info(userid) { + const client = await this.pool.connect(); + let info = null; + + try { + await client.query("BEGIN"); + + const query = "select * from users where userid = $1"; + const values = [userid]; + const result = await client.query(query, values); + + if (result.rows.length != 0) { + const row = result.rows[0]; + + info = { + userId: row["userid"], + joinDate: row["joindate"], + leaveDate: row["leavedate"], + userLeft: row["userleft"], + }; + } + } catch (ex) { + console.log(`An unexpected error occurred: ${ex}`); + } finally { + await client.query("ROLLBACK"); + client.release(); + // console.log("Client released successfully.") + } + + return info; } // Adding a user role @@ -477,6 +516,20 @@ class DBuser { client.release(); } } + + async deleteUsers() { + // Temporary - delete after use + const client = await this.pool.connect(); + try { + // Query to delete users who have left the server + const query = `DROP TABLE users CASCADE;`; + await client.query(query); + } catch (error) { + console.error(error); + } finally { + client.release(); + } + } } module.exports = {