diff --git a/Program.fs b/Program.fs index 3fd1957..6aa4e25 100644 --- a/Program.fs +++ b/Program.fs @@ -2,9 +2,6 @@ open DSharpPlus open DSharpPlus.Entities open DSharpPlus.SlashCommands -open DSharpPlus.CommandsNext -open DSharpPlus.CommandsNext.Attributes -open Emzi0767.Utilities type Move = | Rock @@ -27,24 +24,21 @@ type Turn = | BothCompleted of Move * Move type Match = - { player1 : DiscordMember - player2 : DiscordMember + { player1 : DiscordUser + player2 : DiscordUser round : int scorePlayer1 : int scorePlayer2 : int turn : Turn } type JoeBot() = - inherit BaseCommandModule () + inherit ApplicationCommandModule () - let mutable currentMatch : Match option = None + static let mutable currentMatch : Match option = None - [] - [] - member this.StartMatch (ctx : CommandContext, [] player1 : DiscordMember, [] player2 : DiscordMember) = + [] + member _.StartMatch (ctx : InteractionContext, [] player1 : DiscordUser, [] player2 : DiscordUser) = async { - do! ctx.TriggerTypingAsync() |> Async.AwaitTask - currentMatch <- Some { player1 = player1 player2 = player2 @@ -54,24 +48,21 @@ type JoeBot() = turn = WaitingForBoth } - do! ctx.RespondAsync (sprintf "Match started between %s and %s. May the best hacker win!" player1.DisplayName player2.DisplayName) + do! ctx.CreateResponseAsync (sprintf "Match started between %s and %s. May the best hacker win!" player1.Username player2.Username) |> Async.AwaitTask |> Async.Ignore } |> Async.StartAsTask :> Task - [] - [] - member this.SendMove (ctx : CommandContext, [] moveString : string) = + [] + member _.SendMove (ctx : InteractionContext, [] moveString : string) = async { - do! ctx.TriggerTypingAsync() |> Async.AwaitTask - let move = match moveString.ToLower() with | "rock" -> Some Rock | "paper" -> Some Paper - | "scissor" -> Some Scissor + | "scissors" -> Some Scissor | _ -> None match currentMatch , move with @@ -79,17 +70,17 @@ type JoeBot() = let updatedTurn = match mtc.turn with | WaitingForBoth -> - match ctx.Member with + match ctx.User with | mem when mem = mtc.player1 -> WaitingForTwo move | mem when mem = mtc.player2 -> WaitingForOne move | _ -> mtc.turn | WaitingForOne p1m -> - match ctx.Member with + match ctx.User with | mem when mem = mtc.player1 -> BothCompleted ( p1m , move ) | mem when mem = mtc.player2 -> mtc.turn | _ -> mtc.turn | WaitingForTwo p2m -> - match ctx.Member with + match ctx.User with | mem when mem = mtc.player1 -> mtc.turn | mem when mem = mtc.player2 -> BothCompleted ( p2m , move ) | _ -> mtc.turn @@ -110,99 +101,71 @@ type JoeBot() = 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 winningMove = match result with P1Win -> p1m | P2Win -> p2m | Draw -> p1m + let losingMove = match result with P1Win -> p2m | P2Win -> p1m | Draw -> p1m + let message = $"{winningMove} beats {losingMove}! {winner.Username} takes the round!" + + 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 = WaitingForBoth + } + if mtc.round >= 3 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!" + do! ctx.CreateResponseAsync $"{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 - } + do! ctx.CreateResponseAsync message |> Async.AwaitTask | Draw -> - do! ctx.RespondAsync $"{mtc.player1.DisplayName} and {mtc.player2.DisplayName} both did {p1m}. Round was a draw! Go again!" + currentMatch <- Some { mtc with turn = WaitingForBoth } + do! ctx.CreateResponseAsync $"{mtc.player1.Username} and {mtc.player2.Username} 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}!") + currentMatch <- Some { mtc with turn = updatedTurn } + let builder = DiscordInteractionResponseBuilder() + do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder.WithContent(($"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") + do! ctx.CreateResponseAsync ("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'" + do! ctx.CreateResponseAsync $"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) = + + [] + member _.Status (ctx : InteractionContext) = async { - do! ctx.TriggerTypingAsync() |> Async.AwaitTask - - do! ctx.RespondAsync ("Status") + let builder = DiscordInteractionResponseBuilder() + builder.IsEphemeral <- true + do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder.WithContent(sprintf "%A" currentMatch)) |> 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() +let slash = client.UseSlashCommands(); +slash.RegisterCommands(); client.ConnectAsync () |> Async.AwaitTask @@ -211,3 +174,8 @@ client.ConnectAsync () Task.Delay(-1) |> Async.AwaitTask |> Async.RunSynchronously + +client.DisconnectAsync () +|> Async.AwaitTask +|> Async.RunSynchronously + diff --git a/discord-bot.fsproj b/discord-bot.fsproj index afdd5f3..5a24393 100644 --- a/discord-bot.fsproj +++ b/discord-bot.fsproj @@ -8,5 +8,8 @@ + + + \ No newline at end of file diff --git a/paket.dependencies b/paket.dependencies index 09d45a5..205db6f 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -3,7 +3,9 @@ source https://api.nuget.org/v3/index.json storage: none framework: net6.0, netstandard2.0, netstandard2.1 -nuget DSharpPlus >= 4.1.0 -nuget DSharpPlus.CommandsNext >= 4.1.0 -nuget DSharpPlus.SlashCommands >= 1.0.0 nuget FSharp.Core >= 6.0.0 + +source https://nuget.emzi0767.com/api/v3/index.json + +nuget DSharpPlus >= 4.2.0-nightly-01054 +nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01054 diff --git a/paket.lock b/paket.lock index 4dfe189..73f1304 100644 --- a/paket.lock +++ b/paket.lock @@ -1,8 +1,8 @@ STORAGE: NONE RESTRICTION: || (== net6.0) (== netstandard2.0) (== netstandard2.1) NUGET - remote: https://api.nuget.org/v3/index.json - DSharpPlus (4.1) + remote: https://nuget.emzi0767.com/api/v3/index.json + DSharpPlus (4.2.0-nightly-01054) Emzi0767.Common (>= 2.6.2) Microsoft.Extensions.Logging.Abstractions (>= 5.0) Newtonsoft.Json (>= 13.0.1) @@ -11,11 +11,11 @@ NUGET System.Net.WebSockets (>= 4.3) System.Net.WebSockets.Client (>= 4.3.2) System.Runtime.InteropServices.RuntimeInformation (>= 4.3) - DSharpPlus.CommandsNext (4.1) - DSharpPlus (>= 4.1) + System.Threading.Channels (>= 5.0) + DSharpPlus.SlashCommands (4.2.0-nightly-01054) + DSharpPlus (>= 4.2.0-nightly-01054) Microsoft.Extensions.DependencyInjection (>= 5.0.1) - DSharpPlus.SlashCommands (1.0) - DSharpPlus (>= 4.0.0-rc3) + remote: https://api.nuget.org/v3/index.json Emzi0767.Common (2.6.2) System.Collections.Immutable (>= 5.0) System.Memory (>= 4.5.4) @@ -436,6 +436,8 @@ NUGET System.Threading (4.3) System.Runtime (>= 4.3) System.Threading.Tasks (>= 4.3) + System.Threading.Channels (6.0) + System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net461)) System.Threading.Tasks (4.3) Microsoft.NETCore.Platforms (>= 1.1) Microsoft.NETCore.Targets (>= 1.1) diff --git a/paket.references b/paket.references index c9e50c8..a083389 100644 --- a/paket.references +++ b/paket.references @@ -1,4 +1,5 @@ FSharp.Core DSharpPlus -DSharpPlus.CommandsNext +// DSharpPlus.CommandsNext +// DSharpPlus.Interactivity DSharpPlus.SlashCommands