open System.IO open System.Threading.Tasks open DSharpPlus open DSharpPlus.Entities open DSharpPlus.SlashCommands open Emzi0767.Utilities open LiteDB open LiteDB.FSharp type HackType = | Virus = 0 | Ransom = 1 | DDos = 2 | Worm = 3 | Crack = 4 | SomeOtherThing = 4 type DefenseType = | Firewall | PortScan | Encryption | Cypher | Hardening [] type Weapon = { Id : int Name : string Damage : single } type Player = { Id : int Name : string Nickname : string DiscordId : uint16 Weapons : int array } type Match = { scorePlayer1 : int round : int scorePlayer2 : int } type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule () type JoeBot() = inherit ApplicationCommandModule () [] member _.AddHackerRole (ctx : InteractionContext) = async { for role in ctx.Guild.Roles do if role.Value.Name = "Hacker" then do! ctx.Member.GrantRoleAsync(role.Value) |> Async.AwaitTask do! ctx.CreateResponseAsync("You are now an elite haxxor", true) |> Async.AwaitTask } |> Async.StartAsTask :> Task [] member _.RemoveHackerRole (ctx : InteractionContext) = async { for role in ctx.Member.Roles do if role.Name = "Hacker" then do! ctx.Member.RevokeRoleAsync(role) |> Async.AwaitTask do! ctx.CreateResponseAsync("You are now lame", true) |> Async.AwaitTask } |> Async.StartAsTask :> Task [] member _.StartMatch (ctx : InteractionContext, [] player : DiscordUser) = async { // We won't be able to find the user if they are Away or Sleeping apparently let ( result , discordMember ) = ctx.Guild.Members.TryGetValue(player.Id) if result then let yes = DiscordButtonComponent( ButtonStyle.Primary, "first_button", "I do") let no = DiscordButtonComponent( ButtonStyle.Danger, "second_button", "No thank you") let builder = DiscordMessageBuilder() let builder = builder.AddComponents(yes, no) use img = new FileStream("challenge.jpg", FileMode.Open) builder.WithFile(img) |> ignore builder.Content <- $"You have been challenged by {player.Username}, do you accept?" for channel in ctx.Guild.Channels do if channel.Value.Name = "battle-1" then do! channel.Value.SendMessageAsync builder |> Async.AwaitTask |> Async.Ignore let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- $"Sending challenge to {player.Username}" do! ctx.CreateResponseAsync (builder) |> Async.AwaitTask else let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- $"Unable to find user in this server" do! ctx.CreateResponseAsync (builder) |> Async.AwaitTask } |> Async.StartAsTask :> Task member _.Embed () = let builder = DiscordEmbedBuilder() builder.Color <- Optional(DiscordColor.Blurple) builder.Description <- "This is a test embed" let author = DiscordEmbedBuilder.EmbedAuthor() author.Name <- "Joebot Pro" author.Url <- "https://ferano.io" author.IconUrl <- "https://i.kym-cdn.com/entries/icons/original/000/028/861/cover3.jpg" builder.Author <- author let footer = DiscordEmbedBuilder.EmbedFooter() footer.Text <- "This is a footer" footer.IconUrl <- "https://dg8krxphbh767.cloudfront.net/exercises/bird-watcher.svg" builder.Footer <- footer builder.Title <- "THIS IS A TITLE" builder.ImageUrl <- "https://avatars3.githubusercontent.com/u/2642263" builder.Build() [] member this.Hack (ctx : InteractionContext, [] player : DiscordUser) = let constructButtons (weapons : HackType list) = weapons |> Seq.map (fun hack -> // TODO:L Button ID should be a GUID and we should keep an in-memory store of the buttons we're waiting for DiscordButtonComponent( ButtonStyle.Primary, $"{hack}{System.Guid.NewGuid()}", $"{hack}")) async { let builder = DiscordInteractionResponseBuilder() builder.AddEmbed (this.Embed()) |> ignore constructButtons [ HackType.Virus ; HackType.Crack ; HackType.Ransom ; HackType.Worm ; HackType.DDos ] |> Seq.cast |> builder.AddComponents |> ignore constructButtons [ HackType.Virus ; HackType.Crack ; HackType.Ransom ; HackType.Worm ; HackType.DDos ] |> Seq.cast |> builder.AddComponents |> ignore builder.AsEphemeral true |> ignore do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask } |> Async.StartAsTask :> Task [] member this.TestEmbed (ctx : InteractionContext) = async { do! ctx.CreateResponseAsync (this.Embed() , true) |> Async.AwaitTask } |> Async.StartAsTask :> Task let mapper = FSharpBsonMapper() let db = new LiteDatabase("hacker-game.db", mapper) let config = DiscordConfiguration() config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk" config.TokenType <- TokenType.Bot config.Intents <- DiscordIntents.All //config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace let client = new DiscordClient(config) client.add_ComponentInteractionCreated(AsyncEventHandler( fun client event -> async { return () } |> Async.StartAsTask :> Task)) let slash = client.UseSlashCommands() slash.RegisterCommands(922419263275425832uL); client.ConnectAsync () |> Async.AwaitTask |> Async.RunSynchronously Task.Delay(-1) |> Async.AwaitTask |> Async.RunSynchronously client.DisconnectAsync () |> Async.AwaitTask |> Async.RunSynchronously