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
|
} |> Async.StartAsTask
|
||||||
:> Task
|
:> Task
|
||||||
//hackerBattleBot.add_InteractionCreated(AsyncEventHandler(asdf))
|
//hackerBattleBot.add_InteractionCreated(AsyncEventHandler(asdf))
|
||||||
hackerBattleBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
|
||||||
GuildEnvironment.botClientHacker <- Some hackerBattleBot
|
|
||||||
|
|
||||||
jpegBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
jpegBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
GuildEnvironment.botClientJpeg <- Some jpegBot
|
GuildEnvironment.botClientJpeg <- Some jpegBot
|
||||||
|
|
||||||
storeBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
storeBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
GuildEnvironment.botClientStore <- Some storeBot
|
GuildEnvironment.botClientStore <- Some storeBot
|
||||||
|
|
||||||
|
hackerBattleBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
|
GuildEnvironment.botClientHacker <- Some hackerBattleBot
|
||||||
|
|
||||||
adminBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
adminBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
|
|
||||||
inviterBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
inviterBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
|
@ -105,7 +105,7 @@ let getStoreItems (storeId : string) =
|
|||||||
|> Sql.connect
|
|> Sql.connect
|
||||||
|> Sql.parameters [ "sid", Sql.string storeId ]
|
|> Sql.parameters [ "sid", Sql.string storeId ]
|
||||||
|> Sql.query """
|
|> 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
|
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
|
FROM store_item
|
||||||
JOIN item i on store_item.item_id = i.id
|
JOIN item i on store_item.item_id = i.id
|
||||||
@ -116,6 +116,7 @@ let getStoreItems (storeId : string) =
|
|||||||
Stock = reader.int "stock"
|
Stock = reader.int "stock"
|
||||||
LimitStock = reader.bool "limit_stock"
|
LimitStock = reader.bool "limit_stock"
|
||||||
Available = reader.bool "available"
|
Available = reader.bool "available"
|
||||||
|
Rank = reader.int "rank"
|
||||||
SaleEnd = reader.int64OrNone "sale_end"
|
SaleEnd = reader.int64OrNone "sale_end"
|
||||||
TotalSold = None
|
TotalSold = None
|
||||||
RequiresInvites = reader.intOrNone "require_invites"
|
RequiresInvites = reader.intOrNone "require_invites"
|
||||||
@ -128,7 +129,7 @@ let getAllActiveStoreItems () =
|
|||||||
connStr
|
connStr
|
||||||
|> Sql.connect
|
|> Sql.connect
|
||||||
|> Sql.query """
|
|> 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
|
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
|
FROM store_item
|
||||||
JOIN item i on store_item.item_id = i.id
|
JOIN item i on store_item.item_id = i.id
|
||||||
@ -139,6 +140,7 @@ let getAllActiveStoreItems () =
|
|||||||
Stock = reader.int "stock"
|
Stock = reader.int "stock"
|
||||||
LimitStock = reader.bool "limit_stock"
|
LimitStock = reader.bool "limit_stock"
|
||||||
Available = reader.bool "available"
|
Available = reader.bool "available"
|
||||||
|
Rank = reader.int "rank"
|
||||||
SaleEnd = reader.int64OrNone "sale_end"
|
SaleEnd = reader.int64OrNone "sale_end"
|
||||||
TotalSold = None
|
TotalSold = None
|
||||||
RequiresInvites = reader.intOrNone "require_invites"
|
RequiresInvites = reader.intOrNone "require_invites"
|
||||||
@ -153,7 +155,7 @@ let getRafflesWithPurchases storeId =
|
|||||||
|> Sql.parameters [ "sid" , Sql.string storeId ]
|
|> Sql.parameters [ "sid" , Sql.string storeId ]
|
||||||
|> Sql.query """
|
|> Sql.query """
|
||||||
WITH raffles AS
|
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
|
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
|
FROM store_item
|
||||||
JOIN item i on store_item.item_id = i.id
|
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"
|
Stock = reader.int "stock"
|
||||||
LimitStock = reader.bool "limit_stock"
|
LimitStock = reader.bool "limit_stock"
|
||||||
Available = reader.bool "available"
|
Available = reader.bool "available"
|
||||||
|
Rank = reader.int "rank"
|
||||||
SaleEnd = reader.int64OrNone "sale_end"
|
SaleEnd = reader.int64OrNone "sale_end"
|
||||||
TotalSold = reader.intOrNone "total"
|
TotalSold = reader.intOrNone "total"
|
||||||
RequiresInvites = reader.intOrNone "require_invites"
|
RequiresInvites = reader.intOrNone "require_invites"
|
||||||
@ -181,7 +184,7 @@ let getStoreItemBySymbol (itemSymbol : string) =
|
|||||||
|> Sql.connect
|
|> Sql.connect
|
||||||
|> Sql.parameters [ "iid", Sql.string itemSymbol ]
|
|> Sql.parameters [ "iid", Sql.string itemSymbol ]
|
||||||
|> Sql.query """
|
|> 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
|
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
|
FROM store_item
|
||||||
JOIN item i on store_item.item_id = i.id
|
JOIN item i on store_item.item_id = i.id
|
||||||
@ -192,6 +195,7 @@ let getStoreItemBySymbol (itemSymbol : string) =
|
|||||||
Stock = reader.int "stock"
|
Stock = reader.int "stock"
|
||||||
LimitStock = reader.bool "limit_stock"
|
LimitStock = reader.bool "limit_stock"
|
||||||
Available = reader.bool "available"
|
Available = reader.bool "available"
|
||||||
|
Rank = reader.int "rank"
|
||||||
SaleEnd = reader.int64OrNone "sale_end"
|
SaleEnd = reader.int64OrNone "sale_end"
|
||||||
TotalSold = None
|
TotalSold = None
|
||||||
RequiresInvites = reader.intOrNone "require_invites"
|
RequiresInvites = reader.intOrNone "require_invites"
|
||||||
|
@ -144,6 +144,7 @@ type StoreItem = {
|
|||||||
LimitStock : bool
|
LimitStock : bool
|
||||||
Available : bool
|
Available : bool
|
||||||
TotalSold : int option
|
TotalSold : int option
|
||||||
|
Rank : int
|
||||||
SaleEnd : int64 option
|
SaleEnd : int64 option
|
||||||
RequiresRole : uint64 option
|
RequiresRole : uint64 option
|
||||||
RequiresInvites : int option
|
RequiresInvites : int option
|
||||||
|
@ -11,6 +11,18 @@ open Degenz.Messaging
|
|||||||
open Degenz.PlayerInteractions
|
open Degenz.PlayerInteractions
|
||||||
open FsToolkit.ErrorHandling
|
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 =
|
let embedWithError error =
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AsEphemeral()
|
.AsEphemeral()
|
||||||
@ -140,7 +152,7 @@ let getItemEmbeds owned (items : StoreItem list) =
|
|||||||
embed.AddField("🚫 Closed", $"<t:{time}:R>", true) |> ignore)
|
embed.AddField("🚫 Closed", $"<t:{time}:R>", true) |> ignore)
|
||||||
|
|
||||||
item.TotalSold |> Option.iter (fun total -> embed.AddField("Total Sold", string total, 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.Title <- titleText
|
||||||
embed.Description <- item.Item.Description
|
embed.Description <- item.Item.Description
|
||||||
embed.ImageUrl <- "https://stage.degenz.game/blank-row.png"
|
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
|
match owned , inStock , saleStillOngoing with
|
||||||
| _ , false , _ ->
|
| _ , false , _ ->
|
||||||
let msg = if item.Available then "Out of Stock" else "Unavailable"
|
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)
|
DiscordButtonComponent(getRankButtonColor item.Rank, $"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 , true , true -> DiscordButtonComponent(getRankButtonColor item.Rank, $"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)
|
| _ , _ , false -> DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"Closed {item.Item.Name}", true)
|
||||||
| _ ->
|
| _ ->
|
||||||
match checkDoesntExceedStackCap item.Item player with
|
match checkDoesntExceedStackCap item.Item player with
|
||||||
| Ok _ -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Buy {item.Item.Name}")
|
| Ok _ -> DiscordButtonComponent(getRankButtonColor item.Rank, $"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)
|
| Error _ -> DiscordButtonComponent(getRankButtonColor item.Rank, $"Buy-{item.Item.Id}-{storeId}", $"Own {item.Item.Name}", true)
|
||||||
:> DiscordComponent)
|
:> DiscordComponent)
|
||||||
|
|
||||||
let builder =
|
let builder =
|
||||||
@ -255,6 +267,7 @@ let buy (storeId : string) (filterBy : ItemType option) (ctx : IDiscordContext)
|
|||||||
match filterBy with
|
match filterBy with
|
||||||
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
|
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
|
||||||
| None -> items
|
| None -> items
|
||||||
|
|> List.sortByDescending (fun i -> i.Rank)
|
||||||
let itemStore = getBuyItemsEmbed storeId player items'
|
let itemStore = getBuyItemsEmbed storeId player items'
|
||||||
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
||||||
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
|
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
|
||||||
@ -271,6 +284,7 @@ let buyForPlayer storeId player (filterBy : ItemType option) (ctx : IDiscordCont
|
|||||||
match filterBy with
|
match filterBy with
|
||||||
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
|
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
|
||||||
| None -> items
|
| None -> items
|
||||||
|
|> List.sortByDescending (fun i -> i.Rank)
|
||||||
let itemStore = getBuyItemsEmbed storeId player items'
|
let itemStore = getBuyItemsEmbed storeId player items'
|
||||||
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
||||||
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
|
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
|
||||||
@ -320,7 +334,7 @@ Then try again…
|
|||||||
let checkHasRequiredRole storeItem (user : DiscordMember) =
|
let checkHasRequiredRole storeItem (user : DiscordMember) =
|
||||||
match storeItem.RequiresRole with
|
match storeItem.RequiresRole with
|
||||||
| Some roleId ->
|
| 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 ()
|
Ok ()
|
||||||
else
|
else
|
||||||
let embed = DiscordEmbedBuilder()
|
let embed = DiscordEmbedBuilder()
|
||||||
@ -347,6 +361,32 @@ Then try again…
|
|||||||
|> Error
|
|> Error
|
||||||
| None -> Ok ()
|
| 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
|
// TODO: When you buy a shield, prompt the user to activate it
|
||||||
let handleBuyItem (dispatch : IDiscordContext -> Task) (ctx : IDiscordContext) itemId =
|
let handleBuyItem (dispatch : IDiscordContext -> Task) (ctx : IDiscordContext) itemId =
|
||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
@ -358,6 +398,7 @@ let handleBuyItem (dispatch : IDiscordContext -> Task) (ctx : IDiscordContext) i
|
|||||||
do! checkHasStock storeItem
|
do! checkHasStock storeItem
|
||||||
do! checkItemSaleStillActive storeItem
|
do! checkItemSaleStillActive storeItem
|
||||||
do! checkDoesntExceedStackCap storeItem.Item player
|
do! checkDoesntExceedStackCap storeItem.Item player
|
||||||
|
do! checkIsHolder storeItem (ctx.GetDiscordMember())
|
||||||
do! checkHasRequiredRole storeItem (ctx.GetDiscordMember())
|
do! checkHasRequiredRole storeItem (ctx.GetDiscordMember())
|
||||||
do! checkHasRequiredInvites storeItem player
|
do! checkHasRequiredInvites storeItem player
|
||||||
return storeItem
|
return storeItem
|
||||||
@ -468,11 +509,12 @@ let sendBackalleyEmbed (ctx : IDiscordContext) =
|
|||||||
embed.Color <- DiscordColor.Lilac
|
embed.Color <- DiscordColor.Lilac
|
||||||
embed.Description <- $"Hey, what do you want, kid?\nI ain’t got all day…"
|
embed.Description <- $"Hey, what do you want, kid?\nI ain’t got all day…"
|
||||||
builder.AddEmbed embed |> ignore
|
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 button2 = DiscordButtonComponent(ButtonStyle.Success, $"ShowStore-0-BACKALLEY2", $"Whitelist Raffle") :> DiscordComponent
|
||||||
// let button3 = DiscordButtonComponent(ButtonStyle.Success, $"ShowStore-0-BACKALLEY3", $"USDT Raffles") :> DiscordComponent
|
// let button3 = DiscordButtonComponent(ButtonStyle.Success, $"ShowStore-0-BACKALLEY3", $"USDT Raffles") :> DiscordComponent
|
||||||
let button4 = DiscordButtonComponent(ButtonStyle.Primary, $"ShowJpegInventory-0-0", $"My Stash") :> 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)
|
do! GuildEnvironment.botClientJpeg.Value.SendMessageAsync(channel, builder)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
|
@ -46,6 +46,7 @@ let channelAnnouncements = getId "CHANNEL_ANNOUNCEMENTS"
|
|||||||
let channelGeneral = getId "CHANNEL_GENERAL"
|
let channelGeneral = getId "CHANNEL_GENERAL"
|
||||||
let channelQuests = getId "CHANNEL_QUESTS"
|
let channelQuests = getId "CHANNEL_QUESTS"
|
||||||
let channelQuestProof = getId "CHANNEL_QUEST_PROOF"
|
let channelQuestProof = getId "CHANNEL_QUEST_PROOF"
|
||||||
|
let channelVerifyNft = getId "CHANNEL_VERIFY_NFT"
|
||||||
//let channelThievery = getId "CHANNEL_THIEVERY"
|
//let channelThievery = getId "CHANNEL_THIEVERY"
|
||||||
let botIdHackerBattle = getId "BOT_HACKER_BATTLE"
|
let botIdHackerBattle = getId "BOT_HACKER_BATTLE"
|
||||||
let botIdArmory = getId "BOT_ARMORY"
|
let botIdArmory = getId "BOT_ARMORY"
|
||||||
@ -63,6 +64,10 @@ let roleMagicEden = getId "ROLE_MAGICEDEN"
|
|||||||
let roleRecruiter1x = getId "ROLE_RECRUITER_1X"
|
let roleRecruiter1x = getId "ROLE_RECRUITER_1X"
|
||||||
let roleRecruiter2x = getId "ROLE_RECRUITER_2X"
|
let roleRecruiter2x = getId "ROLE_RECRUITER_2X"
|
||||||
let roleRecruiter3x = getId "ROLE_RECRUITER_3X"
|
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 botClientRecruit : DiscordClient option = None
|
||||||
let mutable botClientHacker : DiscordClient option = None
|
let mutable botClientHacker : DiscordClient option = None
|
||||||
let mutable botClientSlots : DiscordClient option = None
|
let mutable botClientSlots : DiscordClient option = None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user