module Degenz.Store open System.Threading.Tasks open DSharpPlus.Entities open DSharpPlus open DSharpPlus.EventArgs open DSharpPlus.SlashCommands open Degenz open Degenz.Embeds open Degenz.Shared open Newtonsoft.Json let store = try let file = System.IO.File.ReadAllText("Items.json") JsonConvert.DeserializeObject(file) |> Array.groupBy (fun (i : Item) -> i.ItemType) with _ -> [||] let viewStore (ctx : InteractionContext) = async { do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing store) |> Async.AwaitTask } |> Async.StartAsTask :> Task let getItems itemType = store |> Array.find (fun ( t , _ ) -> t = itemType) |> snd let buyHack (ctx : InteractionContext) hackId = async { let! playerResult = DbService.tryFindPlayer ctx.Member.Id let weapons = getItems ItemType.Hack let weaponResult = weapons |> Array.tryFind (fun w -> w.Name = string hackId) return! match playerResult , weaponResult with | Some player , Some item -> async { let newBalance = player.Bank - item.Cost if newBalance >= 0 then let playerHasItem = player.Weapons |> Array.exists (fun w -> item.Name = string w) if not playerHasItem then let weapon = weaponInventory |> Array.find (fun w -> item.Name = string w) let p = { player with Bank = newBalance ; Weapons = Array.append [| weapon |] player.Weapons } do! DbService.updatePlayer p do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx else do! createSimpleResponseAsync $"You already own this item!" ctx else do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx } | None , _ -> notYetAHackerMsg ctx | _ -> createSimpleResponseAsync "Something is wrong" ctx } |> Async.StartAsTask :> Task let buyShield (ctx : InteractionContext) shieldId = async { let! playerResult = DbService.tryFindPlayer ctx.Member.Id let shieldResult = getItems ItemType.Shield |> Array.tryFind (fun w -> w.Name = string shieldId) return! match playerResult , shieldResult with | Some player , Some item -> async { let newBalance = player.Bank - item.Cost if newBalance >= 0 then let playerHasItem = player.Shields |> Array.exists (fun w -> item.Name = string w) if not playerHasItem then let shield = shieldInventory |> Array.find (fun w -> item.Name = string w) let p = { player with Bank = newBalance ; Shields = Array.append [| shield |] player.Shields } do! DbService.updatePlayer p do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx else do! createSimpleResponseAsync $"You already own this item!" ctx else do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx } | None , _ -> notYetAHackerMsg ctx | _ -> createSimpleResponseAsync "Something is wrong" ctx } |> Async.StartAsTask :> Task let constructItemButtons playerInfo itemType (items : 'a array) = items |> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{itemType}-{item}", $"{item}")) let sellItem (ctx : InteractionContext) = async { let! playerResult = DbService.tryFindPlayer ctx.Member.Id match playerResult with | Some player -> let hasInventoryToSell = Array.length player.Weapons + Array.length player.Shields > 0 if hasInventoryToSell then let builder = DiscordInteractionResponseBuilder() builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore Array.chunkBySize 3 player.Weapons |> Array.iter (fun wps -> wps |> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"Hack-{w}", $"{w}")) |> Seq.cast |> builder.AddComponents |> ignore) Array.chunkBySize 3 player.Shields |> Array.iter (fun shs -> shs |> Array.map (fun s -> DiscordButtonComponent(ButtonStyle.Primary, $"Shield-{s}", $"{s}")) |> Seq.cast |> builder.AddComponents |> ignore) builder.AsEphemeral true |> ignore do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask else do! createSimpleResponseAsync "You currently have no inventory to sell" ctx | None -> do! notYetAHackerMsg ctx return () } |> Async.StartAsTask :> Task let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = async { let! playerResult = DbService.tryFindPlayer event.User.Id match playerResult with | Some player -> let split = event.Id.Split("-") let itemType = match split.[0] with "Hack" -> ItemType.Hack | _ -> ItemType.Shield let itemName = split.[1] match itemType with | ItemType.Hack -> let item = getItems ItemType.Hack |> Array.find (fun w -> w.Name = itemName) let salePrice = item.Cost / 2 let updatedWeapons = player.Weapons |> Array.filter (fun (w : Hack) -> string w <> itemName) let updatedPlayer = { player with Bank = player.Bank + salePrice ; Weapons = updatedWeapons } do! DbService.updatePlayer updatedPlayer let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- $"Sold hack {itemName} for {salePrice}! Current Balance: {updatedPlayer.Bank}" do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |> Async.AwaitTask | ItemType.Shield -> let item = getItems ItemType.Shield |> Array.find (fun s -> s.Name = itemName) let salePrice = item.Cost / 2 let updatedShields = player.Shields |> Array.filter (fun (s : Shield) -> string s <> itemName) let updatedPlayer = { player with Bank = player.Bank + salePrice ; Shields = updatedShields } do! DbService.updatePlayer updatedPlayer let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- $"Sold shield {itemName} for {salePrice}! Current Balance: {updatedPlayer.Bank}" do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |> Async.AwaitTask | None -> let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- "An error occurred and the user doesn't not exist" do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |> Async.AwaitTask } |> Async.StartAsTask :> Task type Store() = inherit ApplicationCommandModule () [] member _.ViewStore (ctx : InteractionContext) = viewStore ctx [] member _.BuyHack (ctx : InteractionContext, [] hackId : Hack) = buyHack ctx hackId [] member this.BuyShield (ctx : InteractionContext, [] shieldId : Shield) = buyShield ctx shieldId [] member this.SellItem (ctx : InteractionContext) = sellItem ctx