discord-bot-game/Bot/PlayerInteractions.fs

138 lines
5.3 KiB
Forth

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
[<CLIMutable>]
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 ->
// TODO: Is this working?
let updatedAttacks = p.Attacks |> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
let updatedDefenses = p.Defenses |> removeExpiredActions (TimeSpan.FromHours(24)) (fun (p : Defense) -> p.Timestamp)
do! DbService.updatePlayer <| { p with Attacks = updatedAttacks ; Defenses = updatedDefenses }
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- statusFormat p
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| None -> do! notYetAHackerMsg ctx
} |> Async.StartAsTask
:> Task
type PlayerInteractions() =
inherit ApplicationCommandModule ()
[<SlashCommand("redpill", "Take the redpill and become a hacker")>]
member _.AddHackerRole (ctx : InteractionContext) = Commands.addHackerRole ctx
[<SlashCommand("bluepill", "Take the bluepill and become lame")>]
member _.RemoveHackerRole (ctx : InteractionContext) = Commands.removeHackerRole ctx
[<SlashCommand("status", "Get your current status like bank account, and active hacks and defenses")>]
member this.Status (ctx : InteractionContext) = Commands.status ctx
[<SlashCommand("leaderboard", "View the current list of players ranked by highest earnings")>]
member this.Leaderboard (ctx : InteractionContext) = Commands.leaderboard ctx