Best JavaScript code snippet using fast-check-monorepo
index.js
Source:index.js
1const DiscordJs = require("discord.js"),2 fs = require("fs/promises"),3 path = require("path"),4 Rest = require("@discordjs/rest"),5 Exception = require("../logging/exception"),6 Log = require("../logging/log"),7 Notify = require("../notify"),8 settings = require("../../settings"),9 Warning = require("../logging/warning"),10 discord = new DiscordJs.Client({11 intents: [12 DiscordJs.IntentsBitField.Flags.DirectMessages,13 DiscordJs.IntentsBitField.Flags.Guilds,14 DiscordJs.IntentsBitField.Flags.GuildMembers,15 DiscordJs.IntentsBitField.Flags.GuildMessages,16 DiscordJs.IntentsBitField.Flags.GuildPresences17 ],18 partials: [DiscordJs.Partials.Channel],19 rest: {retries: 999999}20 }),21 urlParse = /^https:\/\/www.twitch.tv\/(?<user>.+)$/;22let readied = false;23/** @type {DiscordJs.TextChannel} */24let alertsChannel;25/** @type {DiscordJs.TextChannel} */26let announcementsChannel;27/** @type {DiscordJs.Role} */28let captainRole;29/** @type {DiscordJs.CategoryChannel} */30let challengesCategory;31/** @type {DiscordJs.Role} */32let exemptRole;33/** @type {DiscordJs.Role} */34let founderRole;35/** @type {DiscordJs.TextChannel} */36let matchResultsChannel;37/** @type {DiscordJs.Guild} */38let otlGuild;39/** @type {DiscordJs.TextChannel} */40let rosterUpdatesChannel;41/** @type {DiscordJs.TextChannel} */42let scheduledMatchesChannel;43/** @type {DiscordJs.Role} */44let testersRole;45/** @type {DiscordJs.TextChannel} */46let vodsChannel;47require("../extensions/discordJs.GuildMember.extensions");48require("../extensions/discordJs.User.extensions");49// #### # #50// # # #51// # # ## ### ### ### # ## ## #52// # # # # # # # # ## # # ##53// # # # ### # # # # # #54// # # # # # # # # # # ##55// #### ### #### ### ### # ## #56/**57 * A static class that handles all Discord.js interctions.58 */59class Discord {60 // ## # ## # ##61 // # # # # # #62 // ### # ## ### ### ### # ### ### ### ### ## #63 // # # # # ## # # # ## # # # # # # # # # # ## #64 // # ## # ## # # ## # # # # # ## # # # # ## #65 // # # ### ## # ## ### ## # # # # # # # # ## ###66 /**67 * Returns the alerts channel.68 * @returns {DiscordJs.TextChannel} The alerts channel.69 */70 static get alertsChannel() {71 return alertsChannel;72 }73 // # ## # ##74 // # # # # #75 // ### ### ### ## # # ### ## ## # # ## ### ### ### # ### ### ### ### ## #76 // # # # # # # # # # # # # # # ## #### # ## # # # ## # # # # # # # # # # ## #77 // # ## # # # # # # # # # # # ## # # ## # # # ## # # # # # ## # # # # ## #78 // # # # # # # ## ### # # ## ## # # ## # # ## ### ## # # # # # # # # ## ###79 /**80 * Returns the announcements channel.81 * @returns {DiscordJs.TextChannel} The announcements channel.82 */83 static get announcementsChannel() {84 return announcementsChannel;85 }86 // # # ### #87 // # # # #88 // ### ## ### # ###89 // # # # # # # # #90 // # # # # # # # #91 // ### ## ## ### ###92 /**93 * Returns the ID of the bot.94 * @returns {string} The ID of the bot.95 */96 static get botId() {97 if (discord && discord.user) {98 return discord.user.id;99 }100 return "";101 }102 // # # ### ##103 // # # # #104 // ## ### ### ### ### ## ### # # ## # ##105 // # # # # # # # # # # # ### # # # # ##106 // # # ## # # # # ## # # # # # # # # ##107 // ## # # ### ## # # ### # # # # ## ### ##108 // #109 /**110 * Returns the captain role.111 * @returns {DiscordJs.Role} The captain role.112 */113 static get captainRole() {114 return captainRole;115 }116 // # ## ## ## #117 // # # # # # #118 // ## ### ### # # ## ### ### ## ### # ### ### ## ### ## ### # #119 // # # # # # # # # ## # # # # # ## ## # # # # # ## # # # # # # # #120 // # # # # ## # # ## # # ## ## ## # # # ## # ## ## # # # # #121 // ## # # # # ### ### ## # # # ## ### ## # # ## ## # ## # #122 // ### ### #123 /**124 * Returns the challenges category.125 * @returns {DiscordJs.CategoryChannel} The challenges category.126 */127 static get challengesCategory() {128 return challengesCategory;129 }130 /**131 * Sets the challenges category.132 * @param {DiscordJs.CategoryChannel} category The challenges category.133 */134 static set challengesCategory(category) {135 challengesCategory = category;136 }137 // # ##138 // # #139 // ## ### ### ### ### ## # ###140 // # # # # # # # # # # ## # ##141 // # # # # ## # # # # ## # ##142 // ## # # # # # # # # ## ### ###143 /**144 * Returns the channels on the server.145 * @returns {DiscordJs.Collection<string, DiscordJs.GuildChannel | DiscordJs.ThreadChannel>} The channels.146 */147 static get channels() {148 if (otlGuild) {149 return otlGuild.channels.cache;150 }151 return new DiscordJs.Collection();152 }153 // # ### ##154 // # # # #155 // ## # # ## # # ### ### # # ## # ##156 // # ## ## # ## #### # # # ### # # # # ##157 // ## ## ## # # # # # # # # # # ##158 // ## # # ## # # ### ## # # ## ### ##159 // #160 /**161 * Returns the cap exempt role.162 * @returns {DiscordJs.Role} The cap exempt role.163 */164 static get exemptRole() {165 return exemptRole;166 }167 // # # ### ##168 // # # # # # #169 // # ## # # ### ### ## ### # # ## # ##170 // ### # # # # # # # # # ## # # ### # # # # ##171 // # # # # # # # # # ## # # # # # # ##172 // # ## ### # # ### ## # # # ## ### ##173 /**174 * Returns the founder role.175 * @returns {DiscordJs.Role} The founder role.176 */177 static get founderRole() {178 return founderRole;179 }180 // #181 //182 // ## ## ## ###183 // # # # # # #184 // # # # # # #185 // ### ## ## # #186 /**187 * Returns the OTL's icon.188 * @returns {string} The URL of the icon.189 */190 static get icon() {191 if (discord && discord.ws && discord.ws.status === 0) {192 return discord.user.avatarURL();193 }194 return void 0;195 }196 // # #197 // #198 // ## ###199 // # # #200 // # # #201 // ### ###202 /**203 * Returns the OTL's server ID.204 * @returns {string} The ID of the server.205 */206 static get id() {207 if (otlGuild) {208 return otlGuild.id;209 }210 return void 0;211 }212 // # # ### ## # ## # ##213 // # # # # # # # # # #214 // # # ### ### ## ### # # ## ### # # # ### ### # ### ### ### ### ## #215 // #### # # # # # # ### # ## ## # # # # ## # # # # # # # # # # ## #216 // # # # ## # # # # # # ## ## # # # # ## # # # # # ## # # # # ## #217 // # # # # ## ## # # # # ## ### ### ### ## ### ## # # # # # # # # ## ###218 /**219 * Returns the match results channel.220 * @returns {DiscordJs.TextChannel} The match results channel.221 */222 static get matchResultsChannel() {223 return matchResultsChannel;224 }225 // # # # # # ## # ##226 // # # # # # # # # #227 // ### ## ### ### ## ### # # ### ### ### ### ## ### # ### ### ### ### ## #228 // # # # # ## # # ## # # # # # # # # # # # # ## ## # # # # # # # # # # ## #229 // # # # ## # ## # # # # # # # # ## # ## ## # # # # # ## # # # # ## #230 // # ## ### ## ## # ## ### ### # # ## ## ### ## # # # # # # # # ## ###231 // #232 /**233 * Returns the roster updates channel.234 * @returns {DiscordJs.TextChannel} The roster updates channel.235 */236 static get rosterUpdatesChannel() {237 return rosterUpdatesChannel;238 }239 // # # ## # # # # # ## # ##240 // # # # # #### # # # # # #241 // ### ## ### ## ### # # # ## ### #### ### ### ## ### ## ### # ### ### ### ### ## #242 // ## # # # # ## # # # # # # ## # # # # # # # # # # # ## ## # # # # # # # # # # ## #243 // ## # # # ## # # # # # ## # # # # # ## # # # # ## ## # # # # # ## # # # # ## #244 // ### ## # # ## ### ### ### ## ### # # # # ## ## # # ## ### ## # # # # # # # # ## ###245 /**246 * Returns the scheduled matches channel.247 * @returns {DiscordJs.TextChannel} The scheduled matches channel.248 */249 static get scheduledMatchesChannel() {250 return scheduledMatchesChannel;251 }252 // # # ### ##253 // # # # # #254 // ### ## ### ### ## ### ### # # ## # ##255 // # # ## ## # # ## # # ## ### # # # # ##256 // # ## ## # ## # ## # # # # # ##257 // ## ## ### ## ## # ### # # ## ### ##258 /**259 * Returns the testers role.260 * @returns {DiscordJs.Role} The testers role.261 */262 static get testersRole() {263 return testersRole;264 }265 // # ## # ##266 // # # # # #267 // # # ## ### ### # ### ### ### ### ## #268 // # # # # # # ## # # # # # # # # # # ## #269 // # # # # # # ## # # # # # ## # # # # ## #270 // # ## ### ### ## # # # # # # # # ## ###271 /**272 * Returns the VoDs channel.273 * @returns {DiscordJs.TextChannel} The VoDs channel.274 */275 static get vodsChannel() {276 return vodsChannel;277 }278 // # #279 // # #280 // ### ### ### ### ### # # ###281 // ## # # # # # # # # # #282 // ## # # ## # # # # # #283 // ### ## # # # ## ### ###284 // #285 /**286 * Sets up Discord events. Should only ever be called once.287 * @returns {void}288 */289 static startup() {290 discord.on("ready", async () => {291 Log.log("Connected to Discord.");292 otlGuild = discord.guilds.cache.find((g) => g.name === settings.guild);293 const files = await fs.readdir(path.join(__dirname, "commands")),294 guildCommands = [],295 globalCommands = [];296 /** @type {{[x: string]: (function(DiscordJs.SlashCommandSubcommandBuilder): DiscordJs.SlashCommandSubcommandBuilder)[]}} */297 const simulateCommands = {};298 for (const file of files) {299 const commandFile = require(`./commands/${file}`);300 /** @type {DiscordJs.SlashCommandBuilder} */301 const command = commandFile.command();302 if (commandFile.global) {303 globalCommands.push(command);304 } else {305 guildCommands.push(command);306 if (commandFile.simulate) {307 if (!simulateCommands[commandFile.simulate]) {308 simulateCommands[commandFile.simulate] = [];309 }310 simulateCommands[commandFile.simulate].push((subcommand) => {311 subcommand312 .addUserOption((option) => option313 .setName("from")314 .setDescription("The user to simulate the command with.")315 .setRequired(true));316 commandFile.builder(subcommand);317 return subcommand;318 });319 }320 }321 }322 for (const group of Object.keys(simulateCommands)) {323 const simulate = new DiscordJs.SlashCommandBuilder();324 simulate325 .setName(`simulate${group}`)326 .setDescription(`Simulates a ${group} command from another user.`)327 .setDefaultMemberPermissions(0);328 for (const subcommand of simulateCommands[group]) {329 simulate.addSubcommand(subcommand);330 }331 guildCommands.push(simulate);332 }333 try {334 const rest = new Rest.REST().setToken(settings.discord.token);335 await rest.put(DiscordJs.Routes.applicationGuildCommands(settings.discord.clientId, otlGuild.id), {body: guildCommands});336 await rest.put(DiscordJs.Routes.applicationCommands(settings.discord.clientId), {body: globalCommands});337 } catch (err) {338 Log.exception("Error adding slash commands.", err);339 }340 if (!readied) {341 readied = true;342 }343 captainRole = otlGuild.roles.cache.find((r) => r.name === "Captain");344 exemptRole = otlGuild.roles.cache.find((r) => r.name === "Cap Exempt");345 founderRole = otlGuild.roles.cache.find((r) => r.name === "Founder");346 testersRole = otlGuild.roles.cache.find((r) => r.name === "Testers");347 alertsChannel = /** @type {DiscordJs.TextChannel} */ (otlGuild.channels.cache.find((c) => c.name === "otlbot-alerts")); // eslint-disable-line no-extra-parens348 announcementsChannel = /** @type {DiscordJs.TextChannel} */ (otlGuild.channels.cache.find((c) => c.name === "announcements")); // eslint-disable-line no-extra-parens349 matchResultsChannel = /** @type {DiscordJs.TextChannel} */ (otlGuild.channels.cache.find((c) => c.name === "match-results")); // eslint-disable-line no-extra-parens350 rosterUpdatesChannel = /** @type {DiscordJs.TextChannel} */ (otlGuild.channels.cache.find((c) => c.name === "roster-updates")); // eslint-disable-line no-extra-parens351 scheduledMatchesChannel = /** @type {DiscordJs.TextChannel} */ (otlGuild.channels.cache.find((c) => c.name === "scheduled-matches")); // eslint-disable-line no-extra-parens352 vodsChannel = /** @type {DiscordJs.TextChannel} */ (otlGuild.channels.cache.find((c) => c.name === "vods")); // eslint-disable-line no-extra-parens353 challengesCategory = /** @type {DiscordJs.CategoryChannel} */ (otlGuild.channels.cache.find((c) => c.name === "Challenges")); // eslint-disable-line no-extra-parens354 Notify.setupNotifications();355 });356 discord.on("disconnect", (ev) => {357 Log.exception("Disconnected from Discord.", ev);358 });359 discord.on("guildMemberRemove", async (member) => {360 if (member.guild && member.guild.id === otlGuild.id) {361 try {362 await member.leftDiscord();363 } catch (err) {364 Log.exception(`There was a problem with ${member.displayName} leaving the server.`, err);365 }366 }367 });368 discord.on("guildMemberUpdate", async (/** @type {DiscordJs.GuildMember} */ oldMember, newMember) => {369 if (newMember.guild && newMember.guild.id === otlGuild.id) {370 if (oldMember.displayName === newMember.displayName) {371 return;372 }373 try {374 await newMember.updateName(oldMember);375 } catch (err) {376 Log.exception(`There was a problem with ${oldMember.displayName} changing their name to ${newMember.displayName}.`, err);377 }378 }379 });380 discord.on("interactionCreate", async (interaction) => {381 if (!interaction.isChatInputCommand()) {382 return;383 }384 let success = false;385 try {386 if (interaction.commandName.startsWith("simulate")) {387 const module = require(`../discord/commands/${interaction.options.getSubcommand(true).toLowerCase()}`);388 if (!module.global && !Discord.channelIsOnServer(interaction.channel)) {389 return;390 }391 success = await module.handle(interaction, interaction.options.getUser("from", true));392 } else {393 const module = require(`../discord/commands/${interaction.commandName.toLowerCase()}`);394 if (!module.global && !Discord.channelIsOnServer(interaction.channel)) {395 return;396 }397 success = await module.handle(interaction, interaction.user);398 }399 } catch (err) {400 if (err instanceof Warning) {401 Log.warning(`${interaction.channel} ${interaction.user}: ${interaction} - ${err.message || err}`);402 } else if (err instanceof Exception) {403 Log.exception(`${interaction.channel} ${interaction.user}: ${interaction} - ${err.message}`, err.innerError);404 } else {405 Log.exception(`${interaction.channel} ${interaction.user}: ${interaction}`, err);406 }407 }408 if (success) {409 Log.log(`${interaction.channel} ${interaction.user}: ${interaction}`);410 }411 });412 discord.on("presenceUpdate", async (oldPresence, newPresence) => {413 if (newPresence && newPresence.activities && newPresence.member && newPresence.guild && newPresence.guild.id === otlGuild.id) {414 const activity = newPresence.activities.find((p) => p.name === "Twitch");415 if (activity && urlParse.test(activity.url)) {416 const {groups: {user}} = urlParse.exec(activity.url);417 await newPresence.member.addTwitchName(user);418 if (activity.state.toLowerCase() === "overload") {419 await newPresence.member.setStreamer();420 }421 }422 }423 });424 discord.on("error", (err) => {425 if (err.message === "read ECONNRESET") {426 // Swallow this error, see https://github.com/discordjs/discord.js/issues/3043#issuecomment-465543902427 return;428 }429 Log.exception("Discord error.", err);430 });431 }432 // #433 // #434 // ## ## ### ### ## ## ###435 // # # # # # # # # ## # #436 // # # # # # # # ## # #437 // ## ## # # # # ## ## ##438 /**439 * Connects to Discord.440 * @returns {Promise} A promise that resolves once Discord is connected.441 */442 static async connect() {443 Log.log("Connecting to Discord...");444 try {445 await discord.login(settings.discord.token);446 Log.log("Connected.");447 } catch (err) {448 Log.exception("Error connecting to Discord, will automatically retry.", err);449 }450 }451 // # ## # #452 // # # # #453 // ## ### # ## ### ### ## ## ### ## ###454 // # ## # # # # # # # # ## # # # ## # #455 // # ## # # # # # # # # ## # # ## # #456 // ### ### ## ## # # # # ## ## ## ## ###457 /**458 * Determines whether the bot is connected to Discord.459 * @returns {boolean} Whether the bot is connected to Discord.460 */461 static isConnected() {462 return discord && discord.ws && otlGuild ? discord.ws.status === 0 : false;463 }464 // ### # # ## # # ##465 // # # # # # ## # # # ##466 // # # # # ## # # ##467 // ### ### ## ### ##468 // #469 /**470 * Queues a message to be sent.471 * @param {string} message The message to be sent.472 * @param {DiscordJs.TextChannel|DiscordJs.DMChannel|DiscordJs.GuildMember|DiscordJs.GuildTextBasedChannel} channel The channel to send the message to.473 * @returns {Promise<DiscordJs.Message>} A promise that resolves with the sent message.474 */475 static async queue(message, channel) {476 if (channel.id === discord.user.id) {477 return void 0;478 }479 let msg;480 try {481 msg = await Discord.richQueue(Discord.embedBuilder({description: message}), channel);482 } catch {}483 return msg;484 }485 // # # ### # ## #486 // # # # # # #487 // ## # # ### ## ### ### # # ## # ###488 // # ## #### # # # ## # # # # # # # # # #489 // ## # # # # ## # # # # # # # # # #490 // ## # # ### ## ### ### ### ### ### ###491 /**492 * Gets a new DiscordJs EmbedBuilder object.493 * @param {DiscordJs.EmbedData} [options] The options to pass.494 * @returns {DiscordJs.EmbedBuilder} The EmbedBuilder object.495 */496 static embedBuilder(options) {497 const embed = new DiscordJs.EmbedBuilder(options);498 embed.setFooter({text: embed.data && embed.data.footer ? embed.data.footer.text : "Overload Teams League", iconURL: Discord.icon});499 if (!embed.data || !embed.data.color) {500 embed.setColor(0xFF6600);501 }502 if (!embed.data || !embed.data.timestamp) {503 embed.setTimestamp(new Date());504 }505 return embed;506 }507 // # # #### # # #508 // # # # #509 // ### ## ## ### ### ### ## ###510 // # # # # # # # # # # #511 // # # # # # # # # # #512 // # ### ## # # #### ### ### ##513 /**514 * Edits a rich embed message.515 * @param {DiscordJs.Message} message The posted message to edit.516 * @param {DiscordJs.EmbedBuilder} embed The message to change the posted message to.517 * @returns {Promise} A promise that resolves when the message is edited.518 */519 static async richEdit(message, embed) {520 embed.setFooter({521 text: embed.data && embed.data.footer ? embed.data.footer.text : "Overload Teams League",522 iconURL: Discord.icon523 });524 if (embed && embed.data && embed.data.fields) {525 embed.data.fields.forEach((field) => {526 if (field.value && field.value.length > 1024) {527 field.value = field.value.substring(0, 1024);528 }529 });530 }531 embed.setColor(message.embeds[0].color);532 if (!embed.data || !embed.data.timestamp) {533 embed.setTimestamp(new Date());534 }535 await message.edit({embeds: [embed]});536 }537 // # # ##538 // # # #539 // ### ## ## ### # # # # ## # # ##540 // # # # # # # # # # # # ## # # # ##541 // # # # # # ## # # # ## # # ##542 // # ### ## # # ## ### ## ### ##543 // #544 /**545 * Queues a rich embed message to be sent.546 * @param {DiscordJs.EmbedBuilder} embed The message to be sent.547 * @param {DiscordJs.TextChannel|DiscordJs.DMChannel|DiscordJs.GuildMember|DiscordJs.GuildTextBasedChannel} channel The channel to send the message to.548 * @returns {Promise<DiscordJs.Message>} A promise that resolves with the sent message.549 */550 static async richQueue(embed, channel) {551 if (channel.id === discord.user.id) {552 return void 0;553 }554 if (embed && embed.data && embed.data.fields) {555 embed.data.fields.forEach((field) => {556 if (field.value && field.value.length > 1024) {557 field.value = field.value.substring(0, 1024);558 }559 });560 }561 let msg;562 try {563 const msgSend = await channel.send({embeds: [embed]});564 if (msgSend instanceof Array) {565 msg = msgSend[0];566 } else {567 msg = msgSend;568 }569 } catch {}570 return msg;571 }572 // # ## ### ## ##573 // # # # # # # #574 // ## ### ### ### ### ## # # ### # # ### # ## ### # # ## ###575 // # # # # # # # # # # ## # # ## # # # # # # ## # # # # # ## # #576 // # # # # ## # # # # ## # # ## # # # # # # ## # # # ## #577 // ## # # # # # # # # ## ### ### ### ## # # ## ## # # ## #578 /**579 * Returns whether the channel is on the OTL server.580 * @param {DiscordJs.GuildTextBasedChannel} channel The channel.581 * @returns {boolean} Whether the channel is on the OTL server.582 */583 static channelIsOnServer(channel) {584 return channel.type === DiscordJs.ChannelType.GuildText && channel.guild.name === settings.guild;585 }586 // # ## # ##587 // # # # # #588 // ## ### ## ### ### ## # ### ### ### ### ## #589 // # # # # ## # # # # ## # # # # # # # # # # ## #590 // # # ## # ## # ## # # # # # ## # # # # ## #591 // ## # ## # # ## ## ## # # # # # # # # ## ###592 /**593 * Creates a new channel on the Discord server.594 * @param {string} name The name of the channel.595 * @param {DiscordJs.GuildChannelTypes} type The type of channel to create.596 * @param {DiscordJs.OverwriteResolvable[]|DiscordJs.Collection<DiscordJs.Snowflake, DiscordJs.OverwriteResolvable>} [overwrites] The permissions that should overwrite the default permission set.597 * @param {string} [reason] The reason the channel is being created.598 * @returns {Promise<DiscordJs.TextChannel | DiscordJs.NewsChannel | DiscordJs.VoiceChannel | DiscordJs.CategoryChannel | DiscordJs.StageChannel | DiscordJs.ForumChannel>} The created channel.599 */600 static createChannel(name, type, overwrites, reason) {601 if (!otlGuild) {602 return void 0;603 }604 return otlGuild.channels.create({name, type, permissionOverwrites: overwrites, reason});605 }606 // # ### ##607 // # # # #608 // ## ### ## ### ### ## # # ## # ##609 // # # # # ## # # # # ## ### # # # # ##610 // # # ## # ## # ## # # # # # ##611 // ## # ## # # ## ## # # ## ### ##612 /**613 * Creates a new role on the Discord server.614 * @param {DiscordJs.CreateRoleOptions} data The role data.615 * @returns {Promise<DiscordJs.Role>} A promise that resolves with the created role.616 */617 static createRole(data) {618 if (!otlGuild) {619 return void 0;620 }621 return otlGuild.roles.create(data);622 }623 // # #### #624 // # # #625 // ## ### ## ### ### ## ### # # ## ### ###626 // # # # # ## # # # # ## # # # # ## # # #627 // # # ## # ## # ## # # # ## # # #628 // ## # ## # # ## ## #### # ## # # ##629 /**630 * Creates a new event on the Discord server.631 * @param {DiscordJs.GuildScheduledEventCreateOptions} data The event data.632 * @returns {Promise<DiscordJs.GuildScheduledEvent>} A promise that returns the event.633 */634 static createEvent(data) {635 if (!otlGuild) {636 return void 0;637 }638 return otlGuild.scheduledEvents.create(data);639 }640 // # # # ## # ## ### ### #641 // # # # # # # # # # # #642 // # ## ### ### # ### ### ### ### ## # ### # # # ###643 // ### # # # # # # # # # # # # # # # ## # # # # # # # #644 // # # # # # # # # # # # ## # # # # ## # # # # # # # #645 // # ### # # ### ## # # # # # # # # ## ### ### # ### ###646 // #647 /**648 * Finds a Discord channel by its ID.649 * @param {string} id The ID of the channel.650 * @returns {DiscordJs.GuildChannel | DiscordJs.ThreadChannel} The Discord channel.651 */652 static findChannelById(id) {653 if (!otlGuild) {654 return void 0;655 }656 return otlGuild.channels.cache.find((c) => c.id === id);657 }658 // # # # ## # ## ### # #659 // # # # # # # # # # ## #660 // # ## ### ### # ### ### ### ### ## # ### # # ## # ### # # ##661 // ### # # # # # # # # # # # # # # # ## # # # # # # ## # # #### # ##662 // # # # # # # # # # # # ## # # # # ## # # # # # # ## # ## # # ##663 // # ### # # ### ## # # # # # # # # ## ### ### # # # # # # # ##664 // #665 /**666 * Finds a Discord channel by its name.667 * @param {string} name The name of the channel.668 * @returns {DiscordJs.GuildChannel | DiscordJs.ThreadChannel} The Discord channel.669 */670 static findChannelByName(name) {671 if (!otlGuild) {672 return void 0;673 }674 return otlGuild.channels.cache.find((c) => c.name === name);675 }676 // # # # ## # ## # # # # ### ### # ## # #677 // # # # # # # # #### # # # # # # ## #678 // # ## ### ### # # # ## # ### #### ## # # ### ## ### ### # # # # ## ### ### # ### # # ## # ### # # ##679 // ### # # # # # # ## # # # # # # # # # ## #### # # # ## # # # # # # # # # ## # # # # # # # # ## # # #### # ##680 // # # # # # # # # # # # # # # # # ## # # # # ## # # # # # # # # ## # # # # ## # # # ## # ## # # ##681 // # ### # # ### ### ### ### ### ### # # ## # # ### ## # ### # ### ### ### ### ### # # # # # # # # # ##682 // # # #683 /**684 * Returns the Discord user in the guild by their display name.685 * @param {string} displayName The display name of the Discord user.686 * @returns {DiscordJs.GuildMember} The guild member.687 */688 static findGuildMemberByDisplayName(displayName) {689 if (!otlGuild) {690 return void 0;691 }692 return otlGuild.members.cache.find((m) => m.displayName === displayName);693 }694 // # # # ## # ## # # # # ### ### #695 // # # # # # # # #### # # # # #696 // # ## ### ### # # # ## # ### #### ## # # ### ## ### ### # # # ###697 // ### # # # # # # ## # # # # # # # # # ## #### # # # ## # # # # # # # # #698 // # # # # # # # # # # # # # # # # ## # # # # ## # # # # # # # #699 // # ### # # ### ### ### ### ### ### # # ## # # ### ## # ### # ### ###700 // #701 /**702 * Returns the Discord user in the guild by their Discord ID.703 * @param {string} id The ID of the Discord user.704 * @returns {DiscordJs.GuildMember} The guild member.705 */706 static findGuildMemberById(id) {707 if (!otlGuild) {708 return void 0;709 }710 return otlGuild.members.cache.find((m) => m.id === id);711 }712 // # # # ### ## ### ### #713 // # # # # # # # # # #714 // # ## ### ### # # ## # ## ### # # # ###715 // ### # # # # # ### # # # # ## # # # # # # #716 // # # # # # # # # # # # ## # # # # # # #717 // # ### # # ### # # ## ### ## ### # ### ###718 // #719 /**720 * Finds a Discord role by its ID.721 * @param {string} id The ID of the role.722 * @returns {DiscordJs.Role} The Discord role.723 */724 static findRoleById(id) {725 if (!otlGuild) {726 return void 0;727 }728 return otlGuild.roles.cache.find((r) => r.id === id);729 }730 // # # # ### ## ### # #731 // # # # # # # # # ## #732 // # ## ### ### # # ## # ## ### # # ## # ### # # ##733 // ### # # # # # ### # # # # ## # # # # # ## # # #### # ##734 // # # # # # # # # # # # ## # # # # # ## # ## # # ##735 // # ### # # ### # # ## ### ## ### # # # # # # # ##736 // #737 /**738 * Finds a Discord role by its name.739 * @param {string} name The name of the role.740 * @returns {DiscordJs.Role} The Discord role.741 */742 static findRoleByName(name) {743 if (!otlGuild) {744 return void 0;745 }746 return otlGuild.roles.cache.find((r) => r.name === name);747 }748 // # # # # # ### ### #749 // # # # # # # # # #750 // # ## ### ### # # ### ## ### ### # # # ###751 // ### # # # # # # # ## # ## # # # # # # # # #752 // # # # # # # # # ## ## # # # # # # # #753 // # ### # # ### ## ### ## # ### # ### ###754 // #755 /**756 * Finds a Discord user by user ID.757 * @param {string} id The user ID.758 * @returns {Promise<DiscordJs.User>} A promise that resolves with the user.759 */760 static findUserById(id) {761 return discord.users.fetch(id, {cache: false});762 }763 // # # # #### # ### ### #764 // # # # # # # # # #765 // # ## ### ### ### # # ## ### ### ### # # # ###766 // ### # # # # # # # # # ## # # # # # # # # # #767 // # # # # # # # # # ## # # # # # # # # # #768 // # ### # # ### #### # ## # # ## ### # ### ###769 // #770 /**771 * Finds a Discord event by event ID.772 * @param {string} id The event ID.773 * @returns {Promise<DiscordJs.GuildScheduledEvent>} A promise that returns the event.774 */775 static findEventById(id) {776 return otlGuild.scheduledEvents.fetch(id);777 }778 // # # #779 // # ## #780 // ### ## ### ## # ### # # ##781 // # # # ## # # ## # # #### # ##782 // ## ## # # ## # ## # # ##783 // # ## ## # # # # # # ##784 // ###785 /**786 * Returns the user's display name if they are a guild member, or a username if they are a user.787 * @param {DiscordJs.GuildMember|DiscordJs.User} user The user to get the name for.788 * @returns {string} The name of the user.789 */790 static getName(user) {791 return user instanceof DiscordJs.GuildMember ? user.displayName : user.username;792 }793 // # # # # #### #794 // # # # # #795 // ### ## ### # # ### ## ## # # ## ### ### ### # # ## ### ### ###796 // # # # ## # # # # # # # # #### # # # # # # # # # ## # # # ##797 // ## ## # # # # # # # # # # # # # ## # # # ## # # # ##798 // # ## ## ## ### ## ## # # ### # # # #### # ## # # ## ###799 // ### # ###800 /**801 * Gets upcoming Discord events.802 * @returns {Promise<DiscordJs.GuildScheduledEvent[]>} A promise that returns the events.803 */804 static async getUpcomingEvents() {805 if (!otlGuild) {806 return [];807 }808 return Array.from(await otlGuild.scheduledEvents.fetch()).filter((e) => !e[1].isCompleted() && !e[1].isCanceled()).map((e) => e[1]);809 }810 // # ##811 // # #812 // ## ### # # # # ### ## ###813 // # ## # # # # # # # ## # #814 // # ## # # #### # # ## #815 // ### ### ## #### # # ## #816 /**817 * Determines whether the user is the owner.818 * @param {DiscordJs.GuildMember} member The user to check.819 * @returns {boolean} Whether the user is the owner.820 */821 static isOwner(member) {822 return member && member.user.username === settings.admin.username && member.user.discriminator === settings.admin.discriminator;823 }824}...
commands.spec.ts
Source:commands.spec.ts
...14type Cmd = Command<Model, Real>;15const model: Model = Object.freeze({});16const real: Real = Object.freeze({});17describe('commands (integration)', () => {18 function simulateCommands(cmds: Iterable<Cmd>): void {19 for (const c of cmds) {20 if (!c.check(model)) continue;21 try {22 c.run(model, real);23 } catch (err) {24 return;25 }26 }27 }28 it('should generate a cloneable instance', () => {29 fc.assert(30 fc.property(fc.integer(), fc.option(fc.integer({ min: 2 }), { nil: undefined }), (seed, biasFactor) => {31 // Arrange32 const mrng = new Random(prand.xorshift128plus(seed));33 const logOnCheck: { data: string[] } = { data: [] };34 // Act35 const commandsArb = commands([36 new FakeConstant(new SuccessCommand(logOnCheck)),37 new FakeConstant(new SkippedCommand(logOnCheck)),38 new FakeConstant(new FailureCommand(logOnCheck)),39 ]);40 const baseCommands = commandsArb.generate(mrng, biasFactor);41 // Assert42 return baseCommands.hasToBeCloned;43 })44 );45 });46 it('should skip skipped commands on shrink', () => {47 fc.assert(48 fc.property(fc.integer(), fc.option(fc.integer({ min: 2 }), { nil: undefined }), (seed, biasFactor) => {49 // Arrange50 const mrng = new Random(prand.xorshift128plus(seed));51 const logOnCheck: { data: string[] } = { data: [] };52 // Act53 const commandsArb = commands([54 new FakeConstant(new SuccessCommand(logOnCheck)),55 new FakeConstant(new SkippedCommand(logOnCheck)),56 new FakeConstant(new FailureCommand(logOnCheck)),57 ]);58 const baseCommands = commandsArb.generate(mrng, biasFactor);59 simulateCommands(baseCommands.value);60 // Assert61 const shrinks = commandsArb.shrink(baseCommands.value_, baseCommands.context);62 for (const shrunkCmds of shrinks) {63 logOnCheck.data = [];64 [...shrunkCmds.value].forEach((c) => c.check(model));65 expect(logOnCheck.data.every((e) => e !== 'skipped')).toBe(true);66 }67 })68 );69 });70 it('should shrink with failure at the end', () => {71 fc.assert(72 fc.property(fc.integer(), fc.option(fc.integer({ min: 2 }), { nil: undefined }), (seed, biasFactor) => {73 // Arrange74 const mrng = new Random(prand.xorshift128plus(seed));75 const logOnCheck: { data: string[] } = { data: [] };76 // Act77 const commandsArb = commands([78 new FakeConstant(new SuccessCommand(logOnCheck)),79 new FakeConstant(new SkippedCommand(logOnCheck)),80 new FakeConstant(new FailureCommand(logOnCheck)),81 ]);82 const baseCommands = commandsArb.generate(mrng, biasFactor);83 simulateCommands(baseCommands.value);84 fc.pre(logOnCheck.data[logOnCheck.data.length - 1] === 'failure');85 // Assert86 const shrinks = commandsArb.shrink(baseCommands.value_, baseCommands.context);87 for (const shrunkCmds of shrinks) {88 logOnCheck.data = [];89 [...shrunkCmds.value].forEach((c) => c.check(model));90 if (logOnCheck.data.length > 0) {91 // either empty or ending by the failure92 expect(logOnCheck.data[logOnCheck.data.length - 1]).toEqual('failure');93 }94 }95 })96 );97 });98 it('should shrink with at most one failure and all successes', () => {99 fc.assert(100 fc.property(fc.integer(), fc.option(fc.integer({ min: 2 }), { nil: undefined }), (seed, biasFactor) => {101 // Arrange102 const mrng = new Random(prand.xorshift128plus(seed));103 const logOnCheck: { data: string[] } = { data: [] };104 // Act105 const commandsArb = commands([106 new FakeConstant(new SuccessCommand(logOnCheck)),107 new FakeConstant(new SkippedCommand(logOnCheck)),108 new FakeConstant(new FailureCommand(logOnCheck)),109 ]);110 const baseCommands = commandsArb.generate(mrng, biasFactor);111 simulateCommands(baseCommands.value);112 // Assert113 const shrinks = commandsArb.shrink(baseCommands.value_, baseCommands.context);114 for (const shrunkCmds of shrinks) {115 logOnCheck.data = [];116 [...shrunkCmds.value].forEach((c) => c.check(model));117 expect(logOnCheck.data.every((e) => e === 'failure' || e === 'success')).toBe(true);118 expect(logOnCheck.data.filter((e) => e === 'failure').length <= 1).toBe(true);119 }120 })121 );122 });123 it('should provide commands which have never run', () => {124 const commandsArb = commands([new FakeConstant(new SuccessCommand({ data: [] }))], {125 disableReplayLog: true,126 });127 const manyArbsIncludingCommandsOne = tuple(nat(16), commandsArb, nat(16));128 const assertCommandsNotStarted = (value: Value<[number, Iterable<Cmd>, number]>) => {129 // Check the commands have never been executed130 // by checking the toString of the iterable is empty131 expect(String(value.value_[1])).toEqual('');132 };133 const startCommands = (value: Value<[number, Iterable<Cmd>, number]>) => {134 // Iterate over all the generated commands to run them all135 let ranOneCommand = false;136 for (const cmd of value.value_[1]) {137 ranOneCommand = true;138 cmd.run({}, {});139 }140 // Confirming that executing at least one command will make the toString of the iterable141 // not empty142 if (ranOneCommand) {143 expect(String(value.value_[1])).not.toEqual('');144 }145 };146 fc.assert(147 fc.property(148 fc.integer().noShrink(),149 fc.infiniteStream(fc.nat()),150 fc.option(fc.integer({ min: 2 }), { nil: undefined }),151 (seed, shrinkPath, biasFactor) => {152 // Generate the first Value153 const it = shrinkPath[Symbol.iterator]();154 const mrng = new Random(prand.xorshift128plus(seed));155 let currentValue: Value<[number, Iterable<Cmd>, number]> | null = manyArbsIncludingCommandsOne.generate(156 mrng,157 biasFactor158 );159 // Check status and update first Value160 assertCommandsNotStarted(currentValue);161 startCommands(currentValue);162 // Traverse the shrink tree in order to detect already seen ids163 while (currentValue !== null) {164 currentValue = manyArbsIncludingCommandsOne165 .shrink(currentValue.value_, currentValue.context)166 .map((nextValue) => {167 // Check nothing starting for the next one168 assertCommandsNotStarted(nextValue);169 // Start everything: not supposed to impact any other shrinkable170 startCommands(nextValue);171 return nextValue;172 })173 .getNthOrLast(it.next().value);174 }175 }176 )177 );178 });179 it('should shrink to smaller values', () => {180 const commandsArb = commands([nat(3).map((id) => new SuccessIdCommand(id))]);181 fc.assert(182 fc.property(183 fc.integer().noShrink(),184 fc.infiniteStream(fc.nat()),185 fc.option(fc.integer({ min: 2 }), { nil: undefined }),186 (seed, shrinkPath, biasFactor) => {187 // Generate the first Value188 const it = shrinkPath[Symbol.iterator]();189 const mrng = new Random(prand.xorshift128plus(seed));190 let currentValue: Value<Iterable<Cmd>> | null = commandsArb.generate(mrng, biasFactor);191 // Run all commands of first Value192 simulateCommands(currentValue.value_);193 // Traverse the shrink tree in order to detect already seen ids194 const extractIdRegex = /^custom\((\d+)\)$/;195 while (currentValue !== null) {196 const currentItems = [...currentValue.value_].map((c) => +extractIdRegex.exec(c.toString())![1]);197 currentValue = commandsArb198 .shrink(currentValue.value_, currentValue.context)199 .map((nextValue) => {200 // Run all commands of nextShrinkable201 simulateCommands(nextValue.value_);202 // Check nextShrinkable is strictly smaller than current one203 const nextItems = [...nextValue.value_].map((c) => +extractIdRegex.exec(c.toString())![1]);204 expect(isStrictlySmallerArray(nextItems, currentItems)).toBe(true);205 // Next is eligible for shrinking206 return nextValue;207 })208 .getNthOrLast(it.next().value);209 }210 }211 )212 );213 });214 it('should shrink the same way when based on replay data', () => {215 fc.assert(216 fc.property(217 fc.integer().noShrink(),218 fc.nat(100),219 fc.option(fc.integer({ min: 2 }), { nil: undefined }),220 (seed, numValues, biasFactor) => {221 // create unused logOnCheck222 const logOnCheck: { data: string[] } = { data: [] };223 // generate scenario and simulate execution224 const rng = prand.xorshift128plus(seed);225 const refArbitrary = commands([226 new FakeConstant(new SuccessCommand(logOnCheck)),227 new FakeConstant(new SkippedCommand(logOnCheck)),228 new FakeConstant(new FailureCommand(logOnCheck)),229 nat().map((v) => new SuccessIdCommand(v)),230 ]);231 const refValue: Value<Iterable<Cmd>> = refArbitrary.generate(new Random(rng), biasFactor);232 simulateCommands(refValue.value_);233 // trigger computation of replayPath234 // and extract shrinks for ref235 const refShrinks = [236 ...refArbitrary237 .shrink(refValue.value_, refValue.context)238 .take(numValues)239 .map((s) => [...s.value_].map((c) => c.toString())),240 ];241 // extract replayPath242 const replayPath = /\/\*replayPath=['"](.*)['"]\*\//.exec(refValue.value_.toString())![1];243 // generate scenario but do not simulate execution244 const noExecArbitrary = commands(245 [246 new FakeConstant(new SuccessCommand(logOnCheck)),...
Using AI Code Generation
1const { simulateCommands } = require('fast-check-monorepo');2 { command: 'npm install', exitCode: 0 },3 { command: 'npm run build', exitCode: 0 },4 { command: 'npm run test', exitCode: 1 },5];6simulateCommands(commands);
Using AI Code Generation
1const { simulateCommands } = require('fast-check-monorepo');2 { command: 'ls' },3 { command: 'cd', args: ['src'] },4 { command: 'ls' },5 { command: 'cd', args: ['..'] },6 { command: 'ls' }7];8const result = simulateCommands(commands);9console.log(result);10{11}12const { simulateCommand } = require('fast-check-monorepo');13const command = { command: 'ls' };14const result = simulateCommand(command);15console.log(result);16{17}18const { simulateCommand } = require('fast-check-monorepo');19const command = { command: 'ls', args: ['src'] };20const result = simulateCommand(command);21console.log(result);22{23}24const { simulateCommand } = require('fast-check-monorepo');25const command = { command: 'ls', args: ['src', 'test.js'] };26const result = simulateCommand(command);27console.log(result);28{29}30const { simulateCommand } = require('fast-check-monorepo');31const command = { command: 'ls', args: ['src', 'test.js', 'node_modules'] };32const result = simulateCommand(command);33console.log(result);34{35}36const { simulateCommand } = require('fast-check-monorepo');37const command = { command: 'ls',
Using AI Code Generation
1import fc from 'fast-check'2 fc.constantCommand({ type: 'inc' }),3 fc.constantCommand({ type: 'dec' })4const model = (s: number, c: any) => {5 switch (c.type) {6 }7}8const state = fc.integer(0, 10)9fc.assert(10 fc.property(fc.commands(commands, 100), (cmds) => {11 const actual = cmds.reduce(model, 0)12 const expected = cmds.reduce((s, c) => model(s, c), 0)13 })14import fc from 'fast-check'15 fc.constantCommand({ type: 'inc' }),16 fc.constantCommand({ type: 'dec' })17const model = (s: number, c: any) => {18 switch (c.type) {19 }20}21const state = fc.integer(0, 10)22fc.assert(23 fc.property(fc.commands(commands, 100), (cmds) => {24 const actual = cmds.reduce(model, 0)25 const expected = cmds.reduce((s, c) => model(s, c), 0)26 })27import fc from 'fast-check'28 fc.constantCommand({ type: 'inc' }),29 fc.constantCommand({ type: 'dec' })30const model = (s: number, c: any) => {31 switch (c.type) {
Using AI Code Generation
1const fc = require("fast-check");2const { simulateCommands } = require("fast-check-monorepo");3 .oneof(4 fc.record({5 type: fc.constant("ADD"),6 value: fc.nat()7 }),8 fc.record({9 type: fc.constant("SUB"),10 value: fc.nat()11 })12 .map(c => ({13 type: c.type.toLowerCase()14 }));15const initialState = 0;16const reducer = (state, command) => {17 switch (command.type) {18 return state + command.value;19 return state - command.value;20 }21};22const assertReducer = (state, command, next) => {23 const actualNext = reducer(state, command);24 if (actualNext !== next) {25 throw new Error(26 `reducer(${state}, ${JSON.stringify(command)}) should be ${next} but was ${actualNext}`27 );28 }29};30const assertReducerInvariant = (state, command) => {31 assertReducer(state, command, reducer(state, command));32};33simulateCommands(34);35{36 "scripts": {37 },38 "dependencies": {39 },40 "devDependencies": {41 }42}43{44 "dependencies": {45 "@babel/code-frame": {
Using AI Code Generation
1const fc = require('fast-check');2const { simulateCommands } = require('fast-check-monorepo');3const commands = simulateCommands(4 fc.integer(0, 10),5 fc.integer(0, 10),6 (x, y) => x + y,7);8console.log(commands);9const add = require('./add');10const { commands } = require('./test');11test('add', () => {12 commands.forEach(([x, y]) => {13 const result = add(x, y);14 expect(result).toBe(x + y);15 });16});
Using AI Code Generation
1const fc = require("fast-check");2const simulateCommands = async (commands) => {3 const state = await commands.reduce(async (acc, command) => {4 const state = await acc;5 return command(state);6 }, Promise.resolve({}));7 return state;8};9 async (state) => {10 return { ...state, a: 1 };11 },12 async (state) => {13 return { ...state, b: 2 };14 },15];16const simulateCommands = async (commands) => {17 const state = await commands.reduce(async (acc, command) => {18 const state = await acc;19 return command(state);20 }, Promise.resolve({}));21 return state;22};23 async (state) => {24 return { ...state, a: 1 };25 },26 async (state) => {27 return { ...state, b: 2 };28 },29];30const simulateCommands = async (commands) => {31 const state = await commands.reduce(async (acc, command) => {32 const state = await acc;33 return command(state);34 }, Promise.resolve({}));35 return state;36};37 async (state) => {38 return { ...state, a: 1 };39 },40 async (state) => {41 return { ...state, b: 2 };42 },43];44const simulateCommands = async (commands) => {45 const state = await commands.reduce(async (acc, command) => {46 const state = await acc;47 return command(state);48 }, Promise.resolve({}));49 return state;50};51 async (state) => {52 return { ...state, a: 1 };53 },54 async (state) => {55 return { ...state, b: 2 };56 },57];58const simulateCommands = async (commands) => {59 const state = await commands.reduce(async (acc, command) => {60 const state = await acc;61 return command(state);62 }, Promise.resolve({}));63 return state;64};65 async (state) => {66 return { ...state, a: 1 };67 },
Using AI Code Generation
1import { simulateCommands } from "fast-check-monorepo";2import { model, init, command } from "system-under-test";3const commands = [command1, command2, ...];4const initialState = init();5const model = simulateCommands(model, commands, initialState);6export const model = {7 state: {8 },9 events: {10 },11};12export const init = () => {13};14export const command1 = () => {15};16export const command2 = () => {17};
Using AI Code Generation
1const { property, fc } = require('fast-check');2const { replay } = require('fast-check-monorepo');3const myCommand = fc.integer().chain((x) => {4 return fc.constant(x);5});6const myProperty = (x) => {7 return x > 0;8};9property(myProperty, myCommand).check({ seed: 1234, numRuns: 1 });10replay(1234, 0);
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!