module Degenz.PlayerInteractions open System open System.Threading.Tasks open AsciiTableFormatter open DSharpPlus.Entities open DSharpPlus open DSharpPlus.SlashCommands open Degenz open Degenz.Shared module Commands = let newPlayer nickname (membr : uint64) = // let h1 = [| Weapon.Virus ; Weapon.Ransom |] // let h2 = [| Weapon.DDos ; Weapon.Worm |] // let h3 = [| Weapon.Crack ; Weapon.Injection |] // let d1 = [| Shield.Firewall ; Shield.PortScan |] // let d2 = [| Shield.Encryption ; Shield.Cypher |] // let d3 = [| Shield.Hardening ; Shield.Sanitation |] let rand = System.Random(System.Guid.NewGuid().GetHashCode()) let getRandom (actions : 'a array) = actions.[rand.Next(0, Math.Max(0, actions.Length - 1))] let weapons = [| getRandom weaponInventory |] let shields = [| getRandom shieldInventory |] { DiscordId = membr Name = nickname Weapons = weapons Shields = shields Attacks = [||] Defenses = [||] Bank = 15 } let addHackerRole (ctx : InteractionContext) = async { let! player = DbService.tryFindPlayer ctx.Member.Id let! newPlayer = match player with | Some _ -> async.Return false | None -> async { do! newPlayer ctx.Member.Username ctx.Member.Id |> DbService.insertNewPlayer for role in ctx.Guild.Roles do if role.Value.Name = "Hacker" then do! ctx.Member.GrantRoleAsync(role.Value) |> Async.AwaitTask return true } if newPlayer then // TODO: Add a better registration message that shows which weapon and how much currency they start with do! ctx.CreateResponseAsync("You are now an elite haxxor", true) |> Async.AwaitTask else do! ctx.CreateResponseAsync("Already registered as an elite haxxor", true) |> Async.AwaitTask } |> Async.StartAsTask :> Task let removeHackerRole (ctx : InteractionContext) = async { for role in ctx.Member.Roles do if role.Name = "Hacker" then do! ctx.Member.RevokeRoleAsync(role) |> Async.AwaitTask do! DbService.removePlayer ctx.Member.Id do! ctx.CreateResponseAsync("You are now lame", true) |> Async.AwaitTask } |> Async.StartAsTask :> Task [] type LeaderboardEntry = { Position : string Amount : string Name : string } let leaderboard (ctx : InteractionContext) = async { let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true let! leaders = DbService.getTopPlayers 10 let content = leaders |> Seq.toArray |> Array.sortByDescending (fun p -> p.Bank) |> Array.mapi (fun i p -> { Position = string (i + 1) ; Amount = string p.Bank ; Name = p.Name }) |> Formatter.Format builder.Content <- if not <| String.IsNullOrEmpty content then $"```{content}```" else "There are no active hackers" do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask } |> Async.StartAsTask :> Task let status (ctx : InteractionContext) = async { let! player = DbService.tryFindPlayer ctx.Member.Id match player with | Some p -> let updatedAttacks = p.Attacks |> removeExpiredActions (TimeSpan.FromHours(24)) (fun (atk : Attack) -> atk.Timestamp) let updatedDefenses = p.Defenses |> removeExpiredActions (TimeSpan.FromHours(6)) (fun (p : Defense) -> p.Timestamp) let updatedPlayer = { p with Attacks = updatedAttacks ; Defenses = updatedDefenses } do! DbService.updatePlayer updatedPlayer let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- statusFormat updatedPlayer do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask | None -> do! notYetAHackerMsg ctx } |> Async.StartAsTask :> Task type PlayerInteractions() = inherit ApplicationCommandModule () [] member _.AddHackerRole (ctx : InteractionContext) = Commands.addHackerRole ctx [] member _.RemoveHackerRole (ctx : InteractionContext) = Commands.removeHackerRole ctx [] member this.Status (ctx : InteractionContext) = Commands.status ctx [] member this.Leaderboard (ctx : InteractionContext) = Commands.leaderboard ctx