2020-07-26 01:53:55 +02:00
import { PluginOptions } from "knub" ;
2021-06-22 02:49:31 +02:00
import { ConfigPreprocessorFn } from "knub/dist/config/configTypes" ;
import { GuildButtonRoles } from "../../data/GuildButtonRoles" ;
2020-10-01 01:43:38 +03:00
import { GuildReactionRoles } from "../../data/GuildReactionRoles" ;
import { GuildSavedMessages } from "../../data/GuildSavedMessages" ;
import { Queue } from "../../Queue" ;
2021-07-25 14:32:08 +02:00
import { isValidSnowflake } from "../../utils" ;
import { StrictValidationError } from "../../validatorUtils" ;
2021-06-06 23:51:32 +02:00
import { LogsPlugin } from "../Logs/LogsPlugin" ;
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint" ;
import { ClearReactionRolesCmd } from "./commands/ClearReactionRolesCmd" ;
2020-07-26 01:53:55 +02:00
import { InitReactionRolesCmd } from "./commands/InitReactionRolesCmd" ;
2021-06-06 23:51:32 +02:00
import { PostButtonRolesCmd } from "./commands/PostButtonRolesCmd" ;
2020-07-26 01:53:55 +02:00
import { RefreshReactionRolesCmd } from "./commands/RefreshReactionRolesCmd" ;
import { AddReactionRoleEvt } from "./events/AddReactionRoleEvt" ;
2021-06-06 04:57:05 +02:00
import { ButtonInteractionEvt } from "./events/ButtonInteractionEvt" ;
2021-06-08 04:34:32 +02:00
import { MessageDeletedEvt } from "./events/MessageDeletedEvt" ;
2021-06-06 23:51:32 +02:00
import { ConfigSchema , ReactionRolesPluginType } from "./types" ;
import { autoRefreshLoop } from "./util/autoRefreshLoop" ;
2021-06-22 02:49:31 +02:00
import { getRowCount } from "./util/splitButtonsIntoRows" ;
2020-07-26 01:53:55 +02:00
const MIN_AUTO_REFRESH = 1000 * 60 * 15 ; // 15min minimum, let's not abuse the API
const defaultOptions : PluginOptions < ReactionRolesPluginType > = {
config : {
2021-06-06 04:57:05 +02:00
button_groups : { } ,
2020-07-26 01:53:55 +02:00
auto_refresh_interval : MIN_AUTO_REFRESH ,
2020-08-30 00:49:44 +03:00
remove_user_reactions : true ,
2020-07-26 01:53:55 +02:00
can_manage : false ,
} ,
overrides : [
{
level : ">=100" ,
config : {
can_manage : true ,
} ,
} ,
] ,
} ;
2021-06-22 02:49:31 +02:00
const MAXIMUM_COMPONENT_ROWS = 5 ;
const configPreprocessor : ConfigPreprocessorFn < ReactionRolesPluginType > = options = > {
if ( options . config . button_groups ) {
for ( const [ groupName , group ] of Object . entries ( options . config . button_groups ) ) {
const defaultButtonNames = Object . keys ( group . default_buttons ) ;
const defaultButtons = Object . values ( group . default_buttons ) ;
const menuNames = Object . keys ( group . button_menus ? ? [ ] ) ;
const defaultBtnRowCount = getRowCount ( defaultButtons ) ;
if ( defaultBtnRowCount > MAXIMUM_COMPONENT_ROWS || defaultBtnRowCount === 0 ) {
throw new StrictValidationError ( [
` Invalid row count for default_buttons: You currently have ${ defaultBtnRowCount } , the maximum is 5. A new row is started automatically each 5 consecutive buttons. ` ,
] ) ;
}
for ( let i = 0 ; i < defaultButtons . length ; i ++ ) {
const defBtn = defaultButtons [ i ] ;
if ( ! menuNames . includes ( defBtn . role_or_menu ) && ! isValidSnowflake ( defBtn . role_or_menu ) ) {
throw new StrictValidationError ( [
` Invalid value for default_buttons/ ${ defaultButtonNames [ i ] } /role_or_menu: ${ defBtn . role_or_menu } is neither an existing menu nor a valid snowflake. ` ,
] ) ;
}
2021-07-01 00:30:48 +02:00
if ( ! defBtn . label && ! defBtn . emoji ) {
throw new StrictValidationError ( [
` Invalid values for default_buttons/ ${ defaultButtonNames [ i ] } /(label|emoji): Must have label, emoji or both set for the button to be valid. ` ,
] ) ;
}
2021-06-22 02:49:31 +02:00
}
for ( const [ menuName , menuButtonEntries ] of Object . entries ( group . button_menus ? ? [ ] ) ) {
const menuButtonNames = Object . keys ( menuButtonEntries ) ;
const menuButtons = Object . values ( menuButtonEntries ) ;
const menuButtonRowCount = getRowCount ( menuButtons ) ;
if ( menuButtonRowCount > MAXIMUM_COMPONENT_ROWS || menuButtonRowCount === 0 ) {
throw new StrictValidationError ( [
` Invalid row count for button_menus/ ${ menuName } : You currently have ${ menuButtonRowCount } , the maximum is 5. A new row is started automatically each 5 consecutive buttons. ` ,
] ) ;
}
for ( let i = 0 ; i < menuButtons . length ; i ++ ) {
const menuBtn = menuButtons [ i ] ;
if ( ! menuNames . includes ( menuBtn . role_or_menu ) && ! isValidSnowflake ( menuBtn . role_or_menu ) ) {
throw new StrictValidationError ( [
` Invalid value for button_menus/ ${ menuButtonNames [ i ] } /role_or_menu: ${ menuBtn . role_or_menu } is neither an existing menu nor a valid snowflake. ` ,
] ) ;
}
2021-07-01 00:30:48 +02:00
if ( ! menuBtn . label && ! menuBtn . emoji ) {
throw new StrictValidationError ( [
` Invalid values for default_buttons/ ${ defaultButtonNames [ i ] } /(label|emoji): Must have label, emoji or both set for the button to be valid. ` ,
] ) ;
}
2021-06-22 02:49:31 +02:00
}
}
}
}
return options ;
} ;
2021-05-23 14:35:16 +03:00
export const ReactionRolesPlugin = zeppelinGuildPlugin < ReactionRolesPluginType > ( ) ( {
name : "reaction_roles" ,
2020-07-30 13:08:06 +03:00
showInDocs : true ,
info : {
prettyName : "Reaction roles" ,
} ,
2021-08-18 19:33:22 +03:00
dependencies : ( ) = > [ LogsPlugin ] ,
2020-07-26 01:53:55 +02:00
configSchema : ConfigSchema ,
defaultOptions ,
// prettier-ignore
commands : [
RefreshReactionRolesCmd ,
ClearReactionRolesCmd ,
InitReactionRolesCmd ,
2021-06-06 04:57:05 +02:00
PostButtonRolesCmd ,
2020-07-26 01:53:55 +02:00
] ,
// prettier-ignore
events : [
AddReactionRoleEvt ,
2021-06-06 04:57:05 +02:00
ButtonInteractionEvt ,
2021-06-08 04:34:32 +02:00
MessageDeletedEvt ,
2020-07-26 01:53:55 +02:00
] ,
2021-06-22 02:49:31 +02:00
configPreprocessor ,
2020-07-26 01:53:55 +02:00
2021-05-23 17:13:11 +03:00
beforeLoad ( pluginData ) {
2020-07-26 01:53:55 +02:00
const { state , guild } = pluginData ;
state . reactionRoles = GuildReactionRoles . getGuildInstance ( guild . id ) ;
state . savedMessages = GuildSavedMessages . getGuildInstance ( guild . id ) ;
2021-06-08 04:34:32 +02:00
state . buttonRoles = GuildButtonRoles . getGuildInstance ( guild . id ) ;
2020-07-26 01:53:55 +02:00
state . reactionRemoveQueue = new Queue ( ) ;
state . roleChangeQueue = new Queue ( ) ;
state . pendingRoleChanges = new Map ( ) ;
state . pendingRefreshes = new Set ( ) ;
2021-05-23 17:13:11 +03:00
} ,
2020-07-26 01:53:55 +02:00
2021-05-23 17:13:11 +03:00
afterLoad ( pluginData ) {
2020-07-26 01:53:55 +02:00
let autoRefreshInterval = pluginData . config . get ( ) . auto_refresh_interval ;
if ( autoRefreshInterval != null ) {
autoRefreshInterval = Math . max ( MIN_AUTO_REFRESH , autoRefreshInterval ) ;
autoRefreshLoop ( pluginData , autoRefreshInterval ) ;
}
} ,
2021-05-23 14:35:16 +03:00
beforeUnload ( pluginData ) {
2020-07-26 01:53:55 +02:00
if ( pluginData . state . autoRefreshTimeout ) {
clearTimeout ( pluginData . state . autoRefreshTimeout ) ;
}
} ,
} ) ;