Add NFT holder check and rank feature for store item
This commit is contained in:
parent
977e70d97d
commit
fb9c638848
@ -100,15 +100,15 @@ let asdf _ (event : DSharpPlus.EventArgs.InteractionCreateEventArgs) =
|
||||
} |> Async.StartAsTask
|
||||
:> Task
|
||||
//hackerBattleBot.add_InteractionCreated(AsyncEventHandler(asdf))
|
||||
hackerBattleBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
GuildEnvironment.botClientHacker <- Some hackerBattleBot
|
||||
|
||||
jpegBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
GuildEnvironment.botClientJpeg <- Some jpegBot
|
||||
|
||||
storeBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
GuildEnvironment.botClientStore <- Some storeBot
|
||||
|
||||
hackerBattleBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
GuildEnvironment.botClientHacker <- Some hackerBattleBot
|
||||
|
||||
adminBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
|
||||
inviterBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
|
@ -105,7 +105,7 @@ let getStoreItems (storeId : string) =
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "sid", Sql.string storeId ]
|
||||
|> Sql.query """
|
||||
SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,
|
||||
SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,rank,
|
||||
buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,attack_power,defense_power,class_name,max_stack,mods
|
||||
FROM store_item
|
||||
JOIN item i on store_item.item_id = i.id
|
||||
@ -116,6 +116,7 @@ let getStoreItems (storeId : string) =
|
||||
Stock = reader.int "stock"
|
||||
LimitStock = reader.bool "limit_stock"
|
||||
Available = reader.bool "available"
|
||||
Rank = reader.int "rank"
|
||||
SaleEnd = reader.int64OrNone "sale_end"
|
||||
TotalSold = None
|
||||
RequiresInvites = reader.intOrNone "require_invites"
|
||||
@ -128,7 +129,7 @@ let getAllActiveStoreItems () =
|
||||
connStr
|
||||
|> Sql.connect
|
||||
|> Sql.query """
|
||||
SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,
|
||||
SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,rank,
|
||||
buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,attack_power,defense_power,class_name,max_stack,mods
|
||||
FROM store_item
|
||||
JOIN item i on store_item.item_id = i.id
|
||||
@ -139,6 +140,7 @@ let getAllActiveStoreItems () =
|
||||
Stock = reader.int "stock"
|
||||
LimitStock = reader.bool "limit_stock"
|
||||
Available = reader.bool "available"
|
||||
Rank = reader.int "rank"
|
||||
SaleEnd = reader.int64OrNone "sale_end"
|
||||
TotalSold = None
|
||||
RequiresInvites = reader.intOrNone "require_invites"
|
||||
@ -153,7 +155,7 @@ let getRafflesWithPurchases storeId =
|
||||
|> Sql.parameters [ "sid" , Sql.string storeId ]
|
||||
|> Sql.query """
|
||||
WITH raffles AS
|
||||
(SELECT store_id,stock,available,limit_stock,i.id AS raffle_id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,
|
||||
(SELECT store_id,stock,available,limit_stock,i.id AS raffle_id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,rank,
|
||||
buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,attack_power,defense_power,class_name,max_stack,mods
|
||||
FROM store_item
|
||||
JOIN item i on store_item.item_id = i.id
|
||||
@ -168,6 +170,7 @@ FULL JOIN (SELECT item_id, count(*) AS total FROM inventory_item
|
||||
Stock = reader.int "stock"
|
||||
LimitStock = reader.bool "limit_stock"
|
||||
Available = reader.bool "available"
|
||||
Rank = reader.int "rank"
|
||||
SaleEnd = reader.int64OrNone "sale_end"
|
||||
TotalSold = reader.intOrNone "total"
|
||||
RequiresInvites = reader.intOrNone "require_invites"
|
||||
@ -181,7 +184,7 @@ let getStoreItemBySymbol (itemSymbol : string) =
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "iid", Sql.string itemSymbol ]
|
||||
|> Sql.query """
|
||||
SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,
|
||||
SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,require_role,require_invites,sale_end,rank,
|
||||
buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,attack_power,defense_power,class_name,max_stack,mods
|
||||
FROM store_item
|
||||
JOIN item i on store_item.item_id = i.id
|
||||
@ -192,6 +195,7 @@ let getStoreItemBySymbol (itemSymbol : string) =
|
||||
Stock = reader.int "stock"
|
||||
LimitStock = reader.bool "limit_stock"
|
||||
Available = reader.bool "available"
|
||||
Rank = reader.int "rank"
|
||||
SaleEnd = reader.int64OrNone "sale_end"
|
||||
TotalSold = None
|
||||
RequiresInvites = reader.intOrNone "require_invites"
|
||||
|
@ -144,6 +144,7 @@ type StoreItem = {
|
||||
LimitStock : bool
|
||||
Available : bool
|
||||
TotalSold : int option
|
||||
Rank : int
|
||||
SaleEnd : int64 option
|
||||
RequiresRole : uint64 option
|
||||
RequiresInvites : int option
|
||||
|
@ -11,6 +11,18 @@ 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()
|
||||
@ -140,7 +152,7 @@ let getItemEmbeds owned (items : StoreItem list) =
|
||||
embed.AddField("🚫 Closed", $"<t:{time}:R>", true) |> ignore)
|
||||
|
||||
item.TotalSold |> Option.iter (fun total -> embed.AddField("Total Sold", string total, true) |> ignore)
|
||||
embed.Color <- WeaponClass.getClassEmbedColor item.Item
|
||||
embed.Color <- getRankEmbedColor item.Rank
|
||||
embed.Title <- titleText
|
||||
embed.Description <- item.Item.Description
|
||||
embed.ImageUrl <- "https://stage.degenz.game/blank-row.png"
|
||||
@ -166,13 +178,13 @@ let getBuyItemsEmbed storeId player (storeInventory : StoreItem list) =
|
||||
match owned , inStock , saleStillOngoing with
|
||||
| _ , false , _ ->
|
||||
let msg = if item.Available then "Out of Stock" else "Unavailable"
|
||||
DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"{item.Item.Name} ({msg})", true)
|
||||
| false , true , true -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Buy {item.Item.Name}")
|
||||
| _ , _ , false -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Closed {item.Item.Name}", true)
|
||||
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(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Buy {item.Item.Name}")
|
||||
| Error _ -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Own {item.Item.Name}", true)
|
||||
| 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 =
|
||||
@ -255,6 +267,7 @@ let buy (storeId : string) (filterBy : ItemType option) (ctx : IDiscordContext)
|
||||
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
|
||||
@ -271,6 +284,7 @@ let buyForPlayer storeId player (filterBy : ItemType option) (ctx : IDiscordCont
|
||||
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
|
||||
@ -320,7 +334,7 @@ Then try again…
|
||||
let checkHasRequiredRole storeItem (user : DiscordMember) =
|
||||
match storeItem.RequiresRole with
|
||||
| Some roleId ->
|
||||
if user.Roles |> Seq.exists (fun r -> r.Id = roleId) then
|
||||
if holderRoles |> Seq.contains roleId || user.Roles |> Seq.exists (fun r -> r.Id = roleId) then
|
||||
Ok ()
|
||||
else
|
||||
let embed = DiscordEmbedBuilder()
|
||||
@ -347,6 +361,32 @@ Then try again…
|
||||
|> 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 {
|
||||
@ -358,6 +398,7 @@ let handleBuyItem (dispatch : IDiscordContext -> Task) (ctx : IDiscordContext) i
|
||||
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
|
||||
@ -468,11 +509,12 @@ let sendBackalleyEmbed (ctx : IDiscordContext) =
|
||||
embed.Color <- DiscordColor.Lilac
|
||||
embed.Description <- $"Hey, what do you want, kid?\nI ain’t got all day…"
|
||||
builder.AddEmbed embed |> ignore
|
||||
let button1 = DiscordButtonComponent(ButtonStyle.Danger, $"ShowStore-0-BACKALLEY1", $"NFT Raffle") :> DiscordComponent
|
||||
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 [| button1 ; button2 ; button4 |] |> ignore
|
||||
builder.AddComponents [| button3 ; button1 ; button2 ; button4 |] |> ignore
|
||||
|
||||
do! GuildEnvironment.botClientJpeg.Value.SendMessageAsync(channel, builder)
|
||||
|> Async.AwaitTask
|
||||
|
@ -46,6 +46,7 @@ let channelAnnouncements = getId "CHANNEL_ANNOUNCEMENTS"
|
||||
let channelGeneral = getId "CHANNEL_GENERAL"
|
||||
let channelQuests = getId "CHANNEL_QUESTS"
|
||||
let channelQuestProof = getId "CHANNEL_QUEST_PROOF"
|
||||
let channelVerifyNft = getId "CHANNEL_VERIFY_NFT"
|
||||
//let channelThievery = getId "CHANNEL_THIEVERY"
|
||||
let botIdHackerBattle = getId "BOT_HACKER_BATTLE"
|
||||
let botIdArmory = getId "BOT_ARMORY"
|
||||
@ -63,6 +64,10 @@ let roleMagicEden = getId "ROLE_MAGICEDEN"
|
||||
let roleRecruiter1x = getId "ROLE_RECRUITER_1X"
|
||||
let roleRecruiter2x = getId "ROLE_RECRUITER_2X"
|
||||
let roleRecruiter3x = getId "ROLE_RECRUITER_3X"
|
||||
let roleHolder1 = getId "ROLE_HOLDER_1"
|
||||
let roleHolder5 = getId "ROLE_HOLDER_5"
|
||||
let roleHolder10 = getId "ROLE_HOLDER_10"
|
||||
let roleHolder50 = getId "ROLE_HOLDER_50"
|
||||
let mutable botClientRecruit : DiscordClient option = None
|
||||
let mutable botClientHacker : DiscordClient option = None
|
||||
let mutable botClientSlots : DiscordClient option = None
|
||||
|
Loading…
x
Reference in New Issue
Block a user