547 lines
25 KiB
Forth
547 lines
25 KiB
Forth
module Degenz.Store
|
||
|
||
open System
|
||
open System.Threading.Tasks
|
||
open DSharpPlus.Entities
|
||
open DSharpPlus
|
||
open DSharpPlus.EventArgs
|
||
open DSharpPlus.SlashCommands
|
||
open Degenz
|
||
open Degenz.Messaging
|
||
open Degenz.PlayerInteractions
|
||
open FsToolkit.ErrorHandling
|
||
|
||
let holderRoles = [ GuildEnvironment.roleHolder1 ; GuildEnvironment.roleHolder5 ; GuildEnvironment.roleHolder10 ; GuildEnvironment.roleHolder50 ]
|
||
|
||
let getRankEmbedColor = function
|
||
| 3 -> DiscordColor.Red
|
||
| 2 -> DiscordColor.Green
|
||
| _ -> DiscordColor.Blurple
|
||
|
||
let getRankButtonColor = function
|
||
| 3 -> ButtonStyle.Danger
|
||
| 2 -> ButtonStyle.Success
|
||
| _ -> ButtonStyle.Primary
|
||
|
||
let embedWithError error =
|
||
DiscordFollowupMessageBuilder()
|
||
.AsEphemeral()
|
||
.WithContent(error)
|
||
|> Error
|
||
|
||
let checkHasStock (item : StoreItem) =
|
||
if item.Stock > 0 || item.LimitStock = false
|
||
then Ok ()
|
||
else $"{item.Item.Name} is out of stock! Check back later to purchase"
|
||
|> embedWithError
|
||
|
||
let checkHasSufficientFunds (item : Item) player =
|
||
match item.Attributes with
|
||
| CanBuy price ->
|
||
if player.Bank - price >= 0<GBT>
|
||
then Ok ()
|
||
else $"""
|
||
**__Current Balance:__** {player.Bank} 💰 $GBT
|
||
Hold up Degen! You don't have enough $GBT!
|
||
Go to <#{GuildEnvironment.channelQuests}> to start earning some now..."""
|
||
|> embedWithError
|
||
| _ -> $"{item.Name} item cannot be bought"
|
||
|> embedWithError
|
||
|
||
let getTotalOwnedOfItem (item : Item) (inventory : Item list) =
|
||
inventory
|
||
|> List.countBy (fun i -> i.Id)
|
||
|> List.tryFind (fst >> ((=) item.Id))
|
||
|> Option.map snd
|
||
|
||
let checkDoesntExceedStackCap (item : Item) player =
|
||
let itemCount = getTotalOwnedOfItem item player.Inventory
|
||
match item.Attributes , itemCount with
|
||
| CanStack max , Some count ->
|
||
if count >= max
|
||
then $"You own the maximum allowed amount {item.Name}!"
|
||
|> embedWithError
|
||
else Ok ()
|
||
| _ , Some _ -> "You already own this item" |> embedWithError
|
||
| _ -> Ok ()
|
||
|
||
let checkItemSaleStillActive (item : StoreItem) =
|
||
match item.SaleEnd with
|
||
| Some time ->
|
||
let date = DateTimeOffset.FromUnixTimeSeconds(time).DateTime.ToUniversalTime()
|
||
if DateTime.UtcNow < date then Ok () else $"Sale for {item.Item.Name} has already ended!" |> embedWithError
|
||
| None -> Ok ()
|
||
|
||
let checkSoldItemAlready (item : Item) player =
|
||
if player.Inventory |> List.exists (fun i -> item.Id = i.Id)
|
||
then Ok ()
|
||
else $"{item.Name} not found in your inventory! Looks like you sold it already."
|
||
|> embedWithError
|
||
|
||
let checkHasItemsInArsenal itemType items =
|
||
if List.isEmpty items |> not
|
||
then Ok ()
|
||
else $"You currently have no {itemType} in your arsenal to sell!"
|
||
|> embedWithError
|
||
|
||
let getItemEmbeds owned (items : StoreItem list) =
|
||
items
|
||
|> List.countBy (fun item -> item.Item.Id)
|
||
|> List.map (fun (id,count) -> items |> List.find (fun i -> i.Item.Id = id) , count )
|
||
|> List.map (fun (item,count) ->
|
||
let mutable titleText = item.Item.Name
|
||
let embed = DiscordEmbedBuilder()
|
||
if not owned && item.LimitStock then
|
||
embed.AddField("Stock", $"{item.Stock}", true) |> ignore
|
||
item.Item.Attributes
|
||
|> List.iter (function
|
||
| Buyable price ->
|
||
if not owned then
|
||
embed.AddField("Price", (if price = 0<GBT> then "Free" else $"{price} 💰 $GBT"), true) |> ignore
|
||
| Attackable power ->
|
||
let title = match item.Item.Type with ItemType.Hack -> "Reward" | _ -> "Power"
|
||
embed.AddField($"{title}", string power, true) |> ignore
|
||
| Classable className ->
|
||
let title =
|
||
match item.Item.Type with
|
||
| ItemType.Hack -> "Weak Against" | ItemType.Shield -> "Defeats"
|
||
| _ -> ""
|
||
let goodAgainst =
|
||
match item.Item.Type with
|
||
| ItemType.Hack -> WeaponClass.getGoodAgainst className |> fst |> string
|
||
| ItemType.Shield -> WeaponClass.getGoodAgainst className |> snd |> string
|
||
| _ -> ""
|
||
let weaponName = Arsenal.weapons |> List.find (fun w -> w.Id = goodAgainst) |> fun i -> i.Name
|
||
embed.AddField(title, weaponName, true) |> ignore
|
||
| RateLimitable time ->
|
||
let title =
|
||
match item.Item.Type with
|
||
| ItemType.Hack -> "Cooldown" | ItemType.Shield -> "Active For"
|
||
| _ -> ""
|
||
let ts = TimeSpan.FromMinutes(int time)
|
||
let timeStr = if ts.Hours = 0 then $"{ts.Minutes} mins" else $"{ts.Hours} hours"
|
||
embed.AddField(title, timeStr, true) |> ignore
|
||
| Stackable max ->
|
||
if owned
|
||
then embed.AddField($"Owned", $"{count}", true) |> ignore
|
||
elif max < 1000 then embed.AddField($"Max Allowed", string max, true) |> ignore
|
||
else ()
|
||
// let totalOwned = getTotalOwnedOfItem item.Item (items |> List.map (fun i -> i.Item)) |> Option.defaultValue 1
|
||
// titleText <- $"{totalOwned}x " + titleText
|
||
| Modifiable effects ->
|
||
let fx =
|
||
effects
|
||
|> List.map (fun f ->
|
||
match f.Effect with
|
||
| Min i -> $"{f.TargetStat} Min + {i}"
|
||
| Max i -> $"{f.TargetStat} Max + {i}"
|
||
| Add i ->
|
||
let str = if i > 0 then "Boost" else "Penalty"
|
||
$"{f.TargetStat} {str} + {i}"
|
||
| RateMultiplier i -> $"{f.TargetStat} Multiplier - i")
|
||
|> String.concat "\n"
|
||
embed.AddField($"Effect - Amount", $"{fx}", true) |> ignore
|
||
| _ -> ())
|
||
// if item.Item.Type = ItemType.Whitelist then
|
||
// embed.AddField("Mint Allowance", (if item.Item.Id = "WHITEOG" then 2 else 1) |> string, true) |> ignore
|
||
item.SaleEnd |> Option.iter (fun time ->
|
||
let date = DateTimeOffset.FromUnixTimeSeconds(time).DateTime.ToUniversalTime()
|
||
if DateTime.UtcNow < date then
|
||
embed.AddField("⏰ Closes", $"<t:{time}:R>", true) |> ignore
|
||
else
|
||
embed.AddField("🚫 Closed", $"<t:{time}:R>", true) |> ignore)
|
||
|
||
item.TotalSold |> Option.iter (fun total -> embed.AddField("Total Sold", string total, true) |> ignore)
|
||
embed.Color <- getRankEmbedColor item.Rank
|
||
embed.Title <- titleText
|
||
embed.Description <- item.Item.Description
|
||
embed.ImageUrl <- "https://stage.degenz.game/blank-row.png"
|
||
if String.IsNullOrWhiteSpace(item.Item.IconUrl)
|
||
then embed
|
||
else embed.WithThumbnail(item.Item.IconUrl))
|
||
|> List.map (fun e -> e.Build())
|
||
|> Seq.ofList
|
||
|
||
let getBuyItemsEmbed storeId player (storeInventory : StoreItem list) =
|
||
let embeds = getItemEmbeds false storeInventory
|
||
let buttons =
|
||
storeInventory
|
||
|> List.map (fun item ->
|
||
let owned = player.Inventory |> List.exists (fun i -> i.Id = item.Item.Id)
|
||
let saleStillOngoing =
|
||
match item.SaleEnd with
|
||
| Some time ->
|
||
let date = DateTimeOffset.FromUnixTimeSeconds(time).DateTime.ToUniversalTime()
|
||
DateTime.UtcNow < date
|
||
| None -> true
|
||
let inStock = item.Available && (item.Stock > 0 || item.LimitStock = false)
|
||
match owned , inStock , saleStillOngoing with
|
||
| _ , false , _ ->
|
||
let msg = if item.Available then "Out of Stock" else "Unavailable"
|
||
DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"{item.Item.Name} ({msg})", true)
|
||
| false , true , true -> DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"Buy {item.Item.Name}")
|
||
| _ , _ , false -> DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"Closed {item.Item.Name}", true)
|
||
| _ ->
|
||
match checkDoesntExceedStackCap item.Item player with
|
||
| Ok _ -> DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"Buy {item.Item.Name}")
|
||
| Error _ -> DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"Own {item.Item.Name}", true)
|
||
:> DiscordComponent)
|
||
|
||
let builder =
|
||
DiscordFollowupMessageBuilder()
|
||
.AddEmbeds(embeds)
|
||
.AsEphemeral(true)
|
||
buttons
|
||
|> List.chunkBySize 5
|
||
|> List.iter (fun btns -> builder.AddComponents(btns) |> ignore)
|
||
builder
|
||
|
||
let purchaseItemEmbed quantity (item : Item) =
|
||
let embed = DiscordEmbedBuilder()
|
||
embed.ImageUrl <- item.ImageUrl
|
||
embed.Title <- $"Purchased {quantity}x {item.Name}"
|
||
match item.Type with
|
||
| ItemType.Jpeg ->
|
||
let itemName = item.Name.Replace("🎟️", "")
|
||
embed.Description <- $"Congratulations! You are in the draw for the {itemName}.\n\nWinners announced in <#{GuildEnvironment.channelGiveaway}>"
|
||
embed.ImageUrl <- item.ImageUrl
|
||
embed.Thumbnail <- DiscordEmbedBuilder.EmbedThumbnail()
|
||
embed.Thumbnail.Url <- item.IconUrl
|
||
| ItemType.Whitelist ->
|
||
embed.ImageUrl <- item.ImageUrl
|
||
let og = if item.Id = "WHITEOG" then "OG " else ""
|
||
embed.Description <- $"""
|
||
🎉 Congratulations, you purchased {og}WHITELIST!
|
||
|
||
**__Mint Day: 20th JUNE__**
|
||
Go to <#{GuildEnvironment.channelSubmitWallet}> to input your **Solana Wallet Address**, and confirm your Whitelist."""
|
||
| _ -> embed.Description <- $"Purchased {item.Name}"
|
||
embed
|
||
|
||
let getSellEmbed (items : Inventory) =
|
||
let embeds , buttons =
|
||
items
|
||
|> List.choose (fun item ->
|
||
match item.Attributes with
|
||
| CanSell price ->
|
||
let builder =
|
||
DiscordEmbedBuilder()
|
||
.AddField("Sell For 💰", $"{price} $GBT", true)
|
||
.WithTitle($"{item.Name}")
|
||
.WithColor(WeaponClass.getClassEmbedColor item)
|
||
.Build()
|
||
let button = DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Sell-{item.Id}", $"Sell {item.Name}") :> DiscordComponent
|
||
Some ( builder , button )
|
||
| _ -> None)
|
||
|> List.unzip
|
||
|
||
// TODO: We should alert the user that they have no sellable items
|
||
DiscordFollowupMessageBuilder()
|
||
.AddEmbeds(embeds)
|
||
.AddComponents(buttons)
|
||
.AsEphemeral(true)
|
||
|
||
let showJpegsEmbed (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
||
let! storeItems = DbService.getAllActiveStoreItems ()
|
||
let jpegs =
|
||
player.Inventory
|
||
|> Inventory.getItemsByType ItemType.Jpeg
|
||
|> List.choose (fun ii -> storeItems |> List.tryFind (fun si -> si.Item.Id = ii.Id))
|
||
match jpegs with
|
||
| [] -> do! Messaging.sendFollowUpMessage ctx $"You currently do not own any jpegs or raffle tickets. Go to <#{GuildEnvironment.channelBackAlley}> to buy some"
|
||
| jpegs ->
|
||
let embeds = getItemEmbeds true jpegs
|
||
let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true)
|
||
do! ctx.FollowUp builder |> Async.AwaitTask
|
||
})
|
||
|
||
let buy (storeId : string) (filterBy : ItemType option) (ctx : IDiscordContext) =
|
||
executePlayerAction ctx (fun player -> async {
|
||
try
|
||
let! items =
|
||
if storeId.StartsWith("BACKALLEY")
|
||
then DbService.getRafflesWithPurchases storeId
|
||
else DbService.getStoreItems storeId
|
||
if items.Length > 0 then
|
||
let items' =
|
||
match filterBy with
|
||
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
|
||
| None -> items
|
||
|> List.sortByDescending (fun i -> i.Rank)
|
||
let itemStore = getBuyItemsEmbed storeId player items'
|
||
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
||
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
|
||
else
|
||
do! Messaging.sendFollowUpMessage ctx "There are currently no items available, check back later"
|
||
with ex -> printfn $"{ex.Message}"
|
||
})
|
||
|
||
let buyForPlayer storeId player (filterBy : ItemType option) (ctx : IDiscordContext) = async {
|
||
try
|
||
let! items = DbService.getStoreItems storeId
|
||
if items.Length > 0 then
|
||
let items' =
|
||
match filterBy with
|
||
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
|
||
| None -> items
|
||
|> List.sortByDescending (fun i -> i.Rank)
|
||
let itemStore = getBuyItemsEmbed storeId player items'
|
||
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
||
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
|
||
else
|
||
do! Messaging.sendFollowUpMessage ctx "There are currently no items available, check back later"
|
||
with ex -> printfn $"{ex.Message}"
|
||
}
|
||
|
||
let sell itemType getItems (ctx : IDiscordContext) =
|
||
executePlayerAction ctx (fun player -> async {
|
||
let items = getItems player.Inventory
|
||
match checkHasItemsInArsenal itemType items with
|
||
| Ok _ -> let itemStore = getSellEmbed items
|
||
do! ctx.FollowUp(itemStore) |> Async.AwaitTask
|
||
| Error e -> do! ctx.FollowUp e |> Async.AwaitTask
|
||
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) itemType
|
||
})
|
||
|
||
let checkHasRequiredInvites storeItem player =
|
||
async {
|
||
match storeItem.RequiresInvites with
|
||
| Some amount ->
|
||
let! totalInvites = InviteTracker.getInvitedUserCount player.DiscordId
|
||
if amount <= totalInvites then
|
||
return Ok ()
|
||
else
|
||
let embedError =
|
||
let embed = DiscordEmbedBuilder()
|
||
embed.Description <- $"""
|
||
❌ **Degen**, can’t you **READ**?!
|
||
⚠️ **__Entry Requirements:__** {amount}x Invited User
|
||
|
||
To Enter this Raffle you must have **__INVITED__** {amount} Degen.
|
||
☑️ Go to <#{GuildEnvironment.channelRecruitment}>
|
||
☑️ Invite just {amount} Degen!
|
||
|
||
Then try again…
|
||
"""
|
||
DiscordFollowupMessageBuilder()
|
||
.AsEphemeral()
|
||
.AddEmbed(embed)
|
||
|> Error
|
||
return embedError
|
||
| None -> return Ok ()
|
||
}
|
||
|
||
let checkHasRequiredRole storeItem (user : DiscordMember) =
|
||
match storeItem.RequiresRole with
|
||
| Some roleId ->
|
||
if holderRoles |> Seq.contains roleId || user.Roles |> Seq.exists (fun r -> r.Id = roleId) then
|
||
Ok ()
|
||
else
|
||
let embed = DiscordEmbedBuilder()
|
||
if roleId = GuildEnvironment.roleMagicEden then
|
||
embed.Description <- $"""
|
||
❌ **Degen**, can’t you **READ**?!
|
||
⚠️ **__Entry Requirements:__** Have the <@&{GuildEnvironment.roleMagicEden}>
|
||
|
||
To get the <@&{GuildEnvironment.roleMagicEden}> role:
|
||
☑️ Upvote us on magic here: https://magiceden.io/drops/degenz_game
|
||
☑️ Post Proof in <#{GuildEnvironment.channelQuestProof}>
|
||
|
||
Then try again…"""
|
||
else
|
||
embed.Description <- $"""
|
||
❌ **Degen**, can’t you **READ**?!
|
||
⚠️ **__Entry Requirements:__** Have the <@&{roleId}>
|
||
|
||
Then try again…
|
||
"""
|
||
DiscordFollowupMessageBuilder()
|
||
.AsEphemeral()
|
||
.AddEmbed(embed)
|
||
|> Error
|
||
| None -> Ok ()
|
||
|
||
let checkIsHolder storeItem (user : DiscordMember) =
|
||
// TODO: Add a check to see if they have a a minimum role
|
||
match storeItem.RequiresRole with
|
||
| Some roleId ->
|
||
if holderRoles |> Seq.contains roleId then
|
||
if user.Roles |> Seq.exists (fun r -> holderRoles |> Seq.contains r.Id) then
|
||
Ok ()
|
||
else
|
||
let embed = DiscordEmbedBuilder()
|
||
embed.Description <- $"""
|
||
❌ **Degen**, can’t you **READ**?!
|
||
⚠️ **__Entry Requirements:__** Have the <@&{roleId}>
|
||
|
||
To become a verified holder
|
||
1️⃣️ If you still don't own a Degenz Game NFT, head over to https://magiceden.io/marketplace/degenz_game
|
||
2️⃣ Verify your wallet <#{GuildEnvironment.channelVerifyNft}>
|
||
|
||
Then try again…"""
|
||
DiscordFollowupMessageBuilder()
|
||
.AsEphemeral()
|
||
.AddEmbed(embed)
|
||
|> Error
|
||
else
|
||
Ok ()
|
||
| None -> Ok ()
|
||
|
||
// TODO: When you buy a shield, prompt the user to activate it
|
||
let handleBuyItem (dispatch : IDiscordContext -> Task) (ctx : IDiscordContext) itemId =
|
||
executePlayerAction ctx (fun player -> async {
|
||
let storeId = ctx.GetInteractionId().Split("-").[2]
|
||
let! result = asyncResult {
|
||
let! storeInventory = DbService.getStoreItems storeId
|
||
let storeItem = storeInventory |> List.find (fun si -> si.Item.Id = itemId)
|
||
do! checkHasSufficientFunds storeItem.Item player
|
||
do! checkHasStock storeItem
|
||
do! checkItemSaleStillActive storeItem
|
||
do! checkDoesntExceedStackCap storeItem.Item player
|
||
do! checkIsHolder storeItem (ctx.GetDiscordMember())
|
||
do! checkHasRequiredRole storeItem (ctx.GetDiscordMember())
|
||
do! checkHasRequiredInvites storeItem player
|
||
return storeItem
|
||
}
|
||
return!
|
||
result
|
||
|> handleResultWithEmbed ctx (fun storeItem -> async {
|
||
let price = match storeItem.Item.Attributes with CanBuy price -> price | _ -> 0<GBT>
|
||
try
|
||
do! dispatch ctx |> Async.AwaitTask
|
||
do! DbService.updatePlayerCurrency -price player.DiscordId |> Async.Ignore
|
||
do! DbService.addToPlayerInventory player.DiscordId storeItem.Item |> Async.Ignore
|
||
if storeItem.LimitStock = true && storeItem.Stock > 0 then
|
||
do! DbService.decrementItemStock storeItem.Item |> Async.Ignore
|
||
let builder = DiscordFollowupMessageBuilder().AsEphemeral(true)
|
||
let embed = purchaseItemEmbed 1 storeItem.Item
|
||
match storeItem.Item.Attributes , getTotalOwnedOfItem storeItem.Item player.Inventory |> Option.defaultValue 0 with
|
||
| CanStack max , amount ->
|
||
embed.AddField("Owned", $"{amount + 1}", true) |> ignore
|
||
embed.AddField("New $GBT Balance", $"`💰` {player.Bank - price} `(-{price} $GBT)`", true) |> ignore
|
||
if amount + 1 < max then
|
||
let btn = DiscordButtonComponent(WeaponClass.getClassButtonColor storeItem.Item, $"Buy-{storeItem.Item.Id}-{storeId}", $"Buy Another")
|
||
builder.AddComponents(btn) |> ignore
|
||
| _ -> ()
|
||
builder.AddEmbed(embed) |> ignore
|
||
do! ctx.FollowUp builder |> Async.AwaitTask
|
||
|
||
let builder = DiscordMessageBuilder()
|
||
builder.WithContent($"{player.Name} just purchased {storeItem.Item.Name}!") |> ignore
|
||
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)
|
||
do! channel.SendMessageAsync(builder)
|
||
|> Async.AwaitTask
|
||
|> Async.Ignore
|
||
|
||
do! Analytics.buyItemButton (ctx.GetDiscordMember()) storeItem.Item.Id price
|
||
with ex ->
|
||
printfn $"STORE ERROR: {ex.Message}"
|
||
})
|
||
})
|
||
|
||
let handleSell (ctx : IDiscordContext) itemId =
|
||
executePlayerAction ctx (fun player -> async {
|
||
let item = player.Inventory |> Inventory.findItemById itemId
|
||
do!
|
||
player
|
||
|> checkSoldItemAlready item
|
||
|> handleResultWithEmbed ctx (fun () -> async {
|
||
match item.Attributes with
|
||
| CanSell price ->
|
||
do!
|
||
[ DbService.updatePlayerCurrency price player.DiscordId |> Async.Ignore
|
||
DbService.removeFromPlayerInventory player.DiscordId item |> Async.Ignore
|
||
DbService.removeShieldEvent player.DiscordId itemId |> Async.Ignore
|
||
sendFollowUpMessage ctx $"Sold {item.Name} for {price}! New Balance: {player.Bank + price}"
|
||
Analytics.sellItemButton (ctx.GetDiscordMember()) item price ]
|
||
|> Async.Parallel
|
||
|> Async.Ignore
|
||
| _ -> ()
|
||
})
|
||
})
|
||
|
||
let handleJpegEvents _ (event : ComponentInteractionCreateEventArgs) =
|
||
let ctx = DiscordEventContext event :> IDiscordContext
|
||
let id = ctx.GetInteractionId()
|
||
let itemId = id.Split("-").[1]
|
||
let storeId = id.Split("-").[2]
|
||
match id with
|
||
| id when id.StartsWith("Buy") -> handleBuyItem (fun _ -> Task.CompletedTask) ctx itemId
|
||
| id when id.StartsWith("ShowStore") -> buy storeId None ctx
|
||
| id when id.StartsWith("ShowJpegInventory") -> showJpegsEmbed ctx
|
||
| _ ->
|
||
task {
|
||
let builder = DiscordInteractionResponseBuilder()
|
||
builder.IsEphemeral <- true
|
||
builder.Content <- $"Incorrect Action identifier {id}"
|
||
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
||
}
|
||
|
||
let handleStoreEvents _ (event : ComponentInteractionCreateEventArgs) =
|
||
let ctx = DiscordEventContext event :> IDiscordContext
|
||
let id = ctx.GetInteractionId()
|
||
let itemId = id.Split("-").[1]
|
||
let storeId = id.Split("-").[2]
|
||
match id with
|
||
| id when id.StartsWith("Buy") -> handleBuyItem (fun _ -> Task.CompletedTask) ctx itemId
|
||
| id when id.StartsWith("Sell") -> handleSell ctx itemId
|
||
| id when id.StartsWith("ShowHacks") -> buy storeId (Some ItemType.Hack) ctx
|
||
| id when id.StartsWith("ShowShields") -> buy storeId (Some ItemType.Shield) ctx
|
||
| _ ->
|
||
task {
|
||
let builder = DiscordInteractionResponseBuilder()
|
||
builder.IsEphemeral <- true
|
||
builder.Content <- $"Incorrect Action identifier {id}"
|
||
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
||
}
|
||
|> Async.AwaitTask
|
||
|> Async.Start
|
||
Task.CompletedTask
|
||
|
||
let sendBackalleyEmbed (ctx : IDiscordContext) =
|
||
async {
|
||
try
|
||
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelBackAlley)
|
||
let builder = DiscordMessageBuilder()
|
||
let embed = DiscordEmbedBuilder()
|
||
embed.ImageUrl <- "https://s7.gifyu.com/images/ezgif.com-gif-maker-23203b9dca779ba7cf.gif"
|
||
embed.Title <- "🎟️ Raffle Store"
|
||
embed.Color <- DiscordColor.Lilac
|
||
embed.Description <- $"Hey, what do you want, kid?\nI ain’t got all day…"
|
||
builder.AddEmbed embed |> ignore
|
||
let button3 = DiscordButtonComponent(ButtonStyle.Danger, $"ShowStore-0-BACKALLEY3", $"Holder Raffle") :> DiscordComponent
|
||
let button1 = DiscordButtonComponent(ButtonStyle.Success, $"ShowStore-0-BACKALLEY1", $"NFT Raffle") :> DiscordComponent
|
||
let button2 = DiscordButtonComponent(ButtonStyle.Success, $"ShowStore-0-BACKALLEY2", $"Whitelist Raffle") :> DiscordComponent
|
||
// let button3 = DiscordButtonComponent(ButtonStyle.Success, $"ShowStore-0-BACKALLEY3", $"USDT Raffles") :> DiscordComponent
|
||
let button4 = DiscordButtonComponent(ButtonStyle.Primary, $"ShowJpegInventory-0-0", $"My Stash") :> DiscordComponent
|
||
builder.AddComponents [| button3 ; button1 ; button2 ; button4 |] |> ignore
|
||
|
||
do! GuildEnvironment.botClientJpeg.Value.SendMessageAsync(channel, builder)
|
||
|> Async.AwaitTask
|
||
|> Async.Ignore
|
||
with e ->
|
||
printfn $"Error trying to get channel Jpeg Store\n\n{e.Message}"
|
||
} |> Async.RunSynchronously
|
||
|
||
let sendArmoryEmbed (ctx : IDiscordContext) =
|
||
async {
|
||
try
|
||
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelArmory)
|
||
let builder = DiscordMessageBuilder()
|
||
let embed = DiscordEmbedBuilder()
|
||
embed.ImageUrl <- "https://s8.gifyu.com/images/Shop_Degenz_Resampled.gif"
|
||
embed.Title <- "Weapons Armory"
|
||
embed.Color <- DiscordColor.Black
|
||
embed.Description <- "Buy Shields to protect yourself or buy Hacks to extract $GBT from others"
|
||
builder.AddEmbed embed |> ignore
|
||
let btn1 = DiscordButtonComponent(ButtonStyle.Success, $"ShowHacks-0-ARMORY", $"Hacks") :> DiscordComponent
|
||
let btn2 = DiscordButtonComponent(ButtonStyle.Success, $"ShowShields-0-ARMORY", $"Shields") :> DiscordComponent
|
||
builder.AddComponents [| btn1 ; btn2 |] |> ignore
|
||
|
||
do! GuildEnvironment.botClientStore.Value.SendMessageAsync(channel, builder)
|
||
|> Async.AwaitTask
|
||
|> Async.Ignore
|
||
with e ->
|
||
printfn $"Error trying to get channel Armory\n\n{e.Message}"
|
||
} |> Async.RunSynchronously
|
||
|