Redoing trainer flow and adding GuildEnvironment module

This commit is contained in:
Joseph Ferano 2022-01-21 22:46:33 +07:00
parent 5261713735
commit ff513331c6
8 changed files with 244 additions and 156 deletions

View File

@ -4,64 +4,53 @@ open System
open System.Threading.Tasks open System.Threading.Tasks
open DSharpPlus open DSharpPlus
open DSharpPlus.SlashCommands open DSharpPlus.SlashCommands
open Degenz
open Degenz.PlayerInteractions open Degenz.PlayerInteractions
open Degenz.SlotMachine //open Degenz.SlotMachine
open Degenz.Trainer
open Degenz.HackerBattle open Degenz.HackerBattle
open Degenz.Store open Degenz.Store
open Emzi0767.Utilities open Emzi0767.Utilities
open dotenv.net
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule () type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
let playerInteractionsConfig = DiscordConfiguration() let playerInteractionsConfig = DiscordConfiguration()
let trainerConfig = DiscordConfiguration()
let hackerBattleConfig = DiscordConfiguration() let hackerBattleConfig = DiscordConfiguration()
let storeConfig = DiscordConfiguration() let storeConfig = DiscordConfiguration()
//let slotMachineConfig = DiscordConfiguration() //let slotMachineConfig = DiscordConfiguration()
//config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace
//let configs = [| playerInteractionsConfig ; trainerConfig ; hackerBattleConfig ; storeConfig ; slotMachineConfig ; |] //let configs = [| playerInteractionsConfig ; hackerBattleConfig ; storeConfig ; slotMachineConfig ; |]
let configs = [| playerInteractionsConfig ; trainerConfig ; hackerBattleConfig ; storeConfig |] let configs = [| playerInteractionsConfig ; hackerBattleConfig ; storeConfig |]
for conf in configs do for conf in configs do
conf.TokenType <- TokenType.Bot conf.TokenType <- TokenType.Bot
conf.Intents <- DiscordIntents.All conf.Intents <- DiscordIntents.All
DotEnv.Load(DotEnvOptions(probeForEnv = true, probeLevelsToSearch = 5, overwriteExistingVars = false)) let guild = GuildEnvironment.guildId
let guild = Environment.GetEnvironmentVariable("DISCORD_GUILD") |> uint64 playerInteractionsConfig.Token <- GuildEnvironment.tokenPlayerInteractions
hackerBattleConfig.Token <- GuildEnvironment.tokenHackerBattle
playerInteractionsConfig.Token <- Environment.GetEnvironmentVariable("BOT_PLAYER_INTERACTIONS") storeConfig.Token <- GuildEnvironment.tokenStore
trainerConfig.Token <- Environment.GetEnvironmentVariable("BOT_TRAINER")
hackerBattleConfig.Token <- Environment.GetEnvironmentVariable("BOT_HACKER_BATTLE")
storeConfig.Token <- Environment.GetEnvironmentVariable("BOT_STORE")
//slotMachineConfig.Token <- Environment.GetEnvironmentVariable("BOT_SLOT_MACHINE") //slotMachineConfig.Token <- Environment.GetEnvironmentVariable("BOT_SLOT_MACHINE")
//config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace
let playerInteractionsBot = new DiscordClient(playerInteractionsConfig) let playerInteractionsBot = new DiscordClient(playerInteractionsConfig)
let trainerBot = new DiscordClient(trainerConfig)
let hackerBattleBot = new DiscordClient(hackerBattleConfig) let hackerBattleBot = new DiscordClient(hackerBattleConfig)
let storeBot = new DiscordClient(storeConfig) let storeBot = new DiscordClient(storeConfig)
//let slotMachineBot = new DiscordClient(slotMachineConfig) //let slotMachineBot = new DiscordClient(slotMachineConfig)
hackerBattleBot.add_ComponentInteractionCreated(AsyncEventHandler(HackerBattle.handleButtonEvent)) hackerBattleBot.add_ComponentInteractionCreated(AsyncEventHandler(HackerBattle.handleButtonEvent))
trainerBot.add_ComponentInteractionCreated(AsyncEventHandler(Trainer.handleButtonEvent))
storeBot.add_ComponentInteractionCreated(AsyncEventHandler(Store.handleSellButtonEvents)) storeBot.add_ComponentInteractionCreated(AsyncEventHandler(Store.handleSellButtonEvents))
//let clients = [| storeBot ; trainerBot ; hackerBattleBot ; playerInteractionsBot ; slotMachineBot |] //let clients = [| storeBot ; trainerBot ; hackerBattleBot ; playerInteractionsBot ; slotMachineBot |]
let clients = [| storeBot ; trainerBot ; hackerBattleBot ; playerInteractionsBot |] let clients = [| storeBot ; hackerBattleBot ; playerInteractionsBot |]
let sc1 = playerInteractionsBot.UseSlashCommands() let sc1 = playerInteractionsBot.UseSlashCommands()
let sc2 = trainerBot.UseSlashCommands()
let sc3 = hackerBattleBot.UseSlashCommands() let sc3 = hackerBattleBot.UseSlashCommands()
let sc4 = storeBot.UseSlashCommands() let sc4 = storeBot.UseSlashCommands()
//let sc5 = slotMachineBot.UseSlashCommands() //let sc5 = slotMachineBot.UseSlashCommands()
sc1.RegisterCommands<PlayerInteractions>(guild); sc1.RegisterCommands<PlayerInteractions>(guild);
sc2.RegisterCommands<Trainer>(guild);
sc3.RegisterCommands<HackerGame>(guild); sc3.RegisterCommands<HackerGame>(guild);
sc4.RegisterCommands<Store>(guild); sc4.RegisterCommands<Store>(guild);
//sc5.RegisterCommands<SlotMachine>(guild); //sc5.RegisterCommands<SlotMachine>(guild);

