2022-02-27 15:12:30 +07:00

122 lines
5.2 KiB
Forth

module Degenz.Store
open System.Threading.Tasks
open DSharpPlus.Entities
open DSharpPlus
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz
open Degenz.Messaging
open Degenz.PlayerInteractions
let checkHasSufficientFunds (item : Item) player =
if player.Bank - item.Price >= 0<GBT>
then Ok player
else Error $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
let checkAlreadyOwnsItem (item : Item) player =
if player.Inventory |> List.exists (fun w -> item.Id = w.Id)
then Error $"You already own {item.Name}!"
else Ok player
let checkSoldItemAlready item player =
if player.Inventory |> List.exists (fun i -> item.Id = i.Id)
then Ok player
else Error $"{item.Name} not found in your inventory! Looks like you sold it already."
let checkHasItemsInArsenal itemType items player =
if List.isEmpty items |> not
then Ok player
else Error $"You currently have no {itemType} in your arsenal to sell!"
let buy getItems (ctx : IDiscordContext) =
executePlayerAction ctx (fun player -> async {
let itemStore = Embeds.getBuyItemsEmbed (getItems player.Inventory) (getItems Armory.battleItems)
do! ctx.FollowUp itemStore |> Async.AwaitTask
})
let sell itemType getItems (ctx : IDiscordContext) =
executePlayerAction ctx (fun player -> async {
let items = getItems player
match checkHasItemsInArsenal itemType items player with
| Ok _ -> let itemStore = Embeds.getSellEmbed items
do! ctx.FollowUp(itemStore) |> Async.AwaitTask
| Error e -> do! sendFollowUpMessage ctx e
})
// TODO: When you buy a shield, prompt the user to activate it
let handleBuyItem (ctx : IDiscordContext) itemId =
executePlayerAction ctx (fun player -> async {
let item = Armory.getItem itemId
do! player
|> checkHasSufficientFunds item
>>= checkAlreadyOwnsItem item
|> handleResultWithResponse ctx (fun player -> async {
let newBalance = player.Bank - item.Price
let p = { player with Bank = newBalance ; Inventory = item::player.Inventory }
do! DbService.updatePlayer GuildEnvironment.pgDb p |> Async.Ignore
do! sendFollowUpMessage ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining"
})
})
let handleSell (ctx : IDiscordContext) itemId =
executePlayerAction ctx (fun player -> async {
let item = Armory.getItem itemId
do!
player
|> checkSoldItemAlready item
|> handleResultWithResponse ctx (fun player -> async {
let updatedPlayer = {
player with
Bank = player.Bank + item.Price
Inventory = player.Inventory |> List.filter (fun i -> i.Id <> itemId)
}
do!
[ DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer |> Async.Ignore
DbService.removeShieldEvent GuildEnvironment.pgDb updatedPlayer.DiscordId itemId |> Async.Ignore
sendFollowUpMessage ctx $"Sold {item.Type} {item.Name} for {item.Price}! Current Balance: {updatedPlayer.Bank}" ]
|> Async.Parallel
|> Async.Ignore
})
})
let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
let ctx = DiscordEventContext event :> IDiscordContext
let id = ctx.GetInteractionId()
let itemId = int <| id.Split("-").[1]
match id with
| id when id.StartsWith("Buy") -> handleBuyItem ctx itemId
| id when id.StartsWith("Sell") -> handleSell ctx itemId
| _ ->
task {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Incorrect Action identifier {id}"
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
}
type Store() =
inherit ApplicationCommandModule ()
let enforceChannel (ctx : IDiscordContext) (storeFn : IDiscordContext -> Task) =
match ctx.GetChannel().Id with
| id when id = GuildEnvironment.channelArmory -> storeFn ctx
| _ ->
task {
let msg = $"You must go to <#{GuildEnvironment.channelArmory}> channel to buy or sell weapons"
do! Messaging.sendSimpleResponse ctx msg
}
[<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>]
member _.BuyHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Armory.getHackItems)
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Armory.getShieldItems)
[<SlashCommand("sell-hack", "Sell a hack for GoodBoyTokenz")>]
member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" Player.getHackItems)
[<SlashCommand("sell-shield", "Sell a shield for GoodBoyTokenz")>]
member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" Player.getShieldItems)