2021-05-30 14:04:58 -07:00
import {
// Discordeno deps
startBot , editBotStatus , editBotNickname ,
Intents , DiscordActivityTypes , DiscordButtonStyles , DiscordInteractionTypes ,
2021-11-11 19:23:36 -08:00
sendMessage , sendInteractionResponse , deleteMessage , getMessage , sendDirectMessage , getGuild , getUser ,
2021-05-30 14:04:58 -07:00
hasGuildPermissions ,
2021-11-11 19:23:36 -08:00
cache , botId , DebugArg , cacheHandlers ,
DiscordenoMessage , DiscordenoGuild ,
ButtonComponent , ActionRow , ButtonData ,
Embed , DiscordInteractionResponseTypes ,
2021-05-30 14:04:58 -07:00
// MySQL Driver deps
Client ,
// Log4Deno deps
LT , initLog , log
} from "./deps.ts" ;
2021-11-11 19:23:36 -08:00
import { BuildingLFG , ActiveLFG , GuildPrefixes , GuildModRoles , GuildCleanChannels } from "./src/mod.d.ts" ;
2021-05-30 14:04:58 -07:00
import intervals from "./src/intervals.ts" ;
import { LFGActivities } from "./src/games.ts" ;
import { JoinLeaveType } from "./src/lfgHandlers.d.ts" ;
2021-11-11 19:23:36 -08:00
import { handleLFGStep , handleMemberJoin , handleMemberLeave , urlToIds } from "./src/lfgHandlers.ts" ;
2021-06-02 09:27:05 -07:00
import { constantCmds , editBtns , lfgStepQuestions } from "./src/constantCmds.ts" ;
2021-11-11 19:23:36 -08:00
import { jsonParseBig , jsonStringifyBig } from "./src/utils.ts" ;
2021-05-30 14:04:58 -07:00
import { DEBUG , LOCALMODE } from "./flags.ts" ;
import config from "./config.ts" ;
// Initialize DB client
const dbClient = await new Client ( ) . connect ( {
hostname : LOCALMODE ? config.db.localhost : config.db.host ,
port : config.db.port ,
db : config.db.name ,
username : config.db.username ,
password : config.db.password
} ) ;
// Initialize logging client with folder to use for logs, needs --allow-write set on Deno startup
initLog ( "logs" , DEBUG ) ;
2021-06-02 09:27:05 -07:00
log ( LT . INFO , ` ${ config . name } Starting up . . . ` ) ;
2021-05-30 14:04:58 -07:00
// Handle idling out the active builders
const activeBuilders : Array < BuildingLFG > = [ ] ;
setInterval ( ( ) = > {
intervals . buildingTimeout ( activeBuilders ) ;
} , 1000 ) ;
2021-11-11 19:23:36 -08:00
const activeLFGPosts : Array < ActiveLFG > = jsonParseBig ( localStorage . getItem ( "activeLFGPosts" ) || "[]" ) ;
2021-05-30 14:04:58 -07:00
log ( LT . INFO , ` Loaded ${ activeLFGPosts . length } activeLFGPosts ` ) ;
setInterval ( ( ) = > {
intervals . lfgNotifier ( activeLFGPosts ) ;
} , 60000 ) ;
const guildPrefixes : Map < bigint , string > = new Map ( ) ;
const getGuildPrefixes = await dbClient . query ( "SELECT * FROM guild_prefix" ) ;
getGuildPrefixes . forEach ( ( g : GuildPrefixes ) = > {
guildPrefixes . set ( g . guildId , g . prefix ) ;
} ) ;
2021-11-11 19:23:36 -08:00
const guildModRoles : Map < bigint , bigint > = new Map ( ) ;
const getGuildModRoles = await dbClient . query ( "SELECT * FROM guild_mod_role" ) ;
getGuildModRoles . forEach ( ( g : GuildModRoles ) = > {
guildModRoles . set ( g . guildId , g . roleId ) ;
} ) ;
const cleanChannels : Map < bigint , Array < bigint > > = new Map ( ) ;
const getCleanChannels = await dbClient . query ( "SELECT * FROM guild_clean_channel" ) ;
getCleanChannels . forEach ( ( g : GuildCleanChannels ) = > {
const tempArr = cleanChannels . get ( g . guildId ) || [ ] ;
tempArr . push ( g . channelId ) ;
cleanChannels . set ( g . guildId , tempArr ) ;
} ) ;
2021-05-30 14:04:58 -07:00
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
// Start up the Discord Bot
startBot ( {
token : LOCALMODE ? config.localtoken : config.token ,
intents : [ Intents . GuildMessages , Intents . DirectMessages , Intents . Guilds ] ,
eventHandlers : {
ready : ( ) = > {
log ( LT . INFO , ` ${ config . name } Logged in! ` ) ;
editBotStatus ( {
activities : [ {
name : "Booting up . . ." ,
type : DiscordActivityTypes . Game ,
createdAt : new Date ( ) . getTime ( )
} ] ,
status : "online"
} ) ;
// Interval to rotate the status text every 30 seconds to show off more commands
2021-11-11 19:23:36 -08:00
setInterval ( async ( ) = > {
2021-05-30 14:04:58 -07:00
log ( LT . LOG , "Changing bot status" ) ;
try {
2021-11-11 19:23:36 -08:00
const cachedCount = await cacheHandlers . size ( "guilds" ) ;
2021-05-30 14:04:58 -07:00
// Wrapped in try-catch due to hard crash possible
editBotStatus ( {
activities : [ {
2021-11-11 19:23:36 -08:00
name : intervals.getRandomStatus ( cachedCount ) ,
2021-05-30 14:04:58 -07:00
type : DiscordActivityTypes . Game ,
createdAt : new Date ( ) . getTime ( )
} ] ,
status : "online"
} ) ;
} catch ( e ) {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to update status: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
}
} , 30000 ) ;
// Interval to update bot list stats every 24 hours
LOCALMODE ? log ( LT . INFO , "updateListStatistics not running" ) : setInterval ( ( ) = > {
log ( LT . LOG , "Updating all bot lists statistics" ) ;
intervals . updateListStatistics ( botId , cache . guilds . size ) ;
} , 86400000 ) ;
// setTimeout added to make sure the startup message does not error out
setTimeout ( ( ) = > {
LOCALMODE && editBotNickname ( config . devServer , ` LOCAL - ${ config . name } ` ) ;
LOCALMODE ? log ( LT . INFO , "updateListStatistics not running" ) : intervals . updateListStatistics ( botId , cache . guilds . size ) ;
editBotStatus ( {
activities : [ {
name : "Booting Complete" ,
type : DiscordActivityTypes . Game ,
createdAt : new Date ( ) . getTime ( )
} ] ,
status : "online"
} ) ;
sendMessage ( config . logChannel , ` ${ config . name } has started, running version ${ config . version } . ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
} , 1000 ) ;
} ,
guildCreate : ( guild : DiscordenoGuild ) = > {
2021-11-11 19:23:36 -08:00
log ( LT . LOG , ` Handling joining guild ${ jsonStringifyBig ( guild ) } ` ) ;
2021-05-30 14:04:58 -07:00
sendMessage ( config . logChannel , ` New guild joined: ${ guild . name } (id: ${ guild . id } ). This guild has ${ guild . memberCount } members! ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
} ,
2021-11-11 19:23:36 -08:00
guildDelete : async ( guild : DiscordenoGuild ) = > {
log ( LT . LOG , ` Handling leaving guild ${ jsonStringifyBig ( guild ) } ` ) ;
2021-05-30 14:04:58 -07:00
sendMessage ( config . logChannel , ` I have been removed from: ${ guild . name } (id: ${ guild . id } ). ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
2021-11-11 19:23:36 -08:00
try {
await dbClient . execute ( "DELETE FROM guild_prefix WHERE guildId = ?" , [ guild . id ] ) ;
await dbClient . execute ( "DELETE FROM guild_mod_role WHERE guildId = ?" , [ guild . id ] ) ;
await dbClient . execute ( "DELETE FROM guild_clean_channel WHERE guildId = ?" , [ guild . id ] ) ;
}
catch ( e ) {
log ( LT . WARN , ` Failed to remove guild from DB: ${ jsonStringifyBig ( e ) } ` ) ;
}
2021-05-30 14:04:58 -07:00
} ,
2021-11-11 19:23:36 -08:00
debug : ( dmsg : string | DebugArg , data? : string ) = > log ( LT . LOG , ` Debug Message | ${ jsonStringifyBig ( dmsg ) } | ${ jsonStringifyBig ( data ) } ` , false ) ,
2021-05-30 14:04:58 -07:00
messageCreate : async ( message : DiscordenoMessage ) = > {
// Ignore all other bots
if ( message . isBot ) return ;
const prefix = guildPrefixes . get ( message . guildId ) || config . prefix ;
// Handle messages not starting with the prefix
if ( message . content . indexOf ( prefix ) !== 0 ) {
// Mentions
2022-05-13 15:53:12 -07:00
if ( message . mentionedUserIds [ 0 ] === botId && ( message . content . trim ( ) . startsWith ( ` <@ ${ botId } > ` ) || message . content . trim ( ) . startsWith ( ` <@! ${ botId } > ` ) ) ) {
2021-05-30 14:04:58 -07:00
// Light telemetry to see how many times a command is being run
await dbClient . execute ( ` CALL INC_CNT("prefix"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
2022-05-13 15:53:12 -07:00
if ( message . content . trim ( ) === ` <@ ${ botId } > ` || message . content . trim ( ) === ` <@! ${ botId } > ` ) {
2021-05-30 14:04:58 -07:00
message . send ( {
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
title : ` Hello ${ message . member ? . username } , and thanks for using Group Up! ` ,
fields : [
{
name : ` My prefix in this guild is: \` ${ prefix } \` ` ,
value : "Mention me with a new prefix to change it."
}
]
2021-11-11 19:23:36 -08:00
} ]
2021-06-02 09:27:05 -07:00
} ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
2021-06-02 09:27:05 -07:00
else if ( await hasGuildPermissions ( message . guildId , message . authorId , [ "ADMINISTRATOR" ] ) ) {
2022-05-13 15:53:12 -07:00
const newPrefix = message . content . replace ( ` <@! ${ botId } > ` , "" ) . replace ( ` <@ ${ botId } > ` , "" ) . trim ( ) ;
2021-05-30 14:04:58 -07:00
if ( newPrefix . length <= 10 ) {
let success = true ;
if ( guildPrefixes . has ( message . guildId ) ) {
// Execute the DB update
await dbClient . execute ( "UPDATE guild_prefix SET prefix = ? WHERE guildId = ?" , [ newPrefix , message . guildId ] ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to insert into database: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
success = false ;
} ) ;
} else {
// Execute the DB insertion
await dbClient . execute ( "INSERT INTO guild_prefix(guildId,prefix) values(?,?)" , [ message . guildId , newPrefix ] ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to insert into database: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
success = false ;
} ) ;
}
if ( success ) {
guildPrefixes . set ( message . guildId , newPrefix ) ;
message . send ( {
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
fields : [
{
name : ` My prefix in this guild is now: \` ${ newPrefix } \` ` ,
value : "Mention me with a new prefix to change it."
}
]
2021-11-11 19:23:36 -08:00
} ]
2021-06-02 09:27:05 -07:00
} ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
} else {
message . send ( {
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
fields : [
{
name : "Something went wrong!" ,
value : ` My prefix is still \` ${ prefix } \` . Please try again, and if the problem persists, please report this to the developers using \` ${ prefix } report \` . `
}
]
2021-11-11 19:23:36 -08:00
} ]
2021-06-02 09:27:05 -07:00
} ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
} else {
message . send ( {
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
fields : [
{
name : "Prefix too long, please set a prefix less than 10 characters long." ,
value : "Mention me with a new prefix to change it."
}
]
2021-11-11 19:23:36 -08:00
} ]
2021-06-02 09:27:05 -07:00
} ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
}
return ;
}
// Other
const activeIdx = activeBuilders . findIndex ( x = > ( message . channelId === x . channelId && message . authorId === x . userId ) ) ;
if ( activeIdx > - 1 ) {
activeBuilders [ activeIdx ] . lastTouch = new Date ( ) ;
activeBuilders [ activeIdx ] = await handleLFGStep ( activeBuilders [ activeIdx ] , message . content ) ;
if ( activeBuilders [ activeIdx ] . step === "done" ) {
if ( message . member ) {
const memberJoined = handleMemberJoin ( activeBuilders [ activeIdx ] . lfgMsg . embeds [ 0 ] . fields || [ ] , message . member , false ) ;
const newTimestamp = new Date ( parseInt ( memberJoined . embed [ 1 ] . value . split ( "#" ) [ 1 ] ) ) ;
const newLfgUid = ALPHABET [ Math . floor ( Math . random ( ) * 26 ) ] + ALPHABET [ Math . floor ( Math . random ( ) * 26 ) ] ;
const tempMembers = memberJoined . embed [ 4 ] . name . split ( ":" ) [ 1 ] . split ( "/" ) ;
const currentMembers = parseInt ( tempMembers [ 0 ] ) ;
const maxMembers = parseInt ( tempMembers [ 1 ] ) ;
if ( activeBuilders [ activeIdx ] . editing ) {
if ( currentMembers > maxMembers ) {
const currentPeople = memberJoined . embed [ 4 ] . value . split ( "\n" ) ;
const newAlts = currentPeople . splice ( maxMembers ) ;
memberJoined . embed [ 4 ] . value = currentPeople . join ( "\n" ) || "None" ;
memberJoined . embed [ 5 ] . value = ` ${ newAlts . join ( "\n" ) } \ n ${ memberJoined . embed [ 5 ] . value === "None" ? "" : memberJoined . embed [ 5 ] . value } ` ;
memberJoined . embed [ 4 ] . name = ` Members Joined: ${ maxMembers } / ${ maxMembers } ` ;
}
}
await activeBuilders [ activeIdx ] . lfgMsg . edit ( {
content : "" ,
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
fields : memberJoined.embed ,
footer : {
text : ` Created by: ${ message . member . username } | ${ newLfgUid } ` ,
} ,
timestamp : newTimestamp.toISOString ( )
2021-11-11 19:23:36 -08:00
} ] ,
2021-05-30 14:04:58 -07:00
components : [
{
type : 1 ,
components : [
{
type : 2 ,
label : "Join" ,
customId : "active@join_group" ,
2021-11-11 19:23:36 -08:00
style : DiscordButtonStyles.Success
2021-05-30 14:04:58 -07:00
} ,
{
type : 2 ,
label : "Leave" ,
customId : "active@leave_group" ,
style : DiscordButtonStyles.Danger
} ,
{
type : 2 ,
label : "Join as Alternate" ,
customId : "active@alternate_group" ,
style : DiscordButtonStyles.Primary
}
]
}
]
2021-06-02 09:27:05 -07:00
} ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to edit message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
2021-11-11 19:23:36 -08:00
if ( activeBuilders [ activeIdx ] ) {
const activeLFGIdx = activeLFGPosts . findIndex ( lfg = > ( lfg . channelId === activeBuilders [ activeIdx ] . channelId && lfg . messageId === activeBuilders [ activeIdx ] . lfgMsg . id && lfg . ownerId === activeBuilders [ activeIdx ] . userId ) ) ;
if ( activeLFGIdx >= 0 ) {
activeLFGPosts [ activeLFGIdx ] . lfgUid = newLfgUid ;
activeLFGPosts [ activeLFGIdx ] . lfgTime = newTimestamp . getTime ( ) ;
activeLFGPosts [ activeLFGIdx ] . notified = false ;
activeLFGPosts [ activeLFGIdx ] . locked = false ;
} else {
activeLFGPosts . push ( {
messageId : activeBuilders [ activeIdx ] . lfgMsg . id ,
channelId : activeBuilders [ activeIdx ] . lfgMsg . channelId ,
ownerId : message.authorId ,
lfgUid : newLfgUid ,
lfgTime : newTimestamp.getTime ( ) ,
notified : false ,
locked : false
} ) ;
}
localStorage . setItem ( "activeLFGPosts" , jsonStringifyBig ( activeLFGPosts ) ) ;
}
2021-05-30 14:04:58 -07:00
}
2021-06-02 09:27:05 -07:00
await activeBuilders [ activeIdx ] . questionMsg . delete ( ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-06-02 09:27:05 -07:00
} ) ;
2021-05-30 14:04:58 -07:00
activeBuilders . splice ( activeIdx , 1 ) ;
}
2021-06-02 09:27:05 -07:00
await message . delete ( ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
return ;
}
// Should this get cleaned up?
const enabledCleanChannels = cleanChannels . get ( message . guildId ) ;
if ( enabledCleanChannels && enabledCleanChannels . length && enabledCleanChannels . indexOf ( message . channelId ) > - 1 ) {
message . delete ( "Cleaning Channel" ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
2021-06-02 09:27:05 -07:00
} ) ;
2021-11-11 19:23:36 -08:00
return ;
2021-05-30 14:04:58 -07:00
}
return ;
2021-11-11 19:23:36 -08:00
} else {
// User is sending a command, make sure its a lfg command if its being sent in a clean channel
const enabledCleanChannels = cleanChannels . get ( message . guildId ) ;
if ( enabledCleanChannels && enabledCleanChannels . length && enabledCleanChannels . indexOf ( message . channelId ) > - 1 && message . content . indexOf ( ` ${ prefix } lfg ` ) !== 0 ) {
message . delete ( "Cleaning Channel" ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
return ;
}
2021-05-30 14:04:58 -07:00
}
2021-11-11 19:23:36 -08:00
log ( LT . LOG , ` Handling message ${ jsonStringifyBig ( message ) } ` ) ;
2021-05-30 14:04:58 -07:00
// Split into standard command + args format
const args = message . content . slice ( prefix . length ) . trim ( ) . split ( /[ \n]+/g ) ;
const command = args . shift ( ) ? . toLowerCase ( ) ;
// All commands below here
// ping
// Its a ping test, what else do you want.
if ( command === "ping" ) {
// Light telemetry to see how many times a command is being run
dbClient . execute ( ` CALL INC_CNT("ping"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
// Calculates ping between sending a message and editing it, giving a nice round-trip latency.
try {
const m = await message . send ( {
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
title : "Ping?"
2021-11-11 19:23:36 -08:00
} ]
2021-05-30 14:04:58 -07:00
} ) ;
m . edit ( {
2021-11-11 19:23:36 -08:00
embeds : [ {
2021-05-30 14:04:58 -07:00
title : ` Pong! Latency is ${ m . timestamp - message . timestamp } ms. `
2021-11-11 19:23:36 -08:00
} ]
2021-05-30 14:04:58 -07:00
} ) ;
} catch ( e ) {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
}
}
// lfg
// Handles all LFG commands, creating, editing, deleting
else if ( command === "lfg" ) {
// Light telemetry to see how many times a command is being run
dbClient . execute ( ` CALL INC_CNT("lfg"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
2021-11-11 19:23:36 -08:00
const subcmd = ( args [ 0 ] || "help" ) . toLowerCase ( ) ;
2021-05-30 14:04:58 -07:00
const lfgUid = ( args [ 1 ] || "" ) . toUpperCase ( ) ;
// Learn how the LFG command works
if ( subcmd === "help" || subcmd === "h" || subcmd === "?" ) {
message . send ( constantCmds . lfgHelp ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
// Create a new LFG
else if ( subcmd === "create" || subcmd === "c" ) {
2021-06-02 09:27:05 -07:00
try {
const lfgMsg = await message . send ( ` Creating new LFG post for <@ ${ message . authorId } >. Please reply with the requested information and watch as your LFG post gets created! ` ) ;
const gameButtons : Array < ButtonComponent > = Object . keys ( LFGActivities ) . map ( game = > {
return {
type : 2 ,
label : game ,
customId : ` building@set_game# ${ game } ` ,
style : DiscordButtonStyles.Primary
} ;
} ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
const buttonComps : Array < ActionRow > = [ ] ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
const temp : Array < ActionRow [ " components " ] > = [ ] ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
gameButtons . forEach ( ( btn , idx ) = > {
if ( ! temp [ Math . floor ( idx / 5 ) ] ) {
temp [ Math . floor ( idx / 5 ) ] = [ btn ] ;
} else {
temp [ Math . floor ( idx / 5 ) ] . push ( btn ) ;
}
} ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
temp . forEach ( btns = > {
if ( btns . length && btns . length <= 5 ) {
buttonComps . push ( {
type : 1 ,
components : btns
} ) ;
}
} ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
const question = await message . send ( {
content : lfgStepQuestions.set_game ,
components : buttonComps
} ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
activeBuilders . push ( {
userId : message.authorId ,
channelId : message.channelId ,
step : "set_game" ,
lfgMsg : lfgMsg ,
questionMsg : question ,
lastTouch : new Date ( ) ,
maxIdle : 60 ,
editing : false
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
message . delete ( ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
catch ( e ) {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` LFG failed at step | create | ${ jsonStringifyBig ( e ) } ` ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
}
// Delete an existing LFG
else if ( subcmd === "delete" || subcmd === "d" ) {
2021-06-02 09:27:05 -07:00
try {
// User provided a Uid, use it
if ( lfgUid ) {
const matches = activeLFGPosts . filter ( lfg = > ( message . authorId === lfg . ownerId && message . channelId === lfg . channelId && lfgUid === lfg . lfgUid ) ) ;
// Found one, delete
if ( matches . length ) {
2021-11-11 19:23:36 -08:00
await deleteMessage ( matches [ 0 ] . channelId , matches [ 0 ] . messageId , "User requested LFG to be deleted." ) . catch ( e = > {
log ( LT . WARN , ` Failed to find message to delete | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
const lfgIdx = activeLFGPosts . findIndex ( lfg = > ( message . authorId === lfg . ownerId && message . channelId === lfg . channelId && lfgUid === lfg . lfgUid ) ) ;
activeLFGPosts . splice ( lfgIdx , 1 ) ;
2021-11-11 19:23:36 -08:00
localStorage . setItem ( "activeLFGPosts" , jsonStringifyBig ( activeLFGPosts ) ) ;
2021-06-02 09:27:05 -07:00
const m = await message . send ( constantCmds . lfgDelete3 ) ;
2021-11-11 19:23:36 -08:00
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
// Did not find one
else {
const m = await message . send ( constantCmds . lfgDelete1 ) ;
2021-11-11 19:23:36 -08:00
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
}
2021-06-02 09:27:05 -07:00
// User did not provide a Uid, find it automatically
2021-05-30 14:04:58 -07:00
else {
2021-06-02 09:27:05 -07:00
const matches = activeLFGPosts . filter ( lfg = > ( message . authorId === lfg . ownerId && message . channelId === lfg . channelId ) ) ;
// Found one, delete
if ( matches . length === 1 ) {
2021-11-11 19:23:36 -08:00
await deleteMessage ( matches [ 0 ] . channelId , matches [ 0 ] . messageId , "User requested LFG to be deleted." ) . catch ( e = > {
log ( LT . WARN , ` Failed to find message to delete | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
const lfgIdx = activeLFGPosts . findIndex ( lfg = > ( message . authorId === lfg . ownerId && message . channelId === lfg . channelId ) ) ;
activeLFGPosts . splice ( lfgIdx , 1 ) ;
2021-11-11 19:23:36 -08:00
localStorage . setItem ( "activeLFGPosts" , jsonStringifyBig ( activeLFGPosts ) ) ;
2021-06-02 09:27:05 -07:00
const m = await message . send ( constantCmds . lfgDelete3 ) ;
2021-11-11 19:23:36 -08:00
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
// Found multiple, notify user
else if ( matches . length ) {
const deleteMsg = constantCmds . lfgDelete2 ;
2021-11-11 19:23:36 -08:00
const deepCloningFailedSoThisIsTheSolution = constantCmds . lfgDelete2 . embeds [ 0 ] . fields [ 0 ] . value ;
2021-06-02 09:27:05 -07:00
matches . forEach ( mt = > {
2021-11-11 19:23:36 -08:00
deleteMsg . embeds [ 0 ] . fields [ 0 ] . value += ` [ ${ mt . lfgUid } ](https://discord.com/channels/ ${ message . guildId } / ${ mt . channelId } / ${ mt . messageId } ) \ n `
2021-06-02 09:27:05 -07:00
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
deleteMsg . embeds [ 0 ] . fields [ 0 ] . value += "\nThis message will self descruct in 30 seconds."
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
const m = await message . send ( deleteMsg ) ;
2021-11-11 19:23:36 -08:00
constantCmds . lfgDelete2 . embeds [ 0 ] . fields [ 0 ] . value = deepCloningFailedSoThisIsTheSolution ;
m . delete ( "Channel Cleanup" , 30000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 30000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
// Found none, notify user you cannot delete other's lfgs
else {
const m = await message . send ( constantCmds . lfgDelete1 ) ;
2021-11-11 19:23:36 -08:00
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
}
}
catch ( e ) {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` LFG failed at step | delete | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
}
}
// Edit an existing LFG
else if ( subcmd === "edit" || subcmd === "e" ) {
2021-06-02 09:27:05 -07:00
try {
// User provided a Uid, use it
if ( lfgUid ) {
const matches = activeLFGPosts . filter ( lfg = > ( message . authorId === lfg . ownerId && message . channelId === lfg . channelId && lfgUid === lfg . lfgUid ) ) ;
// Found one, edit
if ( matches . length ) {
const lfgMessage = await ( await getMessage ( matches [ 0 ] . channelId , matches [ 0 ] . messageId ) ) . edit ( {
content : ` Editing new LFG post for <@ ${ matches [ 0 ] . ownerId } >. Please reply with the requested information and watch as your LFG post gets edited! `
} ) ;
const question = await message . send ( {
content : "Please select an item to edit from the buttons below:" ,
components : [ {
type : 1 ,
components : editBtns
} ]
} ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
activeBuilders . push ( {
userId : matches [ 0 ] . ownerId ,
channelId : matches [ 0 ] . channelId ,
step : "edit_btn" ,
lfgMsg : lfgMessage ,
questionMsg : question ,
lastTouch : new Date ( ) ,
maxIdle : 60 ,
editing : true
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
message . delete ( ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
// Did not find one
else {
const m = await message . send ( constantCmds . lfgEdit1 ) ;
2021-11-11 19:23:36 -08:00
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
}
2021-06-02 09:27:05 -07:00
// User did not provide a Uid, find it automatically
else {
const matches = activeLFGPosts . filter ( lfg = > ( message . authorId === lfg . ownerId && message . channelId === lfg . channelId ) ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
// Found one, edit
if ( matches . length === 1 ) {
const lfgMessage = await ( await getMessage ( matches [ 0 ] . channelId , matches [ 0 ] . messageId ) ) . edit ( {
content : ` Editing new LFG post for <@ ${ matches [ 0 ] . ownerId } >. Please reply with the requested information and watch as your LFG post gets edited! `
} ) ;
const question = await message . send ( {
content : "Please select an item to edit from the buttons below:" ,
components : [ {
type : 1 ,
components : editBtns
} ]
} ) ;
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
activeBuilders . push ( {
userId : matches [ 0 ] . ownerId ,
channelId : matches [ 0 ] . channelId ,
step : "edit_btn" ,
lfgMsg : lfgMessage ,
questionMsg : question ,
lastTouch : new Date ( ) ,
maxIdle : 60 ,
editing : true
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
message . delete ( ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
// Found multiple, notify user
else if ( matches . length ) {
const deleteMsg = constantCmds . lfgEdit2 ;
2021-11-11 19:23:36 -08:00
const deepCloningFailedSoThisIsTheSolution = constantCmds . lfgEdit2 . embeds [ 0 ] . fields [ 0 ] . value ;
2021-06-02 09:27:05 -07:00
matches . forEach ( mt = > {
2021-11-11 19:23:36 -08:00
deleteMsg . embeds [ 0 ] . fields [ 0 ] . value += ` [ ${ mt . lfgUid } ](https://discord.com/channels/ ${ message . guildId } / ${ mt . channelId } / ${ mt . messageId } ) \ n `
2021-06-02 09:27:05 -07:00
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
deleteMsg . embeds [ 0 ] . fields [ 0 ] . value += "\nThis message will self descruct in 30 seconds."
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
const m = await message . send ( deleteMsg ) ;
2021-11-11 19:23:36 -08:00
constantCmds . lfgEdit2 . embeds [ 0 ] . fields [ 0 ] . value = deepCloningFailedSoThisIsTheSolution ;
m . delete ( "Channel Cleanup" , 30000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 30000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
2021-06-02 09:27:05 -07:00
// Found none, notify user you cannot edit other's lfgs
else {
const m = await message . send ( constantCmds . lfgEdit1 ) ;
2021-11-11 19:23:36 -08:00
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
}
}
}
catch ( e ) {
log ( LT . WARN , ` LFG failed at step | edit | ${ jsonStringifyBig ( e ) } ` ) ;
}
}
// Join a LFG on behalf of a user
// gu!lfg join [url] [join/leave/alternate] [member?]
else if ( subcmd === "join" || subcmd === "leave" || subcmd === "alternate" ) {
try {
const action = subcmd ;
const lfgIds = urlToIds ( args [ 1 ] || "" ) ;
const memberStr = args [ 2 ] || ` <@ ${ message . authorId } > ` ;
const member = await message . guild ? . members . get ( BigInt ( memberStr . substr ( 3 , memberStr . length - 4 ) ) ) ;
const modRole = guildModRoles . get ( message . guildId ) || 0 n ;
// Join yourself (or others if you are a guild mod) to an LFG
if ( lfgIds . guildId === message . guildId && member && ( member . id === message . authorId || message . guildMember ? . roles . includes ( modRole ) ) ) {
const lfgMessage = await getMessage ( lfgIds . channelId , lfgIds . messageId ) ;
const embeds = lfgMessage . embeds [ 0 ] . fields || [ ] ;
let results : JoinLeaveType = {
embed : [ ] ,
success : false ,
full : true ,
justFilled : false
} ;
let actionResp : string ;
switch ( action ) {
case "join" :
results = handleMemberJoin ( embeds , member , false ) ;
actionResp = "joined" ;
break ;
case "leave" :
results = handleMemberLeave ( embeds , member ) ;
actionResp = "left" ;
break ;
case "alternate" :
results = handleMemberJoin ( embeds , member , true ) ;
actionResp = "joined as alternate" ;
break ;
}
let resp : string ;
if ( results . success && lfgMessage . components ) {
const buttonRow : ActionRow = lfgMessage . components [ 0 ] as ActionRow ;
await lfgMessage . edit ( {
embeds : [ {
fields : results.embed ,
footer : lfgMessage.embeds [ 0 ] . footer ,
timestamp : lfgMessage.embeds [ 0 ] . timestamp
} ] ,
components : [ buttonRow ]
} ) ;
if ( results . justFilled ) {
const thisLFGPost = activeLFGPosts . filter ( lfg = > ( lfgMessage . id === lfg . messageId && lfgMessage . channelId === lfg . channelId ) ) [ 0 ] ;
const thisLFG = ( await getMessage ( thisLFGPost . channelId , thisLFGPost . messageId ) ) . embeds [ 0 ] . fields || [ ] ;
sendDirectMessage ( thisLFGPost . ownerId , {
embeds : [ {
title : ` Hello ${ ( await getUser ( thisLFGPost . ownerId ) ) . username } ! Your event in ${ lfgMessage . guild ? . name || ( await getGuild ( message . guildId , { counts :false , addToCache : false } )).name} has filled up! ` ,
fields : [
thisLFG [ 0 ] ,
{
name : "Your members are:" ,
value : thisLFG [ 4 ] . value
}
]
} ]
} ) ;
}
resp = ` Successfully ${ actionResp } LFG. ` ;
} else {
resp = ` Failed to ${ action } LFG. `
2021-06-02 09:27:05 -07:00
}
2021-11-11 19:23:36 -08:00
const m = await message . send ( {
embeds : [ {
title : resp
} ]
} ) ;
m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-05-30 14:04:58 -07:00
}
}
2021-06-02 09:27:05 -07:00
catch ( e ) {
2021-11-11 19:23:36 -08:00
log ( LT . WARN , ` Member Join/Leave/Alt command failed: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
const m = await message . send ( {
embeds : [ {
title : "Failed to find LFG."
} ]
} ) ;
m . delete ( "Channel Cleanup" , ) . catch ( e = > {
log ( LT . WARN , ` Failed to clean up joiner | joining on behalf | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to clean up joiner | joining on behalf | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
}
}
// Sets the mod role
else if ( subcmd === "set_mod_role" && ( await hasGuildPermissions ( message . guildId , message . authorId , [ "ADMINISTRATOR" ] ) ) ) {
const mentionedRole = args [ 1 ] || "" ;
const roleId = BigInt ( mentionedRole . substr ( 3 , mentionedRole . length - 4 ) ) ;
if ( message . guild ? . roles . has ( roleId ) ) {
let success = true ;
if ( guildModRoles . has ( message . guildId ) ) {
// Execute the DB update
await dbClient . execute ( "UPDATE guild_mod_role SET roleId = ? WHERE guildId = ?" , [ roleId , message . guildId ] ) . catch ( e = > {
log ( LT . ERROR , ` Failed to insert into database: ${ jsonStringifyBig ( e ) } ` ) ;
success = false ;
} ) ;
} else {
// Execute the DB insertion
await dbClient . execute ( "INSERT INTO guild_mod_role(guildId,roleId) values(?,?)" , [ message . guildId , roleId ] ) . catch ( e = > {
log ( LT . ERROR , ` Failed to insert into database: ${ jsonStringifyBig ( e ) } ` ) ;
success = false ;
} ) ;
}
if ( success ) {
guildModRoles . set ( message . guildId , roleId ) ;
message . send ( {
embeds : [ {
fields : [
{
name : "LFG Mod Role set successfully" ,
value : ` LFG Mod Role set to ${ args [ 1 ] } . `
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
} else {
message . send ( {
embeds : [ {
fields : [
{
name : "Something went wrong!" ,
value : "LFG Mod Role has been left unchanged."
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
}
} else {
if ( guildModRoles . has ( message . guildId ) ) {
message . send ( {
embeds : [ {
fields : [
{
name : "LFG Mod Role is currently set to:" ,
value : ` <@& ${ guildModRoles . get ( message . guildId ) } > `
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
} else {
message . send ( {
embeds : [ {
fields : [
{
name : "There is no LFG Mod Role set for this guild." ,
value : ` To set one, run this command again with the role mentioned. \ n \ nExample: \` ${ prefix } lfg set_mod_role @newModRole \` `
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
}
}
}
// Sets the channel cleaning up for LFG channels to keep LFG events visible and prevent conversations
else if ( subcmd === "set_clean_channel" && ( await hasGuildPermissions ( message . guildId , message . authorId , [ "ADMINISTRATOR" ] ) ) ) {
const cleanSetting = ( args [ 1 ] || "list" ) . toLowerCase ( ) ;
let success = true ;
if ( cleanSetting === "on" ) {
// Execute the DB insertion
await dbClient . execute ( "INSERT INTO guild_clean_channel(guildId,channelId) values(?,?)" , [ message . guildId , message . channelId ] ) . catch ( e = > {
log ( LT . ERROR , ` Failed to insert into database: ${ jsonStringifyBig ( e ) } ` ) ;
success = false ;
} ) ;
if ( success ) {
const tempArr = cleanChannels . get ( message . guildId ) || [ ] ;
tempArr . push ( message . channelId ) ;
cleanChannels . set ( message . guildId , tempArr ) ;
const m = await message . send ( {
embeds : [ {
fields : [
{
name : "Channel Cleaning turned ON." ,
value : "This message will self destruct in 5 seconds."
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
m && m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to clean up | set_clean_channel | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to clean up | set_clean_channel | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
} else {
message . send ( {
embeds : [ {
fields : [
{
name : "Something went wrong!" ,
value : "Channel Clean status left off."
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
}
} else if ( cleanSetting === "off" ) {
// turns clean off for channel
// Execute the DB insertion
await dbClient . execute ( "DELETE FROM guild_clean_channel WHERE guildId = ? AND channelId = ?" , [ message . guildId , message . channelId ] ) . catch ( e = > {
log ( LT . ERROR , ` Failed to delete from database: ${ jsonStringifyBig ( e ) } ` ) ;
success = false ;
} ) ;
if ( success ) {
let tempArr = cleanChannels . get ( message . guildId ) || [ ] ;
tempArr = tempArr . filter ( channelId = > channelId !== message . channelId ) ;
cleanChannels . set ( message . guildId , tempArr ) ;
const m = await message . send ( {
embeds : [ {
fields : [
{
name : "Channel Cleaning turned OFF." ,
value : "This message will self destruct in 5 seconds."
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
m && m . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to clean up | set_clean_channel | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
message . delete ( "Channel Cleanup" , 5000 ) . catch ( e = > {
log ( LT . WARN , ` Failed to clean up | set_clean_channel | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
} else {
message . send ( {
embeds : [ {
fields : [
{
name : "Something went wrong!" ,
value : "Channel Clean status left on."
}
]
} ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
}
} else if ( cleanSetting === "list" ) {
// send list of channels with clean on
let cleanChannelStr = "" ;
for ( const channelId of cleanChannels . get ( message . guildId ) || [ ] ) {
cleanChannelStr += ` <# ${ channelId } > \ n ` ;
}
cleanChannelStr = cleanChannelStr . substr ( 0 , cleanChannelStr . length - 1 ) ;
const tmpEmbed : Embed = { } ;
if ( cleanChannelStr ) {
tmpEmbed . fields = [
{
name : "Clean Channels enabled for this guild:" ,
value : cleanChannelStr
}
]
} else {
tmpEmbed . title = "No Clean Channels are enabled for this guild."
}
await message . send ( {
embeds : [ tmpEmbed ]
} ) . catch ( e = > {
log ( LT . WARN , ` Failed to send message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
2021-06-02 09:27:05 -07:00
}
2021-05-30 14:04:58 -07:00
}
}
// report or r (command that failed)
// Manually report something that screwed up
else if ( command === "report" || command === "r" ) {
// Light telemetry to see how many times a command is being run
dbClient . execute ( ` CALL INC_CNT("report"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
sendMessage ( config . reportChannel , ( "USER REPORT:\n" + args . join ( " " ) ) ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
message . send ( constantCmds . report ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
// version or v
// Returns version of the bot
else if ( command === "version" || command === "v" ) {
// Light telemetry to see how many times a command is being run
dbClient . execute ( ` CALL INC_CNT("version"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
message . send ( constantCmds . version ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
// info or i
// Info command, prints short desc on bot and some links
else if ( command === "info" || command === "i" ) {
// Light telemetry to see how many times a command is being run
dbClient . execute ( ` CALL INC_CNT("info"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
message . send ( constantCmds . info ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
// help or h or ?
// Help command, prints available commands
else if ( command === "help" || command === "h" || command === "?" ) {
// Light telemetry to see how many times a command is being run
dbClient . execute ( ` CALL INC_CNT("help"); ` ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to call stored procedure INC_CNT: ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
message . send ( constantCmds . help ) . catch ( e = > {
2021-11-11 19:23:36 -08:00
log ( LT . ERROR , ` Failed to send message: ${ jsonStringifyBig ( message ) } | ${ jsonStringifyBig ( e ) } ` ) ;
2021-05-30 14:04:58 -07:00
} ) ;
}
} ,
2021-11-11 19:23:36 -08:00
interactionCreate : async ( interact , member ) = > {
try {
if ( interact . type === DiscordInteractionTypes . MessageComponent ) {
if ( interact . message && interact . data && ( interact . data as ButtonData ) . customId && member ) {
log ( LT . INFO , ` Handling Button ${ ( interact . data as ButtonData ) . customId } ` ) ;
log ( LT . LOG , ` Button Data | ${ jsonStringifyBig ( interact ) } ` ) ;
sendInteractionResponse ( BigInt ( interact . id ) , interact . token , {
type : DiscordInteractionResponseTypes . DeferredUpdateMessage
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
const [ handler , stepInfo ] = ( interact . data as ButtonData ) . customId . split ( "@" ) ;
const [ action , value ] = stepInfo . split ( "#" ) ;
switch ( handler ) {
case "building" : {
await activeBuilders . some ( async ( x , i ) = > {
if ( x . channelId === BigInt ( interact . channelId || "0" ) && member && x . userId === BigInt ( member . id ) ) {
x . lastTouch = new Date ( ) ;
x = await handleLFGStep ( x , value ) ;
if ( x . step === "done" && x . lfgMsg . components ) {
const currentLFG = ( x . lfgMsg . embeds [ 0 ] . fields || [ ] ) ;
const newTimestamp = new Date ( parseInt ( currentLFG [ 1 ] . value . split ( "#" ) [ 1 ] ) ) ;
const newLfgUid = ALPHABET [ Math . floor ( Math . random ( ) * 26 ) ] + ALPHABET [ Math . floor ( Math . random ( ) * 26 ) ] ;
const tempMembers = currentLFG [ 4 ] . name . split ( ":" ) [ 1 ] . split ( "/" ) ;
const currentMembers = parseInt ( tempMembers [ 0 ] ) ;
const maxMembers = parseInt ( tempMembers [ 1 ] ) ;
const buttonRow : ActionRow = x . lfgMsg . components [ 0 ] as ActionRow ;
if ( currentMembers > maxMembers ) {
const currentPeople = currentLFG [ 4 ] . value . split ( "\n" ) ;
const newAlts = currentPeople . splice ( maxMembers - 1 ) ;
currentLFG [ 4 ] . value = currentPeople . join ( "\n" ) ;
currentLFG [ 5 ] . value = ` ${ newAlts . join ( "\n" ) } \ n ${ currentLFG [ 5 ] . value } ` ;
currentLFG [ 4 ] . name = ` Members Joined: ${ maxMembers } / ${ maxMembers } ` ;
}
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
await x . lfgMsg . edit ( {
content : "" ,
embeds : [ {
fields : currentLFG ,
footer : {
text : ` Created by: ${ member . username } | ${ newLfgUid } ` ,
} ,
timestamp : newTimestamp.toISOString ( )
} ] ,
components : [ buttonRow ]
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
const activeIdx = activeLFGPosts . findIndex ( lfg = > ( lfg . channelId === x . channelId && lfg . messageId === x . lfgMsg . id && lfg . ownerId === x . userId ) ) ;
activeLFGPosts [ activeIdx ] . lfgTime = newTimestamp . getTime ( ) ;
activeLFGPosts [ activeIdx ] . lfgUid = newLfgUid ;
localStorage . setItem ( "activeLFGPosts" , jsonStringifyBig ( activeLFGPosts ) ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
await activeBuilders [ i ] . questionMsg . delete ( ) . catch ( e = > {
log ( LT . WARN , ` Failed to delete message | ${ jsonStringifyBig ( e ) } ` ) ;
} ) ;
activeBuilders . splice ( i , 1 ) ;
} else {
activeBuilders [ i ] = x ;
}
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
return true ;
}
2021-05-30 14:04:58 -07:00
} ) ;
2021-11-11 19:23:36 -08:00
break ;
2021-05-30 14:04:58 -07:00
}
2021-11-11 19:23:36 -08:00
case "active" : {
const message = await getMessage ( BigInt ( interact . channelId || "0" ) , BigInt ( interact . message . id ) ) ;
const embeds = message . embeds [ 0 ] . fields || [ ] ;
let results : JoinLeaveType = {
embed : [ ] ,
success : false ,
full : true ,
justFilled : false
} ;
switch ( action ) {
case "join_group" :
results = handleMemberJoin ( embeds , member , false ) ;
break ;
case "leave_group" :
results = handleMemberLeave ( embeds , member ) ;
break ;
case "alternate_group" :
results = handleMemberJoin ( embeds , member , true ) ;
break ;
}
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
if ( results . success && message . components ) {
await message . edit ( {
embeds : [ {
fields : results.embed ,
footer : message.embeds [ 0 ] . footer ,
timestamp : message.embeds [ 0 ] . timestamp
} ] ,
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
if ( results . justFilled ) {
const thisLFGPost = activeLFGPosts . filter ( lfg = > ( message . id === lfg . messageId && message . channelId === lfg . channelId ) ) [ 0 ] ;
const thisLFG = ( await getMessage ( thisLFGPost . channelId , thisLFGPost . messageId ) ) . embeds [ 0 ] . fields || [ ] ;
sendDirectMessage ( thisLFGPost . ownerId , {
embeds : [ {
title : ` Hello ${ ( await getUser ( thisLFGPost . ownerId ) ) . username } ! Your event in ${ message . guild ? . name || ( await getGuild ( message . guildId , { counts :false , addToCache : false } )).name} has filled up! ` ,
fields : [
thisLFG [ 0 ] ,
{
name : "Your members are:" ,
value : thisLFG [ 4 ] . value
}
]
} ]
} ) ;
}
}
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
break ;
}
case "editing" : {
await activeBuilders . some ( async ( x , i ) = > {
if ( x . editing && x . channelId === BigInt ( interact . channelId || "0" ) && member && x . userId === BigInt ( member . id ) ) {
x . step = action ;
x . lastTouch = new Date ( ) ;
let nextQuestion = "" ;
const nextComponents : Array < ActionRow > = [ ] ;
switch ( action ) {
case "set_game" : {
nextQuestion = lfgStepQuestions . set_game ;
const gameButtons : Array < ButtonComponent > = Object . keys ( LFGActivities ) . map ( game = > {
return {
type : 2 ,
label : game ,
customId : ` building@set_game# ${ game } ` ,
style : DiscordButtonStyles.Primary
} ;
} ) ;
const temp : Array < ActionRow [ " components " ] > = [ ] ;
gameButtons . forEach ( ( btn , idx ) = > {
if ( ! temp [ Math . floor ( idx / 5 ) ] ) {
temp [ Math . floor ( idx / 5 ) ] = [ btn ] ;
} else {
temp [ Math . floor ( idx / 5 ) ] . push ( btn ) ;
}
} ) ;
temp . forEach ( btns = > {
if ( btns . length && btns . length <= 5 ) {
nextComponents . push ( {
type : 1 ,
components : btns
} ) ;
}
} ) ;
break ;
}
case "set_time" : {
nextQuestion = "Please enter the time of the activity:" ;
break ;
}
case "set_desc" : {
nextQuestion = "Please enter a description for the activity. Enter `none` to skip:" ;
break ;
}
default :
break ;
2021-05-30 14:04:58 -07:00
}
2021-11-11 19:23:36 -08:00
x . questionMsg = await x . questionMsg . edit ( {
content : nextQuestion ,
components : nextComponents
} ) ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
activeBuilders [ i ] = x ;
2021-05-30 14:04:58 -07:00
2021-11-11 19:23:36 -08:00
return true ;
}
} ) ;
break ;
}
default :
break ;
2021-05-30 14:04:58 -07:00
}
}
}
}
2021-11-11 19:23:36 -08:00
catch ( e ) {
log ( LT . ERROR , ` Interaction failed: ${ jsonStringifyBig ( interact ) } | ${ jsonStringifyBig ( member ) } | ${ jsonStringifyBig ( e ) } ` ) ;
}
2021-05-30 14:04:58 -07:00
}
}
} ) ;