open System.Threading.Tasks open DSharpPlus open DSharpPlus.Entities open DSharpPlus.SlashCommands open DSharpPlus.CommandsNext open DSharpPlus.CommandsNext.Attributes open Emzi0767.Utilities type Move = | Rock | Paper | Scissor type RoundResult = | P1Win | P2Win | Draw type Player = { name : string health : string } type Turn = | WaitingForBoth | WaitingForOne of Move | WaitingForTwo of Move | BothCompleted of Move * Move type Match = { player1 : DiscordMember player2 : DiscordMember round : int scorePlayer1 : int scorePlayer2 : int turn : Turn } type JoeBot() = inherit BaseCommandModule () let mutable currentMatch : Match option = None [] [] member this.StartMatch (ctx : CommandContext, [] player1 : DiscordMember, [] player2 : DiscordMember) = async { do! ctx.TriggerTypingAsync() |> Async.AwaitTask currentMatch <- Some { player1 = player1 player2 = player2 round = 0 scorePlayer1 = 0 scorePlayer2 = 0 turn = WaitingForBoth } do! ctx.RespondAsync (sprintf "Match started between %s and %s. May the best hacker win!" player1.DisplayName player2.DisplayName) |> Async.AwaitTask |> Async.Ignore } |> Async.StartAsTask :> Task [] [] member this.SendMove (ctx : CommandContext, [] moveString : string) = async { do! ctx.TriggerTypingAsync() |> Async.AwaitTask let move = match moveString.ToLower() with | "rock" -> Some Rock | "paper" -> Some Paper | "scissor" -> Some Scissor | _ -> None match currentMatch , move with | Some mtc , Some move -> let updatedTurn = match mtc.turn with | WaitingForBoth -> match ctx.Member with | mem when mem = mtc.player1 -> WaitingForTwo move | mem when mem = mtc.player2 -> WaitingForOne move | _ -> mtc.turn | WaitingForOne p1m -> match ctx.Member with | mem when mem = mtc.player1 -> BothCompleted ( p1m , move ) | mem when mem = mtc.player2 -> mtc.turn | _ -> mtc.turn | WaitingForTwo p2m -> match ctx.Member with | mem when mem = mtc.player1 -> mtc.turn | mem when mem = mtc.player2 -> BothCompleted ( p2m , move ) | _ -> mtc.turn | _ -> mtc.turn match updatedTurn with | BothCompleted ( p1m , p2m ) -> let result = match p1m , p2m with | Rock , Paper -> P2Win | Rock , Scissor -> P1Win | Paper , Rock -> P1Win | Paper , Scissor -> P2Win | Scissor , Rock -> P2Win | Scissor , Paper -> P1Win | _ -> Draw match result with | P1Win | P2Win -> let winner = match result with P1Win -> mtc.player1 | P2Win -> mtc.player2 | Draw -> mtc.player1 let message = $"{p1m} beats {p2m}! {winner} takes the round!" do! ctx.RespondAsync message |> Async.AwaitTask |> Async.Ignore if mtc.round >= 5 then let winnerScore = match result with P1Win -> mtc.scorePlayer1 | P2Win -> mtc.scorePlayer2 | Draw -> 0 let loserScore = match result with P1Win -> mtc.scorePlayer2 | P2Win -> mtc.scorePlayer1 | Draw -> 0 currentMatch <- None do! ctx.RespondAsync $"{winner} wins the match {winnerScore} to {loserScore}! Awarding a 100 genz!" |> Async.AwaitTask |> Async.Ignore else currentMatch <- Some { mtc with round = mtc.round + 1 scorePlayer1 = mtc.scorePlayer1 + (match result with P1Win -> 1 | _ -> 0) scorePlayer2 = mtc.scorePlayer2 + (match result with P2Win -> 1 | _ -> 0) turn = updatedTurn } | Draw -> do! ctx.RespondAsync $"{mtc.player1.DisplayName} and {mtc.player2.DisplayName} both did {p1m}. Round was a draw! Go again!" |> Async.AwaitTask |> Async.Ignore | _ -> if updatedTurn <> mtc.turn then do! ctx.RespondAsync ($"Move received by {ctx.Member.DisplayName}!") |> Async.AwaitTask |> Async.Ignore else do! async{ return () } | None , _ -> do! ctx.RespondAsync ("No match has been found, please use the '/start-match' command and mention the two players") |> Async.AwaitTask |> Async.Ignore | _ , None -> do! ctx.RespondAsync $"Could not recognize move '{moveString}', please try again. Valid moves are 'rock', 'paper', or 'scissor'" |> Async.AwaitTask |> Async.Ignore } |> Async.StartAsTask :> Task [] [] member this.Status (ctx : CommandContext) = async { do! ctx.TriggerTypingAsync() |> Async.AwaitTask do! ctx.RespondAsync ("Status") |> Async.AwaitTask |> Async.Ignore } |> Async.StartAsTask :> Task [] [] member this.Challenge (ctx : CommandContext, [] user : DiscordMember) = async { do! ctx.TriggerTypingAsync() |> Async.AwaitTask do! ctx.RespondAsync (sprintf "Targeting %u" user.Id) |> Async.AwaitTask |> Async.Ignore } |> Async.StartAsTask :> Task let config = DiscordConfiguration() config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk" config.TokenType <- TokenType.Bot let commandsConfig = CommandsNextConfiguration() commandsConfig.StringPrefixes <- [ "/" ] let client = new DiscordClient(config) let slash = client.UseSlashCommands() slash.add_SlashCommandExecuted(AsyncEventHandler<_,_>( fun client e -> async { let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- "Does this need to be filled out?" return e.Context.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder) } |> Async.StartAsTask :> Task)) //let commands = client.UseCommandsNext(commandsConfig) //commands.RegisterCommands() client.ConnectAsync () |> Async.AwaitTask |> Async.RunSynchronously Task.Delay(-1) |> Async.AwaitTask |> Async.RunSynchronously