View File

@ -0,0 +1,19 @@
[<Microsoft.FSharp.Core.RequireQualifiedAccess>]
module Degenz.GuildEnvironment
open System
open dotenv.net
DotEnv.Load(DotEnvOptions(probeForEnv = true, probeLevelsToSearch = 5, overwriteExistingVars = false))
let getVar str = Environment.GetEnvironmentVariable(str)
let getId str = getVar str |> uint64
let guildId = getId "DISCORD_GUILD"
let tokenPlayerInteractions = getVar "TOKEN_PLAYER_INTERACTIONS"
let tokenHackerBattle = getVar "TOKEN_HACKER_BATTLE"
let tokenStore = getVar "TOKEN_STORE"
let eventsChannelHackerBattle = getId "EVENTS_CHANNEL_HACKER_BATTLE"
let channelTraining = getId "CHANNEL_TRAINING"
let botHackerBattle = getId "BOT_HACKER_BATTLE"
let roleTrainee = getId "ROLE_TRAINEE"

View File

@ -9,12 +9,6 @@ open DSharpPlus.SlashCommands
open Degenz open Degenz
open Degenz.Shared open Degenz.Shared
[<Literal>]
// Degenz Server
//let battleChannel = 930363007781978142uL
// My server
let battleChannel = 927449884204867664uL
let attack (ctx : InteractionContext) (target : DiscordUser) = let attack (ctx : InteractionContext) (target : DiscordUser) =
async { async {
// TODO: We need to check if the player has any active embed hacks going, if not they can cheat // TODO: We need to check if the player has any active embed hacks going, if not they can cheat
@ -133,7 +127,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
let builder = DiscordMessageBuilder() let builder = DiscordMessageBuilder()
builder.WithContent($"{event.User.Username} successfully hacked <@{targetId}> for a total of {prize} GoodBoyTokenz") |> ignore builder.WithContent($"{event.User.Username} successfully hacked <@{targetId}> for a total of {prize} GoodBoyTokenz") |> ignore
let channel = (event.Guild.GetChannel(battleChannel)) let channel = (event.Guild.GetChannel(GuildEnvironment.eventsChannelHackerBattle))
do! channel.SendMessageAsync(builder) do! channel.SendMessageAsync(builder)
|> Async.AwaitTask |> Async.AwaitTask
|> Async.Ignore |> Async.Ignore
@ -151,7 +145,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
let builder = DiscordMessageBuilder() let builder = DiscordMessageBuilder()
builder.WithContent($"Hacking attempt failed! <@{targetId}> defended hack from {event.User.Username} and took {prize} from them! ") |> ignore builder.WithContent($"Hacking attempt failed! <@{targetId}> defended hack from {event.User.Username} and took {prize} from them! ") |> ignore
let channel = (event.Guild.GetChannel(battleChannel)) let channel = (event.Guild.GetChannel(GuildEnvironment.eventsChannelHackerBattle))
do! channel.SendMessageAsync(builder) do! channel.SendMessageAsync(builder)
|> Async.AwaitTask |> Async.AwaitTask
|> Async.Ignore |> Async.Ignore
@ -194,18 +188,21 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) =
} }
let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
let task =
match event.Id with
| id when id.StartsWith("Attack") -> handleAttack event
| id when id.StartsWith("Defend") -> handleDefense event
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent event
| _ ->
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Incorrect Action identifier {event.Id}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
async { async {
return! match event.Id with return! task
| id when id.StartsWith("Attack") -> handleAttack event
| id when id.StartsWith("Defend") -> handleDefense event
| _ ->
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Incorrect Action identifier {event.Id}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
@ -214,9 +211,18 @@ type HackerGame() =
[<SlashCommand("hack", "Send a hack attack to another player")>] [<SlashCommand("hack", "Send a hack attack to another player")>]
member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) = member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) =
attack ctx target let hasTraineeRole = Seq.exists (fun (r : DiscordRole) -> r.Name = "trainee") ctx.Member.Roles
if ctx.Channel.Name = "training-dojo" && hasTraineeRole then
Trainer.attack ctx target
else
attack ctx target
[<SlashCommand("defend", "Create a passive defense that will last 24 hours")>] [<SlashCommand("defend", "Create a passive defense that will last 24 hours")>]
member this.DefendCommand (ctx : InteractionContext) = defend ctx member this.DefendCommand (ctx : InteractionContext) =
let hasTraineeRole = Seq.exists (fun (r : DiscordRole) -> r.Name = "Trainee") ctx.Member.Roles
if ctx.Channel.Name = "training-dojo" && hasTraineeRole then
Trainer.defend ctx
else
defend ctx

