diff --git a/.github/workflows/PullRequestOpenAll.yml b/.github/workflows/PullRequestOpenAll.yml index 21d965c39..82f053a46 100644 --- a/.github/workflows/PullRequestOpenAll.yml +++ b/.github/workflows/PullRequestOpenAll.yml @@ -27,24 +27,24 @@ jobs: run: npm install eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb-base eslint-config-airbnb-typescript eslint-config-google eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-jest eslint-plugin-sonarjs --save-dev && npx eslint --version - name: Linting run: npx eslint --ext .ts,.js . - test: - name: Test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Use Node.js '20.5.0' - uses: actions/setup-node@v3 - with: - node-version: '20.5.0' - cache: 'npm' - - name: Update npm - run: npm install -g npm && npm --version - - name: Install dependencies - run: npm ci - - name: Copy env - run: cp .env.example .env - - name: Test - run: npx jest --silent -c ./src/jest/jest.unit.config.ts + # test: + # name: Test + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - name: Use Node.js '20.5.0' + # uses: actions/setup-node@v3 + # with: + # node-version: '20.5.0' + # cache: 'npm' + # - name: Update npm + # run: npm install -g npm && npm --version + # - name: Install dependencies + # run: npm ci + # - name: Copy env + # run: cp .env.example .env + # - name: Test + # run: npx jest --silent -c ./src/jest/jest.unit.config.ts codeql: name: CodeQL runs-on: ubuntu-latest diff --git a/.github/workflows/PushToMain.yml b/.github/workflows/PushToMain.yml index c843ab1fa..d5c5b6707 100644 --- a/.github/workflows/PushToMain.yml +++ b/.github/workflows/PushToMain.yml @@ -22,24 +22,24 @@ jobs: run: npm install eslint eslint-config-airbnb-base eslint-config-airbnb-typescript eslint-config-google eslint-import-resolver-typescript eslint-plugin-import --save-dev && npx eslint --version - name: Linting run: npx eslint --ext .ts,.js . - test: - name: Test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Use Node.js '20.5.0' - uses: actions/setup-node@v3 - with: - node-version: '20.5.0' - cache: 'npm' - - name: Update npm - run: npm install -g npm && npm --version - - name: Install dependencies - run: npm ci - - name: Copy env - run: cp .env.example .env - - name: Test - run: npx jest --silent -c ./src/jest/jest.unit.config.ts + # test: + # name: Test + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - name: Use Node.js '20.5.0' + # uses: actions/setup-node@v3 + # with: + # node-version: '20.5.0' + # cache: 'npm' + # - name: Update npm + # run: npm install -g npm && npm --version + # - name: Install dependencies + # run: npm ci + # - name: Copy env + # run: cp .env.example .env + # - name: Test + # run: npx jest --silent -c ./src/jest/jest.unit.config.ts codeql: name: CodeQL runs-on: ubuntu-latest diff --git a/.github/workflows/EveryFridayScan.yml b/.github/workflows/archive/EveryFridayScan.yml similarity index 100% rename from .github/workflows/EveryFridayScan.yml rename to .github/workflows/archive/EveryFridayScan.yml diff --git a/src/discord/commands/guild/d.birthday.ts b/src/discord/commands/guild/d.birthday.ts index 47bc6e45f..2440727e6 100644 --- a/src/discord/commands/guild/d.birthday.ts +++ b/src/discord/commands/guild/d.birthday.ts @@ -131,6 +131,7 @@ export const dBirthday: SlashCommand = { .setName('get') .setDescription('Get someone\'s birthday!') .addUserOption(option => option + // .setRequired(true) If nothing is provided it defaults to the user who ran the command .setName('user') .setDescription('User to lookup')) .addBooleanOption(option => option.setName('ephemeral') diff --git a/src/discord/commands/guild/d.rpg.ts b/src/discord/commands/guild/d.rpg.ts index 689475191..c752c00d3 100644 --- a/src/discord/commands/guild/d.rpg.ts +++ b/src/discord/commands/guild/d.rpg.ts @@ -1939,7 +1939,7 @@ export async function rpgArcade( .addComponents( customButton(`rpgCoinFlip,user:${interaction.user.id}`, 'CoinFlip', 'buttonCoinflip', ButtonStyle.Secondary), customButton(`rpgRoulette,user:${interaction.user.id}`, 'Roulette', 'buttonRoulette', ButtonStyle.Secondary), - // customButton(`rpgTrivia,user:${interaction.user.id}`, 'Trivia', 'buttonTrivia', ButtonStyle.Secondary), + customButton(`rpgTrivia,user:${interaction.user.id}`, 'Trivia', 'buttonTrivia', ButtonStyle.Secondary), // customButton(`rpgBlackjack,user:${interaction.user.id}`, 'Blackjack', '🃏', ButtonStyle.Primary), // customButton(`rpgSlots,user:${interaction.user.id}`, 'Slots', '🎰', ButtonStyle.Primary), customButton(`rpgTown,user:${interaction.user.id}`, 'Town', 'buttonTown', ButtonStyle.Primary), @@ -3171,10 +3171,10 @@ export const dRpg: SlashCommand = { .setDescription('Go to the coinflip game')) .addSubcommand(subcommand => subcommand .setName('roulette') - .setDescription('Go to the roulette game')), - // .addSubcommand(subcommand => subcommand - // .setName('trivia') - // .setDescription('Go to the trivia parlor')), + .setDescription('Go to the roulette game')) + .addSubcommand(subcommand => subcommand + .setName('trivia') + .setDescription('Go to the trivia parlor')), async execute(interaction) { log.info(F, await commandContext(interaction)); const channelRpg = await interaction.guild?.channels.fetch(env.CHANNEL_TRIPTOWN as string) as TextChannel; diff --git a/src/discord/commands/guild/d.timezone.ts b/src/discord/commands/guild/d.timezone.ts index e1fa2bcc2..93e454065 100644 --- a/src/discord/commands/guild/d.timezone.ts +++ b/src/discord/commands/guild/d.timezone.ts @@ -17,6 +17,7 @@ export const dTimezone: SlashCommand = { .setName('get') .setDescription('Get someone\'s timezone!') .addUserOption(option => option + // .setRequired(true) If nothing is provided it defaults to the user who ran the command .setName('user') .setDescription('User to lookup')) .addBooleanOption(option => option.setName('ephemeral') diff --git a/src/discord/commands/guild/d.voice.ts b/src/discord/commands/guild/d.voice.ts index 956fe77f0..15f58f49f 100644 --- a/src/discord/commands/guild/d.voice.ts +++ b/src/discord/commands/guild/d.voice.ts @@ -1,7 +1,5 @@ import { - VoiceChannel, - ChannelType, - Guild, + // Guild, Colors, SlashCommandBuilder, GuildMember, @@ -15,7 +13,7 @@ import commandContext from '../../utils/context'; const F = f(__filename); -type VoiceActions = 'lock' | 'hide' | 'ban' | 'rename' | 'mute' | 'cohost' | 'radio' | 'bitrate'; +type VoiceActions = 'lock' | 'hide' | 'add' | 'ban' | 'rename' | 'mute' | 'cohost' | 'radio' | 'bitrate'; async function tentRename( voiceChannel: VoiceBasedChannel, @@ -31,30 +29,27 @@ async function tentRename( .setDescription(`${voiceChannel} has been renamed to ${newName}`); } -// async function tentLock( -// voiceChannel: VoiceBasedChannel, -// ):Promise { -// let verb = ''; - -// if ( -// voiceChannel -// .permissionsFor(voiceChannel.guild.roles.everyone) -// .has(PermissionsBitField.Flags.ViewChannel) === true -// ) { -// voiceChannel.permissionOverwrites.edit(voiceChannel.guild.roles.everyone, { ViewChannel: false }); -// verb = 'hidden'; -// } else { -// voiceChannel.permissionOverwrites.edit(voiceChannel.guild.roles.everyone, { ViewChannel: true }); -// verb = 'unhidden'; -// } - -// // log.debug(F, `Channel is now ${verb}`); - -// return embedTemplate() -// .setTitle('Success') -// .setColor(Colors.Green) -// .setDescription(`${voiceChannel} has been ${verb}`); -// } +async function tentLock( + voiceChannel: VoiceBasedChannel, +):Promise { + let verb = ''; + if ( + voiceChannel + .permissionsFor(voiceChannel.guild.roles.everyone) + .has(PermissionsBitField.Flags.Connect) === true + ) { + voiceChannel.permissionOverwrites.edit(voiceChannel.guild.roles.everyone, { Connect: false }); + verb = 'locked'; + } else { + voiceChannel.permissionOverwrites.edit(voiceChannel.guild.roles.everyone, { Connect: true }); + verb = 'unlocked'; + } + // log.debug(F, `Channel is now ${verb}`); + return embedTemplate() + .setTitle('Success') + .setColor(Colors.Green) + .setDescription(`${voiceChannel} has been ${verb}`); +} async function tentHide( voiceChannel: VoiceBasedChannel, @@ -81,37 +76,49 @@ async function tentHide( .setDescription(`${voiceChannel} has been ${verb}`); } +// async function tentAdd( +// voiceChannel: VoiceBasedChannel, +// target: GuildMember, +// ):Promise { +// let verb = ''; +// +// if (voiceChannel.permissionsFor(target).has(PermissionsBitField.Flags.ViewChannel) === false){ +// return embedTemplate() +// .setTitle('Error') +// .setColor(Colors.Red) +// .setDescription(`${target} is banned from ${voiceChannel}, unban them first!`); +// } +// +// if (!voiceChannel.permissionsFor(target).has(PermissionsBitField.Flags.ViewChannel) === true){ +// voiceChannel.permissionOverwrites.create(target, { ViewChannel: true, Connect: true }); +// verb = 'added'; +// } else { +// voiceChannel.permissionOverwrites.delete(target); +// verb = 'unadded'; +// } +// // log.debug(F, `${target.displayName} is now ${verb}`); +// +// return embedTemplate() +// .setTitle('Success') +// .setColor(Colors.Green) +// .setDescription(`${target} has been ${verb} from ${voiceChannel}`); +// } + async function tentBan( voiceChannel: VoiceBasedChannel, target: GuildMember, ):Promise { let verb = ''; - if (voiceChannel.permissionsFor(target).has(PermissionsBitField.Flags.ViewChannel) === true) { + if (!voiceChannel.permissionsFor(target).has(PermissionsBitField.Flags.ViewChannel) === false) { voiceChannel.permissionOverwrites.edit(target, { ViewChannel: false, Connect: false }); if (target.voice.channel === voiceChannel) { target.voice.setChannel(null); } - verb = 'banned and hidden'; + verb = 'banned and disconnected'; } else { - voiceChannel.permissionOverwrites.edit(target, { ViewChannel: true, Connect: true }); - verb = 'unbanned and unhidden'; - } - - // Disallow banning bots - if (target.user.bot) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('You cannot ban bots'); - } - - // Disallow banning mods - if (target.roles.cache.has(env.ROLE_MODERATOR) === true) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('You cannot ban mods'); + voiceChannel.permissionOverwrites.delete(target); + verb = 'unbanned'; } // log.debug(F, `${target.displayName} is now ${verb}`); @@ -168,144 +175,6 @@ async function tentCohost( .setDescription(`${target} has been ${verb} in ${voiceChannel}`); } -async function tentRadio( - voiceChannel: VoiceBasedChannel, - stationid: string, - guild: Guild, -):Promise { - const radioChannels: { [key: string]: string } = { - '830530156048285716': env.CHANNEL_LOFIRADIO, - '861363156568113182': env.CHANNEL_JAZZRADIO, - '833406944387268670': env.CHANNEL_SYNTHWAVERADIO, - '831623165632577587': env.CHANNEL_SLEEPYRADIO, - }; - - // If the station choice was "none", send the radio back to the radio room - if (stationid === 'none') { - // Check if any radio bots are in the Tent - const radioBot = voiceChannel.members.find(m => Object.keys(radioChannels).includes(m.user.id)); - if (!radioBot) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('There is already no radio in this Tent'); - } - // Find what radio bot is in the Tent and use the corresponding radio channel from the radioChannels object - // Check if the current channel has a radio bot in it - // by checking if any bots in the channel are in the radioChannels object - const botMember = voiceChannel.members - .find(member => member.user.bot && Object.keys(radioChannels).includes(member.user.id)); - if (botMember) { - // If it does, find the corresponding radio channel from the bot id and move the bot to it - const radioChannelId = radioChannels[botMember.user.id]; - // Get the radio channel from cache - const radioChannel = guild.channels.cache.get(radioChannelId) as VoiceChannel; - // If the radio channel exists, and is a voice channel, move the bot to it - if (radioChannel && radioChannel.type === ChannelType.GuildVoice) { - voiceChannel.members.forEach(member => { - if (member.user.bot) { - member.voice.setChannel(radioChannel.id); - } - }); - } - } - return embedTemplate() - .setTitle('Success') - .setColor(Colors.Green) - .setDescription('The radio has been returned to the radio room'); - } - - const station = voiceChannel.guild.members.cache.get(stationid) as GuildMember; - - // If the station returns invalid (not on the server) - if (!station) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('This radio wasn\'t found! Please report this to the mods'); - } - - // If the radio is offline - if (!station.voice.channel) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('This radio is currently offline, please report this to the mods'); - } - // If the radio is already in another Tent - if (station.voice.channel?.parent?.id === env.CATEGORY_CAMPGROUND && station.voice.channelId !== voiceChannel.id) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('This radio is already being borrowed in another Tent'); - } - // If the radio is already in the Tent - if (station.voice.channelId === voiceChannel.id) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription('This radio is already in your Tent'); - } - // If the radio is available, move it to the Tent - if (station.voice.channel?.parent?.id === env.CATEGORY_RADIO) { - await station.voice.setChannel(voiceChannel); - // Edit the corresponding radio channels name to indicate it is in use - // const radioChannelId = radioChannels[station.user.id]; - // const radioChannel = station.guild.channels.cache.get(radioChannelId) as VoiceChannel; - - return embedTemplate() - .setTitle('Success') - .setColor(Colors.Green) - .setDescription(`${station} has been borrowed to your Tent`); - } - // If the Tent already has a radio - // find its corresonding channel in the radioChannels object and move it back before moving the new radio in - const botMember = station.voice.channel.members - .find(member => member.user.bot && Object.keys(radioChannels).includes(member.user.id)); - if (botMember) { - // If it does, find the corresponding radio channel from the bot id and move the bot to it - const radioChannelId = radioChannels[botMember.user.id]; - // Get the radio channel from cache - const radioChannel = station.guild.channels.cache.get(radioChannelId) as VoiceChannel; - // If the radio channel exists, and is a voice channel, move the bot to it - if (radioChannel && radioChannel.type === ChannelType.GuildVoice) { - radioChannel.members.forEach((member: GuildMember) => { - if (member.user.bot) { - member.voice.setChannel(radioChannel); - } - }); - } - await station.voice.setChannel(voiceChannel); - } - - // log.debug(F, `${target.displayName} is now ${verb}`); - - return embedTemplate() - .setTitle('Success') - .setColor(Colors.Green) - .setDescription(`${station} has been borrowed to your Tent`); -} - -async function tentBitrate( - voiceChannel: VoiceBasedChannel, - bitrate: string, -):Promise { - const bitrateNumber = parseInt(bitrate, 10); - // Check if the bitrate is the same as the current bitrate - if (voiceChannel.bitrate === bitrateNumber * 1000) { - return embedTemplate() - .setTitle('Error') - .setColor(Colors.Red) - .setDescription(`The bitrate is already set to ${bitrate}kbps`); - } - // Change the bitrate - await voiceChannel.setBitrate(bitrateNumber * 1000); - return embedTemplate() - .setTitle('Success') - .setColor(Colors.Green) - .setDescription(`The bitrate has been set to ${bitrate}kbps`); -} - export const dVoice: SlashCommand = { data: new SlashCommandBuilder() .setName('voice') @@ -317,12 +186,22 @@ export const dVoice: SlashCommand = { .setName('name') .setDescription('The new name for your Tent') .setRequired(true))) + .addSubcommand(subcommand => subcommand + .setName('lock') + .setDescription('Lock/Unlock the Tent')) .addSubcommand(subcommand => subcommand .setName('hide') - .setDescription('Hide/Unhide the Tent from the channel list')) + .setDescription('Remove the Tent from the channel list')) + // .addSubcommand(subcommand => subcommand + // .setName('add') + // .setDescription('Allow a user to join your Tent when locked or hidden') + // .addUserOption(option => option + // .setName('target') + // .setDescription('The user to add/unadd') + // .setRequired(true))) .addSubcommand(subcommand => subcommand .setName('ban') - .setDescription('Ban/Unban and hide a user from your Tent') + .setDescription('Ban and disconnect a user from your Tent') .addUserOption(option => option .setName('target') .setDescription('The user to ban/unban') @@ -336,7 +215,7 @@ export const dVoice: SlashCommand = { .setRequired(true))) .addSubcommand(subcommand => subcommand .setName('cohost') - .setDescription('Make another member a co-host in your Tent') + .setDescription('Make another user able to use /voice commands') .addUserOption(option => option .setName('target') .setDescription('The user to make co-host') @@ -378,9 +257,9 @@ export const dVoice: SlashCommand = { const member = interaction.member as GuildMember; const target = interaction.options.getMember('target') as GuildMember; const newName = interaction.options.getString('name') as string; - const stationid = interaction.options.getString('station') as string; - const guild = interaction.guild as Guild; - const bitrate = interaction.options.getString('bitrate') as string; + // const stationid = interaction.options.getString('station') as string; + // const guild = interaction.guild as Guild; + // const bitrate = interaction.options.getString('bitrate') as string; const voiceChannel = member.voice.channel; let embed = embedTemplate() .setTitle('Error') @@ -411,25 +290,29 @@ export const dVoice: SlashCommand = { return false; } - // // Check if the target user is a moderator - // if (target.roles.cache.has(env.ROLE_MODERATOR)) { - // await interaction.editReply({ embeds: [embed.setDescription('You cannot ban a moderator!')] }); - // return false; - // } + // Check if the target user is a moderator + if (target && target.roles.cache.has(env.ROLE_MODERATOR)) { + await interaction.editReply({ embeds: [embed.setDescription('You cannot do that to a moderator!')] }); + return false; + } // log.debug(F, `Command: ${command}`); if (command === 'rename') { embed = await tentRename(voiceChannel, newName); } - // if (command === 'lock') { - // embed = await tentLock(voiceChannel); - // } + if (command === 'lock') { + embed = await tentLock(voiceChannel); + } if (command === 'hide') { embed = await tentHide(voiceChannel); } + // if (command === 'add') { + // embed = await tentAdd(voiceChannel, target); + // } + if (command === 'ban') { embed = await tentBan(voiceChannel, target); } @@ -442,14 +325,6 @@ export const dVoice: SlashCommand = { embed = await tentCohost(voiceChannel, target); } - if (command === 'radio') { - embed = await tentRadio(voiceChannel, stationid, guild); - } - - if (command === 'bitrate') { - embed = await tentBitrate(voiceChannel, bitrate); - } - await interaction.editReply({ embeds: [embed] }); return true; }, diff --git a/src/discord/events/guildMemberUpdate.ts b/src/discord/events/guildMemberUpdate.ts index 93e331274..5db5488f8 100644 --- a/src/discord/events/guildMemberUpdate.ts +++ b/src/discord/events/guildMemberUpdate.ts @@ -340,7 +340,7 @@ async function addedVerified( await channelLounge.send({ content: stripIndents`**${greeting}** - Be safe, have fun, /report any issues! + Be safe, have fun, and don't forget to visit the for more information! *${await topic()}*`, }); diff --git a/src/discord/utils/messageCommand.ts b/src/discord/utils/messageCommand.ts index 765af2869..93844506c 100644 --- a/src/discord/utils/messageCommand.ts +++ b/src/discord/utils/messageCommand.ts @@ -1,14 +1,10 @@ /* eslint-disable max-len */ import { - // ChannelType, Message, - // GuildTextBasedChannel, Role, PermissionResolvable, - // ThreadChannel, EmbedBuilder, - // TextChannel, } from 'discord.js'; import { stripIndents } from 'common-tags'; import { sleep } from '../commands/guild/d.bottest'; diff --git a/src/discord/utils/tents.ts b/src/discord/utils/tents.ts index 81b1413d1..39eadf185 100644 --- a/src/discord/utils/tents.ts +++ b/src/discord/utils/tents.ts @@ -107,7 +107,6 @@ export async function pitchTent( - You can pick up this role in - **Modify your tent** - - \`/voice radio\` - Borrow a radio bot for your tent - \`/voice bitrate\` - Change the bitrate of your tent - \`/voice rename\` - Choose a new name for your tent diff --git a/src/discord/utils/tripsitme.ts b/src/discord/utils/tripsitme.ts index d8ac8915c..cafe624f0 100644 --- a/src/discord/utils/tripsitme.ts +++ b/src/discord/utils/tripsitme.ts @@ -94,11 +94,11 @@ const mindsetRoles = [ env.ROLE_SOBER, ]; -// const otherRoles = [ -// env.ROLE_VERIFIED, -// ]; +const otherRoles = [ + env.ROLE_VERIFIED, +]; -const ignoredRoles = `${teamRoles},${colorRoles},${mindsetRoles}`; +const ignoredRoles = `${teamRoles},${colorRoles},${mindsetRoles},${otherRoles}`; const guildOnly = 'This must be performed in a guild!'; const memberOnly = 'This must be performed by a member of a guild!';