-
-
Notifications
You must be signed in to change notification settings - Fork 245
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #975 from TheBastionBot/dev
v10.4
- Loading branch information
Showing
12 changed files
with
293 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/*! | ||
* @author TRACTION (iamtraction) | ||
* @copyright 2022 | ||
*/ | ||
import { ChannelType, ChatInputCommandInteraction, PermissionFlagsBits } from "discord.js"; | ||
import { Client, Command } from "@bastion/tesseract"; | ||
|
||
import GuildModel from "../../models/Guild"; | ||
|
||
class AutoThreadsCommand extends Command { | ||
constructor() { | ||
super({ | ||
name: "auto-threads", | ||
description: "Configure auto threads in the server.", | ||
options: [], | ||
userPermissions: [ PermissionFlagsBits.ManageGuild ], | ||
}); | ||
} | ||
|
||
public async exec(interaction: ChatInputCommandInteraction<"cached">): Promise<unknown> { | ||
await interaction.deferReply(); | ||
|
||
// check whether the channel is valid | ||
if (interaction.channel.type !== ChannelType.GuildText) { | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadsInvalidChannel")); | ||
} | ||
|
||
const guildDocument = await GuildModel.findById(interaction.guildId); | ||
|
||
// disable auto threads | ||
if (guildDocument.autoThreadChannels?.includes(interaction.channelId)) { | ||
guildDocument.autoThreadChannels = []; | ||
|
||
await guildDocument.save(); | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadsDisable")); | ||
} | ||
|
||
// set rate limit before enabling auto threads | ||
if (interaction.channel.rateLimitPerUser < 5 ) { | ||
await interaction.channel.setRateLimitPerUser(5, "Auto Threads Channel"); | ||
} | ||
|
||
// enable auto threads | ||
guildDocument.autoThreadChannels = [ interaction.channelId ]; | ||
|
||
await guildDocument.save(); | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadsEnable", { channel: interaction.channel })); | ||
} | ||
} | ||
|
||
export = AutoThreadsCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/*! | ||
* @author TRACTION (iamtraction) | ||
* @copyright 2022 | ||
*/ | ||
import { ChatInputCommandInteraction } from "discord.js"; | ||
import { Client, Command, Logger } from "@bastion/tesseract"; | ||
|
||
class ThreadCloseCommand extends Command { | ||
constructor() { | ||
super({ | ||
name: "close", | ||
description: "Close and lock the thread.", | ||
options: [], | ||
}); | ||
} | ||
|
||
public async exec(interaction: ChatInputCommandInteraction<"cached">): Promise<unknown> { | ||
await interaction.deferReply({ ephemeral: true }); | ||
|
||
if (!interaction.channel.isThread()) { | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "commandThreadOnly")); | ||
} | ||
|
||
const starterMessage = await interaction.channel.fetchStarterMessage().catch(Logger.error); | ||
if (!starterMessage) { | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadFirstMessageError")); | ||
} | ||
|
||
if (starterMessage.author.id === interaction.user.id) { | ||
await interaction.channel.edit({ | ||
archived: true, | ||
locked: true, | ||
reason: `Requested by ${ interaction.user.tag }`, | ||
}); | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadArchive")); | ||
} | ||
|
||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadNoPerms")); | ||
} | ||
} | ||
|
||
export = ThreadCloseCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/*! | ||
* @author TRACTION (iamtraction) | ||
* @copyright 2022 | ||
*/ | ||
import { ApplicationCommandOptionType, ChatInputCommandInteraction } from "discord.js"; | ||
import { Client, Command, Logger } from "@bastion/tesseract"; | ||
|
||
class ThreadNameCommand extends Command { | ||
constructor() { | ||
super({ | ||
name: "name", | ||
description: "Change the name of the thread.", | ||
options: [ | ||
{ | ||
type: ApplicationCommandOptionType.String, | ||
name: "name", | ||
description: "The new name for the thread.", | ||
required: true, | ||
}, | ||
], | ||
}); | ||
} | ||
|
||
public async exec(interaction: ChatInputCommandInteraction<"cached">): Promise<unknown> { | ||
await interaction.deferReply({ ephemeral: true }); | ||
const name = interaction.options.getString("name"); | ||
|
||
if (!interaction.channel.isThread()) { | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "commandThreadOnly")); | ||
} | ||
|
||
const starterMessage = await interaction.channel.fetchStarterMessage().catch(Logger.error); | ||
if (!starterMessage) { | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadFirstMessageError")); | ||
} | ||
|
||
if (starterMessage.author.id === interaction.user.id) { | ||
await interaction.channel.setName(name, `Requested by ${ interaction.user.tag }`); | ||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadName", { name })); | ||
} | ||
|
||
return await interaction.editReply((interaction.client as Client).locales.getText(interaction.guildLocale, "autoThreadNoPerms")); | ||
} | ||
} | ||
|
||
export = ThreadNameCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/*! | ||
* @author TRACTION (iamtraction) | ||
* @copyright 2022 | ||
*/ | ||
import { GuildTextBasedChannel, MessageReaction, PartialMessageReaction, PartialUser, Snowflake, User } from "discord.js"; | ||
import { Listener } from "@bastion/tesseract"; | ||
|
||
import GuildModel from "../models/Guild"; | ||
import memcache from "../utils/memcache"; | ||
import { COLORS } from "../utils/constants"; | ||
|
||
class MessageReactionAddListener extends Listener<"messageReactionAdd"> { | ||
constructor() { | ||
super("messageReactionAdd"); | ||
} | ||
|
||
public async exec(reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser): Promise<void> { | ||
// check whether the reaction was of a star | ||
if (reaction.emoji.name !== "⭐") return; | ||
// check whether the message has the minimum reaction count | ||
if (reaction.count < 2) return; | ||
|
||
// check whether the message is already in starboard | ||
const starboardCache = memcache.get("starboard") as Map<Snowflake, Snowflake[]> || new Map<Snowflake, Snowflake[]>(); | ||
const guildStarboardCache = starboardCache.get(reaction.message.guildId); | ||
if (guildStarboardCache?.includes(reaction.message.id)) return; | ||
|
||
const guildDocument = await GuildModel.findById(reaction.message.guildId); | ||
|
||
// check whether the message has required number of reactions | ||
if (reaction.count < guildDocument.starboardThreshold) return; | ||
// find the starboard channel | ||
const starboardChannel = reaction.message.guild.channels.cache.get(guildDocument.starboardChannel) as GuildTextBasedChannel; | ||
|
||
// check whether starboard is enabled | ||
if (!starboardChannel) return; | ||
|
||
// fetch the message | ||
await reaction.message.fetch(); | ||
|
||
// check whether the message author is starring their own message | ||
if (reaction.message.author?.id === user.id) return; | ||
|
||
// extract image attachment from the message | ||
// although, it can be a video. | ||
// TODO: find a way to filter out videos. | ||
const imageAttachment = reaction.message.attachments.filter(a => Boolean(a.height && a.width)).first(); | ||
|
||
// check whether the message has any content | ||
if (!reaction.message.content && !imageAttachment) return; | ||
|
||
// post the message in the starboard | ||
await starboardChannel.send({ | ||
embeds: [ | ||
{ | ||
color: COLORS.YELLOW, | ||
author: { | ||
name: reaction.message.author?.tag, | ||
icon_url: reaction.message.member?.displayAvatarURL(), | ||
url: reaction.message.url, | ||
}, | ||
description: reaction.message.content, | ||
image: { | ||
url: imageAttachment?.url, | ||
}, | ||
footer: { | ||
text: "Starboard", | ||
}, | ||
}, | ||
], | ||
}); | ||
|
||
// update the starboard cache | ||
if (guildStarboardCache instanceof Array) { | ||
guildStarboardCache.push(reaction.message.id); | ||
} else { | ||
starboardCache.set(reaction.message.guildId, [ reaction.message.id ]); | ||
} | ||
memcache.set("starboard", starboardCache); | ||
} | ||
} | ||
|
||
export = MessageReactionAddListener; |
Oops, something went wrong.