View File

@ -7,16 +7,17 @@
<RootNamespace>PlayerRegistration</RootNamespace> <RootNamespace>PlayerRegistration</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="paket.references" />
<Compile Include="Store.fs" />
<Compile Include="HackerBattle.fs" />
<Compile Include="SlotMachine.fs" />
<Compile Include="Trainer.fs" />
<Compile Include="PlayerInteractions.fs" />
<Compile Include="Bot.fs" />
<Content Include="Items.json"> <Content Include="Items.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="paket.references" />
<Compile Include="GuildEnvironment.fs" />
<Compile Include="Store.fs" />
<Compile Include="Trainer.fs" />
<Compile Include="HackerBattle.fs" />
<Compile Include="SlotMachine.fs" />
<Compile Include="PlayerInteractions.fs" />
<Compile Include="Bot.fs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DbService\DbService.fsproj" /> <ProjectReference Include="..\DbService\DbService.fsproj" />

View File

@ -7,37 +7,114 @@ open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands open DSharpPlus.SlashCommands
open Degenz.Shared open Degenz.Shared
let sendMessage (event : ComponentInteractionCreateEventArgs) msg = module Message =
let sendFollowUpMessage (event : ComponentInteractionCreateEventArgs) msg =
async {
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
builder.Content <- msg
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
}
let sendFollowUpMessageWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg =
async {
let builder = DiscordFollowupMessageBuilder()
let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent
builder.AddComponents [| button |] |> ignore
builder.IsEphemeral <- true
builder.Content <- msg
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
}
let sendInteractionEvent (event : ComponentInteractionCreateEventArgs) msg =
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- msg
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
}
let sendInteractionEventWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg =
async {
let builder = DiscordInteractionResponseBuilder()
let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent
builder.AddComponents [| button |] |> ignore
builder.IsEphemeral <- true
builder.Content <- msg
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
}
let sendInitialEmbed (client : DiscordClient) =
async { async {
let builder = DiscordFollowupMessageBuilder() let! channel = client.GetChannelAsync(GuildEnvironment.channelTraining) |> Async.AwaitTask
builder.IsEphemeral <- true let builder = DiscordMessageBuilder()
builder.Content <- msg builder.Content <- "Welcome to the hacker dojo you degenerate, are you ready to get started?"
do! event.Interaction.CreateFollowupMessageAsync(builder) let button = DiscordButtonComponent(ButtonStyle.Success, $"Trainer-1", $"Get started") :> DiscordComponent
builder.AddComponents [| button |] |> ignore
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask |> Async.AwaitTask
|> Async.Ignore |> Async.Ignore
do! Async.Sleep 4000 } |> Async.RunSynchronously
let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) =
async {
let msg = "First time, eh? Beautopia is a dangerous place. I'm going to teach you how to protect yourself from other degenerates. "
+ "And in the process, I'll also show you how to hack some sheeple, so you can earn some cash."
do! Message.sendInteractionEventWithButton event "Trainer-2" msg
let! membr = event.Guild.GetMemberAsync(event.User.Id) |> Async.AwaitTask
let role = event.Guild.GetRole(GuildEnvironment.roleTrainee)
do! membr.GrantRoleAsync(role) |> Async.AwaitTask
} }
let handleInitialDialog (event : ComponentInteractionCreateEventArgs) = let handleTrainerStep2 (event : ComponentInteractionCreateEventArgs) =
let sendMessage' = sendMessage event
async { async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask
let! result = DbService.tryFindPlayer event.User.Id let! result = DbService.tryFindPlayer event.User.Id
match result with match result with
| Some player -> | Some player ->
do! sendMessage' "The Degenz world is a dangerous place. I'm going to teach you how to protect yourself from other degenerates."
do! sendMessage' "And in the process, I'll also show you how to hack these sheeple, so you can earn some cash."
do! sendMessage' "First thing is first, let's get your system protected. Let's put up a shield."
let weaponName = player.Shields |> Array.tryHead |> Option.defaultValue Shield.Firewall let weaponName = player.Shields |> Array.tryHead |> Option.defaultValue Shield.Firewall
do! sendMessage' $"You currently have {weaponName} in your arsenal. To enable it and protect your system, run the `/defend` command and select '{weaponName}'" do! Message.sendFollowUpMessage event
($"First things first, let's get your system protected. Let's enable a shield to protect you from potential hackers. "
+ $"You currently have {weaponName} in your arsenal. To enable it and protect your system, you can use the `/defend` slash command to choose a shield."
+ $"\n\nRun the `/defend` command now and then select '{weaponName}'.")
| None -> | None ->
do! sendMessage' $"Something went wrong, please contact a moderator" do! Message.sendFollowUpMessage event $"Something went wrong, please contact a moderator"
} }
let defend (ctx : InteractionContext) =
async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with
| Some player ->
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick a defense to mount for 8 hours") |> ignore
constructButtons "Defend" (string player.DiscordId) player.Shields
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| None ->
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "Error, please contact a moderator"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
let handleDefense (event : ComponentInteractionCreateEventArgs) = let handleDefense (event : ComponentInteractionCreateEventArgs) =
let sendMessage' = sendMessage event let sendMessage' = Message.sendFollowUpMessage event
async { async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate) do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask |> Async.AwaitTask
@ -48,112 +125,102 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) =
do! sendMessage' $"{event.User.Username} has protected their system!" do! sendMessage' $"{event.User.Username} has protected their system!"
do! sendMessage' "Ok, good, let me make sure that worked. I'll try to hack you now" do! sendMessage' "Ok, good, let me make sure that worked. I'll try to hack you now"
do! sendMessage' $"Hacking attempt failed! {player.Name} defended hack from Degenz-Trainer and took {prize} from them! " do! sendMessage' $"Hacking attempt failed! {player.Name} defended hack from Degenz-Trainer and took {prize} from them! "
do! sendMessage' "Great, I wasn't able to hack you. Great job! Because you had your system protected, when I tried to hack you, I lost some money and had to give it to you" let msg = ("I wasn't able to hack you. Great job! Because you had your system protected when I tried to hack you, you took some money from me. "
do! sendMessage' "But you can make even more by successfully hacking your target. Why don't you try hacking me?" + "Shields only protect you for a certain amount of time, so remember to keep your system protected at all times.")
let weaponName = player.Weapons |> Array.tryHead |> Option.defaultValue Hack.Virus do! Message.sendFollowUpMessageWithButton event "Trainer-3" msg
do! sendMessage' $"You currently have {weaponName} equipped. To attempt a hack, type the '/hack' command and select {weaponName}."
| None -> | None ->
do! sendMessage' $"Something went wrong, please contact a moderator" do! sendMessage' $"Something went wrong, please contact a moderator"
} }
let handleTrainerStep3 (event : ComponentInteractionCreateEventArgs) =
async {
let! result = DbService.tryFindPlayer event.User.Id
match result with
| Some player ->
// TODO: There's a potential bug here where if the player sold their weapons, they'll get stuck
let weaponName = player.Weapons |> Array.tryHead |> Option.defaultValue Hack.Virus
do! Message.sendFollowUpMessage event
($"Next why don't you try hacking me. You currently have {weaponName} equipped. To hack me and get some money, "
+ $" you can use the '/hack' slash command and select a user to hack, then choose the hack attack you wish to use."
+ $"\n\nRun the `/hack` command now and pick me as your target, then click on the '{weaponName}' button.")
| None ->
do! Message.sendFollowUpMessage event $"Something went wrong, please contact a moderator"
}
let attack (ctx : InteractionContext) (target : DiscordUser) =
async {
let isRightTarget = target.Id = GuildEnvironment.botHackerBattle
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match isRightTarget , playerResult with
| true , Some player ->
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick an attack to use on your target") |> ignore
constructButtons "Attack" (string player.DiscordId) player.Weapons
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| false , _ ->
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "You picked the wrong target, you dufus. Try again, this time pick me!"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| _ ->
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "Error, please contact a moderator"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
let handleAttack (event : ComponentInteractionCreateEventArgs) = let handleAttack (event : ComponentInteractionCreateEventArgs) =
let sendMessage' = sendMessage event let sendMessage' = Message.sendFollowUpMessage event
async { async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate) do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask |> Async.AwaitTask
let! result = DbService.tryFindPlayer event.User.Id let! result = DbService.tryFindPlayer event.User.Id
match result with match result with
| Some player -> | Some player ->
let prize = 1.337f // LEET let prize = 2
do! sendMessage' $"{player.Name} successfully hacked Degenz-Trainer for a total of {prize} GoodBoyTokenz" do! sendMessage' $"{player.Name} successfully hacked Degenz-Trainer for a total of {prize} GoodBoyTokenz"
do! sendMessage' "Looks like you got the hang of it. By successfully hacking other people you can earn some GoodBoyTokenz" do! sendMessage' ("Look at that, you are now officially an elite haxor! By successfully hacking other people you can earn GoodBoyTokenz. "
do! sendMessage' "I think we're done for now. If you wish to purchase more hacks or shields, you go to the store to purchase them." + "Hacks take time to recover so check back in later once you've used all your hacks.")
do! sendMessage' "Alright you degenerate, off you go!" let msg = ("I think we're done. You are going to need more hacks and shields if you want to survive in this crazy world. "
+ "Remember to go check out the store and purchase whatever you need to add to your arsenal."
+ "\n\nAlright you degenerate, off you go!")
do! Message.sendFollowUpMessageWithButton event "Trainer-4" msg
| None -> | None ->
do! sendMessage' $"Something went wrong, please contact a moderator" do! sendMessage' $"Something went wrong, please contact a moderator"
} }
let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = let handleTrainerStep4 (event : ComponentInteractionCreateEventArgs) =
async {
let! membr = event.Guild.GetMemberAsync(event.User.Id) |> Async.AwaitTask
let role = event.Guild.GetRole(GuildEnvironment.roleTrainee)
do! membr.RevokeRoleAsync(role) |> Async.AwaitTask
}
let handleButtonEvent (event : ComponentInteractionCreateEventArgs) =
async { async {
match event.Id with match event.Id with
| id when id.StartsWith("Trainer") -> do! handleInitialDialog event | id when id.StartsWith("Trainer") ->
| id when id.StartsWith("Defend") -> do! handleDefense event let split = id.Split("-")
| id when id.StartsWith("Attack") -> do! handleAttack event match int split.[1] with
| _ -> do! sendMessage event "No action found" | 1 -> do! handleTrainerStep1 event
| 2 -> do! handleTrainerStep2 event
| 3 -> do! handleTrainerStep3 event
| _ -> do! Message.sendFollowUpMessage event "No action found"
| _ -> do! Message.sendFollowUpMessage event "No action found"
} }
|> Async.StartAsTask
:> Task
let sendInitialEmbed (client : DiscordClient) =
async {
let! channel = client.GetChannelAsync(933298431521333258uL) |> Async.AwaitTask
let builder = DiscordMessageBuilder()
builder.Content <- "Welcome to the trainer bot, are you ready to get started?"
let button = DiscordButtonComponent(ButtonStyle.Success, $"Trainer-trainer-1", $"Get started") :> DiscordComponent
builder.AddComponents [| button |] |> ignore
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
} |> Async.RunSynchronously
type Trainer() =
inherit ApplicationCommandModule ()
[<SlashCommand("defend", "Create a passive defense that will last 24 hours")>]
member this.DefendCommand (ctx : InteractionContext) =
async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with
| Some player ->
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick a defense to mount for 24 hours") |> ignore
constructButtons "Defend" (string player.DiscordId) player.Shields
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| None ->
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "Error, please contact a moderator"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
[<SlashCommand("hack", "Send a hack attack to another player")>]
member this.Attack (ctx : InteractionContext) =
async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with
| Some player ->
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick an attack to use on your target") |> ignore
constructButtons "Attack" (string player.DiscordId) player.Weapons
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| None ->
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "Error, please contact a moderator"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task

