2024-06-19 19:50:14 +00:00
const { App } = require ( '@slack/bolt' ) ;
2024-06-19 20:20:41 +00:00
const postgres = require ( 'postgres' ) ;
2024-06-19 19:50:14 +00:00
require ( 'dotenv' ) . config ( )
2024-06-19 22:07:29 +00:00
const sql = postgres ( {
2024-06-20 01:03:30 +00:00
host : '/var/run/postgresql' ,
2024-06-19 20:20:41 +00:00
database : 'haroon_slackmaster' ,
2024-06-20 01:03:30 +00:00
username : 'haroon'
2024-06-19 20:20:41 +00:00
} )
2024-06-19 19:50:14 +00:00
2024-06-20 01:03:30 +00:00
const BeginnerOpponents = require ( './opponents/beginner' ) ;
const AllOpponents = [
... BeginnerOpponents
]
2024-06-19 19:50:14 +00:00
const app = new App ( {
token : process . env . SLACK _BOT _TOKEN ,
signingSecret : process . env . SLACK _SIGNING _SECRET
} ) ;
2024-06-19 22:07:29 +00:00
async function initializeUser ( slackUserId ) {
let a = await sql ` SELECT * FROM users WHERE slack_id = ${ slackUserId } ; `
2024-06-19 20:20:41 +00:00
if ( a . length === 0 ) {
2024-06-19 22:07:29 +00:00
a = await sql ` INSERT INTO users (slack_id) VALUES ( ${ slackUserId } ) RETURNING *; `
2024-06-19 20:20:41 +00:00
}
2024-06-19 22:07:29 +00:00
return a [ 0 ] ;
}
app . use ( async ( ctx ) => {
2024-06-20 01:03:30 +00:00
await initializeUser ( ctx . context . userId )
2024-06-19 22:07:29 +00:00
2024-06-19 20:20:41 +00:00
await ctx . next ( )
} )
2024-06-19 19:50:14 +00:00
app . command ( '/chooseopponent' , async ( ctx ) => {
await ctx . ack ( ) ;
2024-06-20 01:03:30 +00:00
const user = await initializeUser ( ctx . body . user _id ) ;
if ( user . currentopponent != "None" ) {
const opponent = AllOpponents . find ( x => x . rawId == user . currentopponent )
return await ctx . respond ( {
response _type : 'ephemeral' ,
text : ` You are already in a battle with ${ opponent . name } . ` ,
blocks : [
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : ` *Battle Master:* You are already in a battle with * ${ opponent . name } *. Please finish your battle with them before proceeding.
$ { user . battlemessage } `
}
}
]
} )
}
2024-06-19 19:50:14 +00:00
await ctx . client . views . open ( {
trigger _id : ctx . body . trigger _id ,
view : {
2024-06-20 01:03:30 +00:00
"private_metadata" : ctx . payload . channel _id ,
2024-06-19 19:50:14 +00:00
"type" : "modal" ,
"callback_id" : "chooseopponent" ,
"title" : {
"type" : "plain_text" ,
"text" : "Choose an opponent" ,
"emoji" : true
} ,
"submit" : {
"type" : "plain_text" ,
"text" : "Choose" ,
"emoji" : true
} ,
"close" : {
"type" : "plain_text" ,
"text" : "Never mind" ,
"emoji" : true
} ,
"blocks" : [
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
2024-06-20 17:31:27 +00:00
"text" : ` *Battle Support*: Hiya <@ ${ ctx . body . user _id } >! What rank opponent would you like to battle against? \n \n Not sure yet? Don't worry! Just cancel out and view what opponents you can fight with \` /viewopponents \` ! `
2024-06-19 19:50:14 +00:00
}
} ,
{
"type" : "divider"
} ,
{
"type" : "input" ,
"element" : {
"type" : "radio_buttons" ,
"options" : [
{
"text" : {
"type" : "plain_text" ,
"text" : "Special" ,
"emoji" : true
} ,
"value" : "SPECIAL"
} ,
{
"text" : {
"type" : "plain_text" ,
"text" : "Beginner" ,
"emoji" : true
} ,
"value" : "BEGINNER"
} ,
{
"text" : {
"type" : "plain_text" ,
"text" : "Casual" ,
"emoji" : true
} ,
"value" : "CASUAL"
}
] ,
"action_id" : "rank-selection"
} ,
"label" : {
"type" : "plain_text" ,
"text" : "Choose a rank:" ,
"emoji" : true
}
}
]
}
} )
} ) ;
2024-06-19 22:07:29 +00:00
function generateProfile ( dbUser , slackUser ) {
return [
{
"type" : "section" ,
"fields" : [
{
"type" : "mrkdwn" ,
"text" : "*User:* " + slackUser . display _name _normalized
} ,
{
"type" : "mrkdwn" ,
"text" : "*Rank:* " + dbUser . rank
} ,
{
"type" : "mrkdwn" ,
"text" : "*Battle Power*: " + ( dbUser . health + dbUser . mindmg + dbUser . maxdmg )
} ,
{
"type" : "mrkdwn" ,
2024-06-21 19:30:56 +00:00
"text" : ` *Victories/Losses:* ${ dbUser . victories } / ${ dbUser . losses } ( ${ ( dbUser . victories / ( dbUser . victories + dbUser . losses ) ) * 100 || 0 } %) `
2024-06-19 22:07:29 +00:00
} ,
{
"type" : "mrkdwn" ,
"text" : "*Current Win Streak:* " + dbUser . curstreak
} ,
{
"type" : "mrkdwn" ,
"text" : "*Highest Win Streak*: " + dbUser . highstreak
}
] ,
"accessory" : {
"type" : "image" ,
"image_url" : slackUser . image _1024 ,
"alt_text" : "user profile"
}
} ,
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
"text" : ` *Base Health:* ${ dbUser . health } \n *Base Min Damage:* ${ dbUser . mindmg } \n *Base Max Damage:* ${ dbUser . maxdmg } `
}
}
]
}
app . command ( '/profile' , async ( ctx ) => {
await ctx . ack ( ) ;
const args = ctx . body . text . slice ( ) . split ( / +/g ) . filter ( x => x ) ;
let match ;
// If there is an argument and the first one is a Slack ping
if ( args . length && ( match = args [ 0 ] . match ( /\<\@(.+)\|(.+)>/ ) ) ) {
const mentionedUser = match [ 1 ] ;
const dbUser = await initializeUser ( mentionedUser ) ;
const slackUser = ( await ctx . client . users . info ( { user : mentionedUser } ) ) . user . profile ;
ctx . say ( {
"text" : ` @ ${ slackUser . display _name _normalized } 's profile ` ,
"blocks" : [
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
"text" : ` <@ ${ ctx . body . user _id } > ran \` /profile @ ${ slackUser . display _name _normalized } \` `
}
} ,
... generateProfile ( dbUser , slackUser )
]
} )
}
// If there is an argument but it isn't a Slack ping
else if ( args . length ) {
ctx . respond ( {
blocks : [
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : ` *Battle Master:* Greetings <@ ${ ctx . body . user _id } >. You have tried to view the profile of an invalid user. Please ensure you either send a user ping as an argument or provide no argument at all. `
}
}
]
} )
}
// There is no argument
else {
const dbUser = await initializeUser ( ctx . body . user _id ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . body . user _id } ) ) . user . profile ;
ctx . say ( {
"text" : ` @ ${ slackUser . display _name _normalized } 's profile ` ,
"blocks" : [
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
"text" : ` <@ ${ ctx . body . user _id } > ran \` /profile \` `
}
} ,
... generateProfile ( dbUser , slackUser )
]
} )
}
} )
2024-06-19 19:50:14 +00:00
app . view ( "chooseopponent" , async ( ctx ) => {
const { selected _option } = Object . values ( ctx . view . state . values ) [ 0 ] [ 'rank-selection' ] ;
const rank = selected _option . value ;
2024-06-19 20:27:12 +00:00
const messages = {
"SPECIAL" : ` *Battle Special*: Wasn't expecting to see ya here <@ ${ ctx . body . user . id } >... I guess you're up for a challenge huh? Alright then, who do ya wanna annoy today? ` ,
"BEGINNER" : ` *Battle Beginner*: Hey there <@ ${ ctx . body . user . id } >! Let's keep things simple, who do you want to battle against? ` ,
"CASUAL" : ` *Battle Casual*: Alright <@ ${ ctx . body . user . id } >, things are about to get a little bit tougher from here... Who do you feel like taking on today? `
}
2024-06-19 19:50:14 +00:00
await ctx . ack ( {
response _action : 'update' ,
view : {
2024-06-20 01:03:30 +00:00
"private_metadata" : ctx . payload . private _metadata ,
2024-06-19 19:50:14 +00:00
"type" : "modal" ,
"callback_id" : "chooseopponent-" + rank ,
"title" : {
"type" : "plain_text" ,
"text" : "Choose an opponent" ,
"emoji" : true
} ,
"submit" : {
"type" : "plain_text" ,
"text" : "Battle" ,
"emoji" : true
} ,
"close" : {
"type" : "plain_text" ,
"text" : "Never mind" ,
"emoji" : true
} ,
"blocks" : [
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
2024-06-19 20:27:12 +00:00
"text" : messages [ rank ] || ` *Battle Master*: Greetings <@ ${ ctx . body . user . id } >. Please choose an opponent from below to battle. `
2024-06-19 19:50:14 +00:00
}
} ,
{
"type" : "divider"
} ,
{
"type" : "input" ,
"element" : {
"type" : "static_select" ,
"options" : BeginnerOpponents . map ( opponent =>
2024-06-19 22:07:29 +00:00
( {
"text" : {
"type" : "plain_text" ,
"text" : ` ${ opponent . name } // ${ opponent . stats . health + opponent . stats . min + opponent . stats . max } Battle Power ` ,
"emoji" : true
} ,
"value" : opponent . rawId
} )
2024-06-19 19:50:14 +00:00
) ,
"action_id" : "opponents"
} ,
"label" : {
"type" : "plain_text" ,
"text" : "Choose an opponent:" ,
"emoji" : true
}
}
]
}
} )
} )
2024-06-19 20:20:41 +00:00
app . view ( "chooseopponent-BEGINNER" , async ( ctx ) => {
await ctx . ack ( ) ;
2024-06-20 01:03:30 +00:00
const channelId = ctx . view . private _metadata ;
const userId = ctx . context . userId ;
const slackUser = ( await ctx . client . users . info ( { user : userId } ) ) . user . profile ;
const opponent = BeginnerOpponents . find ( o => o . rawId == Object . values ( ctx . payload . state . values ) [ 0 ] . opponents . selected _option . value ) ;
const player = await initializeUser ( userId ) ;
await sql ` UPDATE users
SET playerhealth = $ { player . health } ,
playermin = $ { player . mindmg } ,
playermax = $ { player . maxdmg } ,
currentOpponent = $ { opponent . rawId } ,
opponenthealth = $ { opponent . stats . health } ,
opponentmin = $ { opponent . stats . min } ,
opponentmax = $ { opponent . stats . max }
WHERE slack _id = $ { userId } ; `
const msg = await ctx . client . chat . postMessage ( {
channel : channelId ,
text : ` ${ slackUser . display _name _normalized } started a battle against ${ opponent . name } . ` ,
blocks : [
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : opponent . intro . replaceAll ( "{player}" , slackUser . display _name _normalized )
2024-06-20 17:31:27 +00:00
} ,
2024-06-20 01:03:30 +00:00
"accessory" : {
"type" : "image" ,
"image_url" : opponent . image ,
"alt_text" : opponent . name
}
} ,
{
"type" : "actions" ,
"elements" : [
{
"type" : "button" ,
2024-06-20 17:31:27 +00:00
2024-06-20 01:03:30 +00:00
"text" : {
"type" : "plain_text" ,
"text" : "Continue" ,
"emoji" : true
} ,
2024-06-20 17:31:27 +00:00
"value" : userId ,
2024-06-20 01:03:30 +00:00
"action_id" : "continue"
}
]
}
]
} ) ;
2024-06-19 20:20:41 +00:00
2024-06-20 01:03:30 +00:00
await sql ` UPDATE users SET battlemessage = ${ ` https://hackclub.slack.com/archives/ ${ channelId } /p ${ msg . ts . replace ( '.' , '' ) } ` } WHERE slack_id = ${ userId } ; `
2024-06-19 20:20:41 +00:00
} )
2024-06-20 17:31:27 +00:00
async function checkButton ( ctx ) {
await ctx . ack ( ) ;
if ( ctx . payload . value != ctx . context . userId ) {
return ctx . respond ( {
replace _original : false ,
response _type : 'ephemeral' ,
text : "Battle Support: Please do not click other battlers buttons!" ,
blocks : [
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : ` *Battle Support:* Erm, <@ ${ ctx . context . userId } >?... Please don't press other battlers buttons!
If you want to choose an opponent yourself , simply use \ ` /chooseopponent \` to get started! `
}
}
]
} )
}
await ctx . next ( ) ;
2024-06-20 21:17:26 +00:00
}
2024-06-20 17:31:27 +00:00
2024-06-21 19:30:56 +00:00
function chooseAction ( chances ) {
const random = Math . random ( ) ;
let cumulative = 0 ;
2024-06-20 19:49:30 +00:00
2024-06-21 19:30:56 +00:00
for ( const action in chances ) {
cumulative += chances [ action ] ;
if ( random < cumulative ) {
return action ;
}
}
}
async function takeOutOfBattle ( slack _id ) {
return await sql ` UPDATE users SET
currentopponent = 'None' ,
playerhealth = NULL ,
playermin = NULL ,
playermax = NULL ,
playerdefense = NULL ,
playerdefendcount = 0 ,
opponenthealth = NULL ,
opponentmin = NULL ,
opponentmax = NULL ,
opponentdefense = NULL ,
opponentdefendcount = 0 ,
battlemessage = NULL
WHERE slack _id = $ { slack _id } ;
`
}
async function playerLoss ( ctx ) {
const user = await initializeUser ( ctx . context . userId ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . context . userId } ) ) . user . profile ;
await takeOutOfBattle ( ctx . context . userId ) ;
await sql `
UPDATE users
SET spoints = $ { user . spoints - 1 } ,
cshards = $ { user . cshards - 5 } ,
defeats = $ { user . defeats + 1 }
WHERE slack _id = $ { ctx . context . userId } ;
`
ctx . respond ( {
replace _original : true ,
text : ` ${ slackUser . display _name _normalized } lost against ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } ` ,
"blocks" : [
{
"type" : "context" ,
"elements" : [
{
"type" : "mrkdwn" ,
"text" : "*DEFEAT :trophy:*"
}
]
} ,
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
"text" : ` Oh no ${ slackUser . display _name _normalized } ... You've been defeated by ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } ... Don't give up! There's always room for improvement! \n \n \n Losses:* \n > -1 Skill Point \n >-5 Creation Shards \n > 1 Defeat `
} ,
"accessory" : {
"type" : "image" ,
"image_url" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . image ,
"alt_text" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . name
}
}
]
} )
}
async function playerWin ( ctx ) {
const user = await initializeUser ( ctx . context . userId ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . context . userId } ) ) . user . profile ;
await takeOutOfBattle ( ctx . context . userId ) ;
await sql `
UPDATE users
SET spoints = $ { user . spoints + 1 } ,
cshards = $ { user . cshards + 5 } ,
victories = $ { user . victories + 1 }
WHERE slack _id = $ { ctx . context . userId } ;
`
ctx . respond ( {
replace _original : true ,
text : ` ${ slackUser . display _name _normalized } won against ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } ` ,
"blocks" : [
{
"type" : "context" ,
"elements" : [
{
"type" : "mrkdwn" ,
"text" : "*YOU WON! :trophy:*"
}
]
} ,
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
"text" : ` Congratulations ${ slackUser . display _name _normalized } ! You have defeated ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } in battle! Good job! \n \n \n *Rewards:* \n > 1 Skill Point \n >5 Creation Shards \n > 1 Victory `
} ,
"accessory" : {
"type" : "image" ,
"image_url" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . image ,
"alt_text" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . name
}
}
]
} )
}
2024-06-20 19:49:30 +00:00
2024-06-20 17:31:27 +00:00
app . action ( "continue" , checkButton , async ( ctx ) => {
const user = await initializeUser ( ctx . context . userId ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . context . userId } ) ) . user . profile ;
2024-06-20 19:49:30 +00:00
if ( user . playerhealth <= 0 ) {
return playerLoss ( ctx )
}
2024-06-20 17:31:27 +00:00
ctx . respond ( {
replace _original : true ,
text : "" ,
"blocks" : [
{
"type" : "section" ,
"fields" : [
{
"type" : "mrkdwn" ,
2024-06-20 19:49:30 +00:00
"text" : ` ${ slackUser . display _name _normalized } : \n \n *Health:* ${ user . playerhealth } \n *Min Damage:* ${ user . playermin } \n *Max Damage:* ${ user . playermax } `
2024-06-20 17:31:27 +00:00
} ,
{
"type" : "mrkdwn" ,
2024-06-20 21:17:26 +00:00
"text" : ` ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } : \n \n *Health:* ${ user . opponenthealth } \n *Min Damage:* ${ user . opponentmin } \n *Max Damage:* ${ user . opponentmax } `
2024-06-20 17:31:27 +00:00
}
] ,
"accessory" : {
"type" : "image" ,
2024-06-20 21:17:26 +00:00
"image_url" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . image ,
"alt_text" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . name
2024-06-20 17:31:27 +00:00
}
} ,
{
"type" : "context" ,
"elements" : [
{
"type" : "mrkdwn" ,
2024-06-20 21:17:26 +00:00
"text" : ` * ${ slackUser . display _name _normalized } * vs * ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } * | Your Turn `
2024-06-20 17:31:27 +00:00
}
]
} ,
{
"type" : "actions" ,
"elements" : [
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : "⚔️ Attack" ,
"emoji" : true
} ,
"value" : ctx . context . userId ,
"action_id" : "attack"
} ,
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : "🛡️ Defend" ,
"emoji" : true
} ,
"value" : ctx . context . userId ,
"action_id" : "defend"
} ,
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : " 🎁 Item" ,
"emoji" : true
} ,
"value" : ctx . context . userId ,
"action_id" : "item"
} ,
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : "☠️ Forfeit" ,
"emoji" : true
} ,
"style" : "danger" ,
"value" : ctx . context . userId ,
2024-06-20 19:49:30 +00:00
"action_id" : "forfeit"
2024-06-20 17:31:27 +00:00
}
]
2024-06-20 21:17:26 +00:00
}
2024-06-20 17:31:27 +00:00
]
} )
} )
2024-06-20 19:49:30 +00:00
app . action ( 'forfeit' , checkButton , async ( ctx ) => {
ctx . respond ( {
replace _original : false ,
response _type : 'ephemeral' ,
2024-06-21 19:30:56 +00:00
text : 'Not yet...' ,
2024-06-20 19:49:30 +00:00
} )
} )
app . action ( /attack|defend|item/ , checkButton , async ( ctx ) => {
2024-06-20 21:17:26 +00:00
let response = "This error message isn't meant to show up. If it does, contact Haroon." ;
2024-06-20 19:49:30 +00:00
const user = await initializeUser ( ctx . context . userId ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . context . userId } ) ) . user . profile ;
switch ( ctx . payload . action _id ) {
case 'attack' :
if ( user . opponentdefense == 'Strong' ) {
2024-06-20 21:17:26 +00:00
response = ` *_ ${ slackUser . display _name _normalized } attacks ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` NO DAMAGE \` \` \` `
2024-06-20 19:49:30 +00:00
} else if ( user . opponentdefense == 'Moderate' ) {
if ( Math . random ( ) < 0.5 ) {
2024-06-20 21:17:26 +00:00
response = ` *_ ${ slackUser . display _name _normalized } attacks ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` NO DAMAGE \` \` \` `
2024-06-20 19:49:30 +00:00
} else {
2024-06-20 21:17:26 +00:00
const damage = Math . floor ( Math . random ( ) * ( user . playermax - user . playermin + 1 ) ) + user . playermin ;
2024-06-20 19:49:30 +00:00
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth - damage } WHERE slack_id = ${ ctx . context . userId } ; `
2024-06-20 21:17:26 +00:00
response = ` *_ ${ slackUser . display _name _normalized } attacks ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` ${ damage . toLocaleString ( ) } DAMAGE \` \` \` `
2024-06-20 19:49:30 +00:00
}
} else if ( user . opponentdefense == 'Weak' ) {
if ( Math . random ( ) < 0.25 ) {
2024-06-20 21:17:26 +00:00
response = ` *_ ${ slackUser . display _name _normalized } attacks ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` NO DAMAGE \` \` \` `
2024-06-20 19:49:30 +00:00
} else {
2024-06-20 21:17:26 +00:00
const damage = Math . floor ( Math . random ( ) * ( user . playermax - user . playermin + 1 ) ) + user . playermin ;
2024-06-20 19:49:30 +00:00
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth - damage } WHERE slack_id = ${ ctx . context . userId } ; `
2024-06-20 21:17:26 +00:00
response = ` *_ ${ slackUser . display _name _normalized } attacks ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` ${ damage . toLocaleString ( ) } DAMAGE \` \` \` `
}
} else {
const damage = Math . floor ( Math . random ( ) * ( user . playermax - user . playermin + 1 ) ) + user . playermin ;
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth - damage } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ slackUser . display _name _normalized } attacks ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` ${ damage . toLocaleString ( ) } DAMAGE \` \` \` `
}
break ;
case 'defend' :
if ( user . playerdefendcount < 3 ) {
await sql ` UPDATE users SET playerdefense = 'Strong' WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_A blue forcefield magically appears around ${ slackUser . display _name _normalized } _* \n \n \` \` \` STRONG DEFENCE \` \` \` `
} else {
const type = [ "Strong" , "Moderate" , "Weak" ] [ Math . floor ( Math . random ( ) * 3 ) ] ;
await sql ` UPDATE users SET playerdefense = ${ type } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_A blue forcefield magically appears around ${ slackUser . display _name _normalized } _* \n \n \` \` \` ${ type . toUpperCase ( ) } DEFENCE \` \` \` `
2024-06-20 19:49:30 +00:00
}
2024-06-21 19:30:56 +00:00
await sql ` UPDATE users SET playerdefendcount = ${ user . opponentdefendcount + 1 } WHERE slack_id = ${ ctx . context . userId } ; `
2024-06-20 19:49:30 +00:00
break ;
2024-06-20 21:17:26 +00:00
case 'item' :
const increase = Math . floor ( Math . random ( ) * 5 ) + 1 ;
switch ( [ 'health' , 'min' , 'max' , 'nothing' ] [ Math . floor ( Math . random ( ) * 4 ) ] ) {
case 'health' :
await sql ` UPDATE users SET playerhealth = ${ user . playerhealth + increase } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ slackUser . display _name _normalized } drinks some squash. U N D I L U T E D._* \n \n \` \` \` + ${ increase } HEALTH \` \` \` `
break ;
case 'min' :
if ( ( user . playermin + increase ) < user . playermax ) {
response = ` *_ ${ slackUser . display _name _normalized } touches some grass_* \n \n \` \` \` NOTHING HAPPENED \` \` \` `
break ;
}
await sql ` UPDATE users SET playermin = ${ user . playermin + increase } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ slackUser . display _name _normalized } drinks some squash. U N D I L U T E D._* \n \n \` \` \` + ${ increase } MIN DAMAGE \` \` \` `
break ;
case 'max' :
await sql ` UPDATE users SET playermax = ${ user . playermax + increase } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ slackUser . display _name _normalized } drinks some squash. U N D I L U T E D._* \n \n \` \` \` + ${ increase } MAX DAMAGE \` \` \` `
break ;
case 'nothing' :
response = ` *_ ${ slackUser . display _name _normalized } touches some grass_* \n \n \` \` \` NOTHING HAPPENED \` \` \` `
2024-06-21 19:30:56 +00:00
break ;
2024-06-20 21:17:26 +00:00
}
2024-06-20 19:49:30 +00:00
}
2024-06-20 21:17:26 +00:00
await sql ` UPDATE users SET opponentdefense = 'None' WHERE slack_id = ${ ctx . context . userId } ; `
2024-06-20 19:49:30 +00:00
await ctx . respond ( {
"blocks" : [
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
2024-06-20 21:17:26 +00:00
"text" : response
2024-06-20 19:49:30 +00:00
}
} ,
{
"type" : "actions" ,
"elements" : [
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : "Continue" ,
"emoji" : true
} ,
"value" : ctx . context . userId ,
"action_id" : "continue-opponent"
}
]
}
]
2024-06-20 21:17:26 +00:00
} )
2024-06-20 19:49:30 +00:00
} )
2024-06-21 19:30:56 +00:00
app . action ( "continue-opponent" , checkButton , async ( ctx ) => {
const user = await initializeUser ( ctx . context . userId ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . context . userId } ) ) . user . profile ;
if ( user . opponenthealth <= 0 ) {
return playerWin ( ctx )
}
ctx . respond ( {
replace _original : true ,
text : "" ,
"blocks" : [
{
"type" : "section" ,
"fields" : [
{
"type" : "mrkdwn" ,
"text" : ` ${ slackUser . display _name _normalized } : \n \n *Health:* ${ user . playerhealth } \n *Min Damage:* ${ user . playermin } \n *Max Damage:* ${ user . playermax } `
} ,
{
"type" : "mrkdwn" ,
"text" : ` ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } : \n \n *Health:* ${ user . opponenthealth } \n *Min Damage:* ${ user . opponentmin } \n *Max Damage:* ${ user . opponentmax } `
}
] ,
"accessory" : {
"type" : "image" ,
"image_url" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . image ,
"alt_text" : AllOpponents . find ( x => x . rawId == user . currentopponent ) . name
}
} ,
{
"type" : "context" ,
"elements" : [
{
"type" : "mrkdwn" ,
"text" : ` * ${ slackUser . display _name _normalized } * vs * ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } * | ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } 's Turn `
}
]
} ,
{
"type" : "actions" ,
"elements" : [
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : "Continue" ,
"emoji" : true
} ,
"value" : ctx . context . userId ,
"action_id" : "viewaction-opponent"
}
]
}
]
} )
} )
app . action ( 'viewaction-opponent' , checkButton , async ( ctx ) => {
let response = "This error message isn't meant to show up. If it does, contact Haroon." ;
const user = await initializeUser ( ctx . context . userId ) ;
const slackUser = ( await ctx . client . users . info ( { user : ctx . context . userId } ) ) . user . profile ;
const chances = AllOpponents . find ( x => x . rawId == user . currentopponent ) . chances ;
const action = chooseAction ( chances ) ;
switch ( action ) {
case 'attack' :
if ( user . playerdefense == 'Strong' ) {
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } attacks ${ slackUser . display _name _normalized } _* \n \n \` \` \` NO DAMAGE \` \` \` `
} else if ( user . playerdefense == 'Moderate' ) {
if ( Math . random ( ) < 0.5 ) {
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } attacks ${ slackUser . display _name _normalized } _* \n \n \` \` \` NO DAMAGE \` \` \` `
} else {
const damage = Math . floor ( Math . random ( ) * ( user . opponentmax - user . opponentmin + 1 ) ) + user . opponentmin ;
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth - damage } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } attacks ${ slackUser . display _name _normalized } _* \n \n \` \` \` ${ damage . toLocaleString ( ) } DAMAGE \` \` \` `
}
} else if ( user . playerdefense == 'Weak' ) {
if ( Math . random ( ) < 0.25 ) {
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } attacks ${ lackUser . display _name _normalized } _* \n \n \` \` \` NO DAMAGE \` \` \` `
} else {
const damage = Math . floor ( Math . random ( ) * ( user . playermax - user . playermin + 1 ) ) + user . playermin ;
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth - damage } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } attacks ${ slackUser . display _name _normalized } _* \n \n \` \` \` ${ damage . toLocaleString ( ) } DAMAGE \` \` \` `
}
} else {
const damage = Math . floor ( Math . random ( ) * ( user . playermax - user . playermin + 1 ) ) + user . playermin ;
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth - damage } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } attacks ${ slackUser . display _name _normalized } _* \n \n \` \` \` ${ damage . toLocaleString ( ) } DAMAGE \` \` \` `
}
break ;
case 'defend' :
if ( user . opponentdefendcount < 3 ) {
await sql ` UPDATE users SET opponentdefense = 'Strong' WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_A blue forcefield magically appears around ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` STRONG DEFENCE \` \` \` `
} else {
const type = [ "Strong" , "Moderate" , "Weak" ] [ Math . floor ( Math . random ( ) * 3 ) ] ;
await sql ` UPDATE users SET opponentdefense = ${ type } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_A blue forcefield magically appears around ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } _* \n \n \` \` \` ${ type . toUpperCase ( ) } DEFENCE \` \` \` `
}
await sql ` UPDATE users SET opponentdefendcount = ${ user . opponentdefendcount + 1 } WHERE slack_id = ${ ctx . context . userId } ; `
break ;
case 'item' :
const increase = Math . floor ( Math . random ( ) * 5 ) + 1 ;
switch ( [ 'health' , 'min' , 'max' , 'nothing' ] [ Math . floor ( Math . random ( ) * 4 ) ] ) {
case 'health' :
await sql ` UPDATE users SET opponenthealth = ${ user . opponenthealth + increase } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } drinks some squash. U N D I L U T E D._* \n \n \` \` \` + ${ increase } HEALTH \` \` \` `
break ;
case 'min' :
if ( ( user . opponentmin + increase ) < user . opponentmax ) {
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } touches some grass_* \n \n \` \` \` NOTHING HAPPENED \` \` \` `
break ;
}
await sql ` UPDATE users SET opponentmin = ${ user . opponentmin + increase } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } drinks some squash. U N D I L U T E D._* \n \n \` \` \` + ${ increase } MIN DAMAGE \` \` \` `
break ;
case 'max' :
await sql ` UPDATE users SET opponentmax = ${ user . opponentmax + increase } WHERE slack_id = ${ ctx . context . userId } ; `
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } drinks some squash. U N D I L U T E D._* \n \n \` \` \` + ${ increase } MAX DAMAGE \` \` \` `
break ;
case 'nothing' :
response = ` *_ ${ AllOpponents . find ( x => x . rawId == user . currentopponent ) . name } touches some grass_* \n \n \` \` \` NOTHING HAPPENED \` \` \` `
break ;
}
}
await sql ` UPDATE users SET playerdefense = 'None' WHERE slack_id = ${ ctx . context . userId } ; `
2024-06-20 19:49:30 +00:00
2024-06-21 19:30:56 +00:00
await ctx . respond ( {
"blocks" : [
{
"type" : "section" ,
"text" : {
"type" : "mrkdwn" ,
"text" : response
}
} ,
{
"type" : "actions" ,
"elements" : [
{
"type" : "button" ,
"text" : {
"type" : "plain_text" ,
"text" : "Continue" ,
"emoji" : true
} ,
"value" : ctx . context . userId ,
"action_id" : "continue"
}
]
}
]
} )
} )
2024-06-20 19:49:30 +00:00
2024-06-19 20:49:07 +00:00
app . command ( '/bm-eval' , async ( ctx ) => {
await ctx . ack ( ) ;
2024-06-20 21:17:26 +00:00
if ( ctx . context . userId != 'U06TBP41C3E' ) return ;
2024-06-19 20:49:07 +00:00
const resp = require ( 'util' ) . inspect ( await eval ( ctx . body . text ) , undefined , 1 )
ctx . respond ( {
text : resp ,
response _type : 'ephemeral' ,
blocks : [
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : "```" + resp + "```"
}
}
]
} )
} )
2024-06-19 19:50:14 +00:00
app . command ( '/viewopponents' , async ( ctx ) => {
await ctx . ack ( ) ;
2024-06-19 22:07:29 +00:00
const args = ctx . body . text . slice ( ) . split ( / +/g ) ;
2024-06-19 19:50:14 +00:00
switch ( args [ 0 ] . toUpperCase ( ) ) {
case "SPECIAL" :
ctx . respond ( {
text : "You're trying to view Special opponents." ,
response _type : 'ephemeral'
} )
break ;
case "BEGINNER" :
const mappedBeginner = BeginnerOpponents . map ( opponent =>
( {
name : opponent . name ,
battlePower :
opponent . stats . health +
opponent . stats . min +
opponent . stats . max
} )
)
ctx . respond ( {
response _type : 'ephemeral' ,
text : ` *Battle Master:* Greetings battler. Here are the avaliable *Beginner* opponents for you to battle. ` ,
blocks : [
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : ` *Battle Master:* Greetings <@ ${ ctx . body . user _id } >. Here are the avaliable *Beginner* opponents for you to battle. `
}
} ,
{
type : 'section' ,
text : {
type : 'mrkdwn' ,
text : mappedBeginner . map ( opponent => ` * ${ opponent . name } :* \n \n ${ opponent . battlePower } Battle Power ` ) . join ( '\n\n\n' )
}
}
]
} )
break ;
case "CASUAL" :
ctx . say ( "You're trying to view Casual opponents." )
break ;
default :
ctx . say ( "You either wrote nothing or just chose a rank that doesn't exist." )
}
} ) ;
; ( async ( ) => {
// Start your app
await app . start ( process . env . PORT ) ;
console . log ( '⚡️ Bolt app is running!' ) ;
} ) ( ) ;