View File

@ -1,5 +1,6 @@
FSharp.Core FSharp.Core
DSharpPlus DSharpPlus
DSharpPlus.Interactivity
DSharpPlus.SlashCommands DSharpPlus.SlashCommands
dotenv.net dotenv.net
DanielStout.AsciiTableFormatter DanielStout.AsciiTableFormatter

View File

@ -7,7 +7,8 @@ nuget FSharp.Core >= 6.0.0
source https://nuget.emzi0767.com/api/v3/index.json source https://nuget.emzi0767.com/api/v3/index.json
nuget DSharpPlus >= 4.2.0-nightly-01054 nuget DSharpPlus >= 4.2.0-nightly-01061
nuget DSharpPlus.Interactivity >= 4.2.0-nightly-01061
nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01061 nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01061
nuget MongoDB.Driver nuget MongoDB.Driver

View File

@ -2,6 +2,7 @@ STORAGE: NONE
RESTRICTION: || (== net6.0) (== netstandard2.0) (== netstandard2.1) RESTRICTION: || (== net6.0) (== netstandard2.0) (== netstandard2.1)
NUGET NUGET
remote: https://api.nuget.org/v3/index.json remote: https://api.nuget.org/v3/index.json
ConcurrentHashSet (1.3)
DanielStout.AsciiTableFormatter (1.1) DanielStout.AsciiTableFormatter (1.1)
DnsClient (1.5) DnsClient (1.5)
Microsoft.Win32.Registry (>= 5.0) Microsoft.Win32.Registry (>= 5.0)
@ -481,6 +482,9 @@ NUGET
System.Net.WebSockets.Client (>= 4.3.2) System.Net.WebSockets.Client (>= 4.3.2)
System.Runtime.InteropServices.RuntimeInformation (>= 4.3) System.Runtime.InteropServices.RuntimeInformation (>= 4.3)
System.Threading.Channels (>= 5.0) System.Threading.Channels (>= 5.0)
DSharpPlus.Interactivity (4.2.0-nightly-01061)
ConcurrentHashSet (>= 1.1)
DSharpPlus (>= 4.2.0-nightly-01061)
DSharpPlus.SlashCommands (4.2.0-nightly-01061) DSharpPlus.SlashCommands (4.2.0-nightly-01061)
DSharpPlus (>= 4.2.0-nightly-01061) DSharpPlus (>= 4.2.0-nightly-01061)
Microsoft.Extensions.DependencyInjection (>= 5.0.1) Microsoft.Extensions.DependencyInjection (>= 5.0.1)