Modify models to use string ids instead of ints, icon urls, armory embed

This commit is contained in:
Joseph Ferano 2022-05-02 12:44:53 +07:00
parent 892db88c20
commit 1f58bdba60
10 changed files with 136 additions and 120 deletions

View File

@ -16,6 +16,7 @@ type InitEmbeds =
| Whitelist = 1 | Whitelist = 1
| Slots = 2 | Slots = 2
| JpegStore = 3 | JpegStore = 3
| Armory = 4
let handleGuildDownloadReady (_ : DiscordClient) (event : GuildDownloadCompletedEventArgs) = let handleGuildDownloadReady (_ : DiscordClient) (event : GuildDownloadCompletedEventArgs) =
task { task {
@ -35,7 +36,8 @@ let sendEmbed embed (ctx : IDiscordContext) =
| InitEmbeds.Dojo -> Trainer.sendInitialEmbed ctx | InitEmbeds.Dojo -> Trainer.sendInitialEmbed ctx
| InitEmbeds.Whitelist -> InviteTracker.sendInitialEmbed ctx | InitEmbeds.Whitelist -> InviteTracker.sendInitialEmbed ctx
| InitEmbeds.Slots -> SlotMachine.sendInitialEmbedFromSlashCommand ctx | InitEmbeds.Slots -> SlotMachine.sendInitialEmbedFromSlashCommand ctx
| InitEmbeds.JpegStore -> Store.sendInitialEmbed ctx | InitEmbeds.JpegStore -> Store.sendBackalleyEmbed ctx
| InitEmbeds.Armory -> Store.sendArmoryEmbed ctx
| _ -> () | _ -> ()
do! Messaging.sendSimpleResponse ctx "Sent!" do! Messaging.sendSimpleResponse ctx "Sent!"
} :> Task } :> Task

View File

@ -21,11 +21,11 @@ let readItem (reader : RowReader) =
| _ -> Add (int modAmount) | _ -> Add (int modAmount)
let ( _ , stat ) = StatId.TryParse(targetStat) let ( _ , stat ) = StatId.TryParse(targetStat)
{ TargetStat = stat ; Effect = fx } { TargetStat = stat ; Effect = fx }
{ Item.Id = reader.int "id" { Item.Id = reader.string "id"
Item.Name = reader.string "name" Item.Name = reader.string "name"
Item.Description = reader.string "description" Item.Description = reader.string "description"
Item.IconUrl = reader.string "icon" Item.IconUrl = reader.string "icon_url"
Item.Symbol = reader.string "symbol" Item.ImageUrl = reader.string "image_url"
Item.Type = Item.Type =
match reader.string "category" with match reader.string "category" with
| "Hack" -> ItemType.Hack | "Hack" -> ItemType.Hack
@ -57,7 +57,7 @@ let getPlayerInventory (did : uint64) =
|> Sql.connect |> Sql.connect
|> Sql.parameters [ "did", Sql.string (string did) ] |> Sql.parameters [ "did", Sql.string (string did) ]
|> Sql.query """ |> Sql.query """
SELECT ii.id,ii.symbol,name,description,icon,category,buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume, SELECT ii.id,name,description,icon_url,image_url,category,buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,
attack_power,defense_power,class_name,max_stack,mods attack_power,defense_power,class_name,max_stack,mods
FROM inventory_item FROM inventory_item
JOIN item ii on inventory_item.item_id = ii.id JOIN item ii on inventory_item.item_id = ii.id
@ -70,7 +70,7 @@ let getPlayerInventory (did : uint64) =
let addToPlayerInventory (did : uint64) (item : Item) = let addToPlayerInventory (did : uint64) (item : Item) =
connStr connStr
|> Sql.connect |> Sql.connect
|> Sql.parameters [ ( "@did" , Sql.string (string did) ) ; ( "iid" , Sql.int item.Id )] |> Sql.parameters [ ( "@did" , Sql.string (string did) ) ; ( "iid" , Sql.string item.Id )]
|> Sql.query """ |> Sql.query """
INSERT INTO inventory_item (item_id, user_id) INSERT INTO inventory_item (item_id, user_id)
VALUES (@iid, (SELECT id FROM "user" WHERE discord_id = @did)); VALUES (@iid, (SELECT id FROM "user" WHERE discord_id = @did));
@ -78,29 +78,29 @@ let addToPlayerInventory (did : uint64) (item : Item) =
|> Sql.executeNonQueryAsync |> Sql.executeNonQueryAsync
|> Async.AwaitTask |> Async.AwaitTask
let getStoreSymbol (channelId : uint64) = let getStoreSymbol (storeId : string) =
connStr connStr
|> Sql.connect |> Sql.connect
|> Sql.parameters [ "cid", Sql.string (string channelId) ] |> Sql.parameters [ "sid", Sql.string storeId ]
|> Sql.query """ |> Sql.query """
SELECT symbol FROM store WHERE channel_id = @cid SELECT store_id FROM store_item WHERE channel_id = @cid
""" """
|> Sql.executeRowAsync (fun read -> read.string "symbol") |> Sql.executeRowAsync (fun read -> read.string "id")
|> Async.AwaitTask |> Async.AwaitTask
let getStoreItems (channelId : uint64) = let getStoreItems (storeId : string) =
connStr connStr
|> Sql.connect |> Sql.connect
|> Sql.parameters [ "cid", Sql.string (string channelId) ] |> Sql.parameters [ "sid", Sql.string storeId ]
|> Sql.query """ |> Sql.query """
SELECT stock,available,limit_stock,i.id,i.symbol,name,description,icon,category,buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume, SELECT store_id,stock,available,limit_stock,i.id,name,description,icon_url,image_url,category,buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,
attack_power,defense_power,class_name,max_stack,mods attack_power,defense_power,class_name,max_stack,mods
FROM store_item FROM store_item
JOIN store st on store_item.store_id = st.id
JOIN item i on store_item.item_id = i.id JOIN item i on store_item.item_id = i.id
WHERE channel_id = @cid AND available; WHERE store_id = @sid;
""" """
|> Sql.executeAsync (fun reader -> { |> Sql.executeAsync (fun reader -> {
StoreId = reader.string "store_id"
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"
@ -111,7 +111,7 @@ let getStoreItems (channelId : uint64) =
let decrementItemStock (item : Item) = let decrementItemStock (item : Item) =
connStr connStr
|> Sql.connect |> Sql.connect
|> Sql.parameters [ ( "iid" , Sql.int item.Id) ] |> Sql.parameters [ ( "iid" , Sql.string item.Id) ]
|> Sql.query """ |> Sql.query """
UPDATE store_item SET stock = GREATEST(stock - 1, 0) UPDATE store_item SET stock = GREATEST(stock - 1, 0)
WHERE store_item.item_id = @iid WHERE store_item.item_id = @iid
@ -124,9 +124,9 @@ let getWeapons () =
connStr connStr
|> Sql.connect |> Sql.connect
|> Sql.query """ |> Sql.query """
SELECT i.id,i.symbol,name,description,icon,category,buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume, SELECT i.id,i.name,description,icon_url,image_url,category,buy_price,sell_price,rate_limit,expiration,drop_chance,can_trade,can_consume,
attack_power,defense_power,class_name,max_stack,mods attack_power,defense_power,class_name,max_stack,mods
FROM item WHERE category = 'Hack' OR symbol = 'Shield' FROM item WHERE category = 'Hack' OR category = 'Shield'
""" """
|> Sql.executeAsync readItem |> Sql.executeAsync readItem
|> Async.AwaitTask |> Async.AwaitTask
@ -134,7 +134,7 @@ let getWeapons () =
let consumeItem (did : uint64) (item : Item) = let consumeItem (did : uint64) (item : Item) =
connStr connStr
|> Sql.connect |> Sql.connect
|> Sql.parameters [ ( "@did" , Sql.string (string did) ) ; ( "iid" , Sql.int item.Id )] |> Sql.parameters [ ( "@did" , Sql.string (string did) ) ; ( "iid" , Sql.string item.Id )]
|> Sql.query """ |> Sql.query """
DELETE FROM inventory_item DELETE FROM inventory_item
WHERE id IN (SELECT id FROM inventory_item WHERE id IN (SELECT id FROM inventory_item
@ -160,9 +160,9 @@ let getPlayerEvents (did : uint64) =
IsInstigator = read.bool "is_instigator" IsInstigator = read.bool "is_instigator"
Success = read.bool "success" Success = read.bool "success"
Adversary = { Id = read.string "adversary_id" |> uint64 ; Name = read.string "adversary_name" } Adversary = { Id = read.string "adversary_id" |> uint64 ; Name = read.string "adversary_name" }
HackId = read.int "item_id" HackId = read.string "item_id"
} }
| "Shielding" -> Shielding (read.int "item_id") | "Shielding" -> Shielding (read.string "item_id")
| "Stealing" -> Stealing ( read.bool "is_instigator" , { Id = read.string "adversary_id" |> uint64 ; Name = read.string "adversary_name" } ) | "Stealing" -> Stealing ( read.bool "is_instigator" , { Id = read.string "adversary_id" |> uint64 ; Name = read.string "adversary_name" } )
| "PlayingSlot" -> PlayingSlot | "PlayingSlot" -> PlayingSlot
| _ -> Imprison | _ -> Imprison
@ -298,7 +298,7 @@ let removeShieldEvent (did : uint64) shieldId =
|> Sql.connect |> Sql.connect
|> Sql.parameters |> Sql.parameters
[ ( "did" , Sql.string (string did) ) [ ( "did" , Sql.string (string did) )
( "shield_id", Sql.int shieldId ) ] ( "shield_id", Sql.string shieldId ) ]
|> Sql.query """ |> Sql.query """
WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did)
DELETE FROM player_event USING usr WHERE user_id = usr.id and event_type = 'Shielding' and item_id = @shield_id DELETE FROM player_event USING usr WHERE user_id = usr.id and event_type = 'Shielding' and item_id = @shield_id
@ -314,7 +314,7 @@ let addPlayerEvent (did : uint64) (playerEvent : PlayerEvent) =
( "did", Sql.string (string did) ) ( "did", Sql.string (string did) )
( "success" , Sql.bool h.Success ) ( "success" , Sql.bool h.Success )
( "is_instigator", Sql.bool h.IsInstigator ) ( "is_instigator", Sql.bool h.IsInstigator )
( "item_id", Sql.int h.HackId ) ( "item_id", Sql.string h.HackId )
( "cooldown", Sql.int (int playerEvent.Cooldown) ) ( "cooldown", Sql.int (int playerEvent.Cooldown) )
( "adversary_id", Sql.string (string h.Adversary.Id) ) ( "adversary_id", Sql.string (string h.Adversary.Id) )
( "adversary_name", Sql.string (string h.Adversary.Name) ) ( "adversary_name", Sql.string (string h.Adversary.Name) )
@ -327,7 +327,7 @@ let addPlayerEvent (did : uint64) (playerEvent : PlayerEvent) =
| Shielding id -> | Shielding id ->
[ [
( "did" , Sql.string (string did) ) ( "did" , Sql.string (string did) )
( "item_id", Sql.int id ) ( "item_id", Sql.string id )
( "cooldown", Sql.int (int playerEvent.Cooldown) ) ( "cooldown", Sql.int (int playerEvent.Cooldown) )
] , ] ,
""" """
@ -379,7 +379,7 @@ let getRandomHackablePlayers (did : uint64) =
|> Sql.query """ |> Sql.query """
SELECT discord_id, display_name FROM "user" SELECT discord_id, display_name FROM "user"
JOIN user_achievements_achievement uaa ON "user".id = uaa.user_id JOIN user_achievements_achievement uaa ON "user".id = uaa.user_id
JOIN achievement a ON uaa.achievement_id = a.id AND a.symbol = 'FINISHED_TRAINER' JOIN achievement a ON uaa.achievement_id = a.id AND a.id = 'FINISHED_TRAINER'
WHERE "user".in_game = true AND gbt > 20 AND "user".discord_id != @did WHERE "user".in_game = true AND gbt > 20 AND "user".discord_id != @did
ORDER BY random() LIMIT 10 ORDER BY random() LIMIT 10
""" """

View File

@ -3,32 +3,11 @@ module Degenz.Embeds
open System open System
open Degenz open Degenz
open Degenz.Messaging open Degenz.Messaging
open Degenz.Types
open DSharpPlus.Entities open DSharpPlus.Entities
let hackGif = "https://s10.gifyu.com/images/Hacker-Degenz-V20ce8eb832734aa62-min.gif" let hackGif = "https://s10.gifyu.com/images/Hacker-Degenz-V20ce8eb832734aa62-min.gif"
let shieldGif = "https://s10.gifyu.com/images/Defense-Degenz-V2-min.gif" let shieldGif = "https://s10.gifyu.com/images/Defense-Degenz-V2-min.gif"
let getItemIcon id =
match enum<ItemId>(id) with
| ItemId.Virus -> Some "https://s10.gifyu.com/images/Virus-icon.jpg"
| ItemId.RemoteAccess -> Some "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.jpg"
| ItemId.Worm -> Some "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.jpg"
| ItemId.Firewall -> Some "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-1.jpg"
| ItemId.Encryption -> Some "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.jpg"
| ItemId.Cypher -> Some "https://s10.gifyu.com/images/Cypher-Smaller.jpg"
| _ -> None
let getItemGif id =
match enum<ItemId>(id) with
| ItemId.Virus -> "https://s10.gifyu.com/images/Attack-DegenZ-1.gif"
| ItemId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.gif"
| ItemId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.gif"
| ItemId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-min.gif"
| ItemId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.gif"
| ItemId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.gif"
| _ -> hackGif
let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) (items : Inventory) ignoreCooldown = let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) (items : Inventory) ignoreCooldown =
items items
|> List.map (fun item -> |> List.map (fun item ->
@ -96,7 +75,7 @@ let pickHack actionId attacker defender isTrainer =
let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : HackItem) = let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : HackItem) =
let embed = let embed =
DiscordEmbedBuilder() DiscordEmbedBuilder()
.WithImageUrl(getItemGif hack.Id) .WithImageUrl(hack.ImageUrl)
.WithTitle("Hack Attack") .WithTitle("Hack Attack")
.WithDescription($"You successfully hacked <@{targetId}> using {hack.Name}" .WithDescription($"You successfully hacked <@{targetId}> using {hack.Name}"
+ (if earnedMoney then $", and took {amountTaken} 💰$GBT from them!" else "!")) + (if earnedMoney then $", and took {amountTaken} 💰$GBT from them!" else "!"))
@ -106,7 +85,7 @@ let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : H
.AsEphemeral(true) .AsEphemeral(true)
let responseCreatedShield (shield : ShieldItem) = let responseCreatedShield (shield : ShieldItem) =
let embed = DiscordEmbedBuilder().WithImageUrl(getItemGif shield.Id) let embed = DiscordEmbedBuilder().WithImageUrl(shield.ImageUrl)
embed.Title <- "Mounted Shield" embed.Title <- "Mounted Shield"
embed.Description <- $"Mounted {shield.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).TotalHours} hours" embed.Description <- $"Mounted {shield.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).TotalHours} hours"

View File

@ -24,6 +24,8 @@ module Inventory =
Name = item.Name Name = item.Name
Price = buyPrice Price = buyPrice
Cooldown = cooldown Cooldown = cooldown
IconUrl = item.IconUrl
ImageUrl = item.ImageUrl
Power = power Power = power
Class = ``class`` } Class = ``class`` }
| _ -> None | _ -> None
@ -35,6 +37,8 @@ module Inventory =
Name = item.Name Name = item.Name
Price = buyPrice Price = buyPrice
Cooldown = cooldown Cooldown = cooldown
IconUrl = item.IconUrl
ImageUrl = item.ImageUrl
Resistance = resistance Resistance = resistance
Class = ``class`` } Class = ``class`` }
| _ -> None | _ -> None
@ -67,15 +71,16 @@ module WeaponClass =
let getClassEmbedColor item = let getClassEmbedColor item =
match item.Attributes with match item.Attributes with
| CanClass "0" -> DiscordColor.Red | CanClass "NETWORK" -> DiscordColor.Red
| CanClass "1" -> DiscordColor.Blurple | CanClass "EXPLOIT" -> DiscordColor.Blurple
| CanClass "2" -> DiscordColor.Green | CanClass "PENETRATION" -> DiscordColor.Green
| _ -> DiscordColor.Blurple | _ -> DiscordColor.Blurple
let getGoodAgainst = function let getGoodAgainst = function
| "0" -> ( ItemId.Firewall , ItemId.Virus ) | "NETWORK" -> ( ItemId.FIREWALL , ItemId.VIRUS )
| "1" -> ( ItemId.Encryption , ItemId.RemoteAccess ) | "EXPLOIT" -> ( ItemId.ENCRYPTION , ItemId.REMOTE )
| _ -> ( ItemId.Cypher , ItemId.Worm ) | "PENETRATION" -> ( ItemId.CYPHER , ItemId.WORM )
| _ -> ( ItemId.FIREWALL , ItemId.VIRUS )
module Player = module Player =
let getHackEvents player = let getHackEvents player =

View File

@ -17,16 +17,12 @@ module Range =
let constrain value range = if value < range.Min then range.Min elif value > range.Max then range.Max else value let constrain value range = if value < range.Min then range.Min elif value > range.Max then range.Max else value
type ItemId = type ItemId =
| Virus = 0 | VIRUS = 0
| RemoteAccess = 1 | REMOTE = 1
| Worm = 2 | WORM = 2
| Firewall = 6 | FIREWALL = 6
| Encryption = 7 | ENCRYPTION = 7
| Cypher = 8 | CYPHER = 8
| ProteinPowder = 12
| ToroLoco = 13
| Cigs = 14
| MoonPie = 15
type StatId = type StatId =
| Strength = 0 | Strength = 0
@ -67,12 +63,12 @@ type HackEvent = {
IsInstigator : bool IsInstigator : bool
Adversary : DiscordPlayer Adversary : DiscordPlayer
Success : bool Success : bool
HackId : int HackId : string
} }
type PlayerEventType = type PlayerEventType =
| Hacking of HackEvent | Hacking of HackEvent
| Shielding of shieldId : int | Shielding of shieldId : string
| Stealing of instigator : bool * adversary : DiscordPlayer | Stealing of instigator : bool * adversary : DiscordPlayer
| PlayingSlot | PlayingSlot
| Imprison | Imprison
@ -130,16 +126,17 @@ let (|CanClass|_|) itemAttrs = itemAttrs |> List.tryPick (function Classable
let (|CanStack|_|) itemAttrs = itemAttrs |> List.tryPick (function Stackable m -> Some m | _ -> None) let (|CanStack|_|) itemAttrs = itemAttrs |> List.tryPick (function Stackable m -> Some m | _ -> None)
type Item = { type Item = {
Id : int Id : string
Name : string Name : string
Description : string Description : string
Type : ItemType Type : ItemType
Symbol : string
IconUrl : string IconUrl : string
ImageUrl : string
Attributes : ItemAttribute list Attributes : ItemAttribute list
} }
type StoreItem = { type StoreItem = {
StoreId : string
Stock : int Stock : int
LimitStock : bool LimitStock : bool
Available : bool Available : bool
@ -147,19 +144,23 @@ type StoreItem = {
} }
type HackItem = { type HackItem = {
Id : int Id : string
Name : string Name : string
Price : int<GBT> Price : int<GBT>
Cooldown : int<mins> Cooldown : int<mins>
IconUrl : string
ImageUrl : string
Power : int Power : int
Class : string Class : string
} }
type ShieldItem = { type ShieldItem = {
Id : int Id : string
Name : string Name : string
Price : int<GBT> Price : int<GBT>
Cooldown : int<mins> Cooldown : int<mins>
IconUrl : string
ImageUrl : string
Resistance : int Resistance : int
Class : string Class : string
} }

View File

@ -164,7 +164,7 @@ let hack (target : DiscordUser) (ctx : IDiscordContext) =
let handleAttack (ctx : IDiscordContext) = let handleAttack (ctx : IDiscordContext) =
executePlayerAction ctx (fun attacker -> async { executePlayerAction ctx (fun attacker -> async {
let tokens = ctx.GetInteractionId().Split("-") let tokens = ctx.GetInteractionId().Split("-")
let hackId = int tokens.[1] let hackId = tokens.[1]
// TODO: This sucks // TODO: This sucks
let item = Trainer.weapons |> Inventory.findItemById hackId let item = Trainer.weapons |> Inventory.findItemById hackId
let hackItem = (Inventory.getHackItem item).Value let hackItem = (Inventory.getHackItem item).Value
@ -206,7 +206,7 @@ let defend (ctx : IDiscordContext) =
let handleDefense (ctx : IDiscordContext) = let handleDefense (ctx : IDiscordContext) =
executePlayerAction ctx (fun player -> async { executePlayerAction ctx (fun player -> async {
let tokens = ctx.GetInteractionId().Split("-") let tokens = ctx.GetInteractionId().Split("-")
let shieldId = int tokens.[1] let shieldId = tokens.[1]
let item = Trainer.weapons |> Inventory.findItemById shieldId let item = Trainer.weapons |> Inventory.findItemById shieldId
let shieldItem = (Inventory.getShieldItem item).Value let shieldItem = (Inventory.getShieldItem item).Value

View File

@ -130,7 +130,7 @@ let getJackpotAmount () =
|> Sql.connect |> Sql.connect
|> Sql.query """ |> Sql.query """
SELECT stock FROM store_item SELECT stock FROM store_item
WHERE store_item.item_id = (SELECT id FROM item WHERE symbol = 'JACKPOT') WHERE store_item.item_id = (SELECT id FROM item WHERE id = 'JACKPOT')
""" """
|> Sql.executeRowAsync (fun read -> (read.int "stock") * 1<GBT>) |> Sql.executeRowAsync (fun read -> (read.int "stock") * 1<GBT>)
|> Async.AwaitTask |> Async.AwaitTask
@ -141,7 +141,7 @@ let incrementJackpot amount =
|> Sql.parameters [ ( "amount" , Sql.int (int amount) ) ] |> Sql.parameters [ ( "amount" , Sql.int (int amount) ) ]
|> Sql.query """ |> Sql.query """
UPDATE store_item SET stock = stock + @amount UPDATE store_item SET stock = stock + @amount
WHERE store_item.item_id = (SELECT id FROM item WHERE symbol = 'JACKPOT') WHERE store_item.item_id = (SELECT id FROM item WHERE id = 'JACKPOT')
""" """
|> Sql.executeNonQueryAsync |> Sql.executeNonQueryAsync
|> Async.AwaitTask |> Async.AwaitTask

View File

@ -52,13 +52,13 @@ let getItemEmbeds owned (items : StoreItem list) =
.WithColor(WeaponClass.getClassEmbedColor item.Item) .WithColor(WeaponClass.getClassEmbedColor item.Item)
.WithTitle($"{item.Item.Name}") .WithTitle($"{item.Item.Name}")
|> ignore |> ignore
match Embeds.getItemIcon item.Item.Id with if String.IsNullOrWhiteSpace(item.Item.IconUrl)
| Some url -> embed.WithThumbnail(url) then embed
| None -> if String.IsNullOrWhiteSpace(item.Item.IconUrl) then embed else embed.WithThumbnail(item.Item.IconUrl)) else embed.WithThumbnail(item.Item.IconUrl))
|> List.map (fun e -> e.Build()) |> List.map (fun e -> e.Build())
|> Seq.ofList |> Seq.ofList
let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : StoreItem list) = let getBuyItemsEmbed storeId (playerInventory : Inventory) (storeInventory : StoreItem list) =
let embeds = getItemEmbeds false storeInventory let embeds = getItemEmbeds false storeInventory
let buttons = let buttons =
storeInventory storeInventory
@ -66,9 +66,9 @@ let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : StoreItem l
let owned = playerInventory |> List.exists (fun i -> i.Id = item.Item.Id) let owned = playerInventory |> List.exists (fun i -> i.Id = item.Item.Id)
let inStock = item.Available && (item.Stock > 0 || item.LimitStock = false) let inStock = item.Available && (item.Stock > 0 || item.LimitStock = false)
match owned , inStock with match owned , inStock with
| false , true -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}", $"Buy {item.Item.Name}") | false , true -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Buy {item.Item.Name}")
| false , false -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}", $"{item.Item.Name} (Out of Stock)", true) | false , false -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"{item.Item.Name} (Out of Stock)", true)
| true , _ -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}", $"Own {item.Item.Name}", true) | true , _ -> DiscordButtonComponent(WeaponClass.getClassButtonColor item.Item, $"Buy-{item.Item.Id}-{storeId}", $"Own {item.Item.Name}", true)
:> DiscordComponent) :> DiscordComponent)
let builder = let builder =
@ -141,16 +141,18 @@ let checkHasItemsInArsenal itemType items player =
then Ok player then Ok player
else Error $"You currently have no {itemType} in your arsenal to sell!" else Error $"You currently have no {itemType} in your arsenal to sell!"
let buy (ctx : IDiscordContext) = let buy storeId (filterBy : ItemType option) (ctx : IDiscordContext) =
executePlayerAction ctx (fun player -> async { executePlayerAction ctx (fun player -> async {
try try
let channelId = ctx.GetChannel().Id let! items = DbService.getStoreItems storeId
let! items = DbService.getStoreItems channelId
if items.Length > 0 then if items.Length > 0 then
let itemStore = getBuyItemsEmbed player.Inventory items let items' =
match filterBy with
| Some itemType -> items |> List.filter (fun item -> item.Item.Type = itemType)
| None -> items
let itemStore = getBuyItemsEmbed storeId player.Inventory items'
do! ctx.FollowUp itemStore |> Async.AwaitTask do! ctx.FollowUp itemStore |> Async.AwaitTask
let! storeSymbol = DbService.getStoreSymbol channelId do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeId
do! Analytics.buyItemCommand (ctx.GetDiscordMember()) storeSymbol
else else
do! Messaging.sendFollowUpMessage ctx "This channel doesn't have anything to sell" do! Messaging.sendFollowUpMessage ctx "This channel doesn't have anything to sell"
with ex -> printfn $"{ex.Message}" with ex -> printfn $"{ex.Message}"
@ -172,7 +174,7 @@ let purchaseItemEmbed (item : Item) =
embed.Title <- $"Purchased {item.Name}" embed.Title <- $"Purchased {item.Name}"
match item.Type with match item.Type with
| ItemType.Jpeg -> | ItemType.Jpeg ->
if item.Symbol.Contains "RAFFLE" then if item.Id.Contains "RAFFLE" then
embed.Description <- $"Congratulations! You are in the draw for the {item.Name}. The winner will be announced shortly" embed.Description <- $"Congratulations! You are in the draw for the {item.Name}. The winner will be announced shortly"
embed.ImageUrl <- item.Description embed.ImageUrl <- item.Description
else else
@ -183,7 +185,8 @@ let purchaseItemEmbed (item : Item) =
// 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 (ctx : IDiscordContext) itemId = let handleBuyItem (ctx : IDiscordContext) itemId =
executePlayerAction ctx (fun player -> async { executePlayerAction ctx (fun player -> async {
let! storeInventory = DbService.getStoreItems (ctx.GetChannel().Id) let storeId = ctx.GetInteractionId().Split("-").[2]
let! storeInventory = DbService.getStoreItems storeId
let storeItem = storeInventory |> List.find (fun si -> si.Item.Id = itemId) let storeItem = storeInventory |> List.find (fun si -> si.Item.Id = itemId)
let item = storeInventory |> List.map (fun i -> i.Item) |> Inventory.findItemById itemId let item = storeInventory |> List.map (fun i -> i.Item) |> Inventory.findItemById itemId
do! player do! player
@ -231,7 +234,8 @@ let consume (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx
match player.Inventory |> Inventory.getFoods with match player.Inventory |> Inventory.getFoods with
| [] -> do! Messaging.sendFollowUpMessage ctx "You do not have any items to consume" | [] -> do! Messaging.sendFollowUpMessage ctx "You do not have any items to consume"
| items -> | items ->
let items' = items |> List.map (fun i -> { Item = i ; Stock = 1 ; LimitStock = false ; Available = true }) // TODO: You have to provide the correct store id here
let items' = items |> List.map (fun i -> { StoreId = i.Id ; Item = i ; Stock = 1 ; LimitStock = false ; Available = true })
let embeds = getItemEmbeds true items' let embeds = getItemEmbeds true items'
let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true) let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true)
do! ctx.FollowUp builder |> Async.AwaitTask do! ctx.FollowUp builder |> Async.AwaitTask
@ -242,7 +246,7 @@ let handleConsume (ctx : IDiscordContext) itemId = PlayerInteractions.executePla
match player.Inventory |> Inventory.getFoods with match player.Inventory |> Inventory.getFoods with
| [] -> do! Messaging.sendFollowUpMessage ctx "You do not have any items to consume" | [] -> do! Messaging.sendFollowUpMessage ctx "You do not have any items to consume"
| items -> | items ->
let items' = items |> List.map (fun i -> { Item = i ; Stock = 1 ; LimitStock = false ; Available = true }) let items' = items |> List.map (fun i -> { StoreId = i.Id ; Item = i ; Stock = 1 ; LimitStock = false ; Available = true })
let embeds = getItemEmbeds true items' let embeds = getItemEmbeds true items'
let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true) let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true)
do! ctx.FollowUp builder |> Async.AwaitTask do! ctx.FollowUp builder |> Async.AwaitTask
@ -252,7 +256,7 @@ let showJpegsEmbed (ctx : IDiscordContext) = PlayerInteractions.executePlayerAct
let jpegs = let jpegs =
player.Inventory player.Inventory
|> Inventory.getItemsByType ItemType.Jpeg |> Inventory.getItemsByType ItemType.Jpeg
|> List.map (fun i -> { Item = i ; Stock = 1 ; LimitStock = false ; Available = true }) |> List.map (fun i -> { StoreId = "BACKALLEY" ; Item = i ; Stock = 1 ; LimitStock = false ; Available = true })
let embeds = getItemEmbeds true jpegs let embeds = getItemEmbeds true jpegs
let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true) let builder = DiscordFollowupMessageBuilder().AddEmbeds(embeds).AsEphemeral(true)
do! ctx.FollowUp builder |> Async.AwaitTask do! ctx.FollowUp builder |> Async.AwaitTask
@ -283,12 +287,15 @@ let showStats (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction c
let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
let ctx = DiscordEventContext event :> IDiscordContext let ctx = DiscordEventContext event :> IDiscordContext
let id = ctx.GetInteractionId() let id = ctx.GetInteractionId()
let itemId = int <| id.Split("-").[1] let itemId = id.Split("-").[1]
let storeId = id.Split("-").[2]
match id with match id with
| id when id.StartsWith("Buy") -> handleBuyItem ctx itemId | id when id.StartsWith("Buy") -> handleBuyItem ctx itemId
| id when id.StartsWith("Sell") -> handleSell ctx itemId | id when id.StartsWith("Sell") -> handleSell ctx itemId
| id when id.StartsWith("Consume") -> handleConsume ctx itemId | id when id.StartsWith("Consume") -> handleConsume ctx itemId
| id when id.StartsWith("ShowJpegInventory") -> buy ctx | id when id.StartsWith("ShowJpegInventory") -> buy storeId None ctx
| id when id.StartsWith("ShowHacks") -> buy storeId (Some ItemType.Hack) ctx
| id when id.StartsWith("ShowShields") -> buy storeId (Some ItemType.Shield) ctx
| _ -> | _ ->
task { task {
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
@ -297,14 +304,14 @@ let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEve
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
} }
let sendInitialEmbed (ctx : IDiscordContext) = let sendBackalleyEmbed (ctx : IDiscordContext) =
async { async {
try try
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelBackAlley) let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelBackAlley)
let builder = DiscordMessageBuilder() let builder = DiscordMessageBuilder()
let embed = DiscordEmbedBuilder() let embed = DiscordEmbedBuilder()
embed.ImageUrl <- "https://s7.gifyu.com/images/ezgif.com-gif-maker-23203b9dca779ba7cf.gif" embed.ImageUrl <- "https://s7.gifyu.com/images/ezgif.com-gif-maker-23203b9dca779ba7cf.gif"
embed.Title <- "Degenz Game" embed.Title <- "Jpeg Alley"
embed.Color <- DiscordColor.Black embed.Color <- DiscordColor.Black
embed.Description <- "Hey, what do you want kid? Did you come alone?" embed.Description <- "Hey, what do you want kid? Did you come alone?"
builder.AddEmbed embed |> ignore builder.AddEmbed embed |> ignore
@ -318,6 +325,28 @@ let sendInitialEmbed (ctx : IDiscordContext) =
printfn $"Error trying to get channel Jpeg Alley\n\n{e.Message}" printfn $"Error trying to get channel Jpeg Alley\n\n{e.Message}"
} |> Async.RunSynchronously } |> Async.RunSynchronously
let sendArmoryEmbed (ctx : IDiscordContext) =
async {
try
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelArmory)
let builder = DiscordMessageBuilder()
let embed = DiscordEmbedBuilder()
embed.ImageUrl <- "https://s10.gifyu.com/images/ezgif.com-gif-maker-1696ae238f96d4dfc1.gif"
embed.Title <- "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", $"Hacks") :> DiscordComponent
let btn2 = DiscordButtonComponent(ButtonStyle.Success, $"ShowShields-0", $"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
type Store() = type Store() =
inherit ApplicationCommandModule () inherit ApplicationCommandModule ()
@ -343,16 +372,16 @@ type Store() =
// do! Messaging.sendSimpleResponse ctx msg // do! Messaging.sendSimpleResponse ctx msg
// } // }
[<SlashCommand("buy-item", "Purchase an item")>] // [<SlashCommand("buy-item", "Purchase an item")>]
member _.BuyItem (ctx : InteractionContext) = buy (DiscordInteractionContext ctx) // member _.BuyItem (ctx : InteractionContext) = buy (DiscordInteractionContext ctx)
[<SlashCommand("buy-hack", "Purchase a hack so you can take money from other Degenz")>] // [<SlashCommand("buy-hack", "Purchase a hack so you can take money from other Degenz")>]
member _.BuyHack (ctx : InteractionContext) = // member _.BuyHack (ctx : InteractionContext) =
enforceChannel (DiscordInteractionContext(ctx)) buy // enforceChannel (DiscordInteractionContext(ctx)) buy
//
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GBT")>] // [<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GBT")>]
member this.BuyShield (ctx : InteractionContext) = // member this.BuyShield (ctx : InteractionContext) =
enforceChannel (DiscordInteractionContext(ctx)) buy // enforceChannel (DiscordInteractionContext(ctx)) buy
[<SlashCommand("sell-hack", "Sell a hack for GoodBoyTokenz")>] [<SlashCommand("sell-hack", "Sell a hack for GoodBoyTokenz")>]
member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" (Inventory.getItemsByType ItemType.Hack)) member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" (Inventory.getItemsByType ItemType.Hack))
@ -360,14 +389,14 @@ type Store() =
[<SlashCommand("sell-shield", "Sell a shield for GoodBoyTokenz")>] [<SlashCommand("sell-shield", "Sell a shield for GoodBoyTokenz")>]
member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType.Shield)) member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType.Shield))
[<SlashCommand("consume", "Consume a food item")>] // [<SlashCommand("consume", "Consume a food item")>]
member this.Consume (ctx : InteractionContext) = consume (DiscordInteractionContext ctx) // member this.Consume (ctx : InteractionContext) = consume (DiscordInteractionContext ctx)
//
[<SlashCommand("jpegs", "Check your inventory")>] [<SlashCommand("jpegs", "Check your inventory")>]
member this.Inventory (ctx : InteractionContext) = member this.Inventory (ctx : InteractionContext) =
showJpegsEmbed (DiscordInteractionContext ctx) showJpegsEmbed (DiscordInteractionContext ctx)
[<SlashCommand("stats", "Check your stats")>] // [<SlashCommand("stats", "Check your stats")>]
member this.Stats (ctx : InteractionContext) = // member this.Stats (ctx : InteractionContext) =
showStats (DiscordInteractionContext ctx) // showStats (DiscordInteractionContext ctx)

View File

@ -10,8 +10,8 @@ open Degenz.Messaging
let TrainerAchievement = "LEARN_TO_HACKER_BATTLE_QUEST_COMPLETED" let TrainerAchievement = "LEARN_TO_HACKER_BATTLE_QUEST_COMPLETED"
let Sensei = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" } let Sensei = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
let weapons = DbService.getWeapons () |> Async.RunSynchronously let weapons = DbService.getWeapons () |> Async.RunSynchronously
let hackItem = weapons |> Inventory.findItemById (int ItemId.Virus) let hackItem = weapons |> Inventory.findItemById (string ItemId.VIRUS)
let shieldItem = weapons |> Inventory.findItemById (int ItemId.Firewall) let shieldItem = weapons |> Inventory.findItemById (string ItemId.FIREWALL)
let defaultHack = (Inventory.getHackItem hackItem).Value let defaultHack = (Inventory.getHackItem hackItem).Value
let defaultShield = (Inventory.getShieldItem shieldItem ).Value let defaultShield = (Inventory.getShieldItem shieldItem ).Value
let CurrencyGift = 250<GBT> let CurrencyGift = 250<GBT>
@ -30,13 +30,13 @@ let HackEvent () = {
let ShieldEvents () = [ let ShieldEvents () = [
{ Timestamp = System.DateTime.UtcNow { Timestamp = System.DateTime.UtcNow
Cooldown = BeginnerProtectionHours * 60<mins> Cooldown = BeginnerProtectionHours * 60<mins>
Type = Shielding (int ItemId.Firewall) } Type = Shielding (string ItemId.FIREWALL) }
{ Timestamp = System.DateTime.UtcNow { Timestamp = System.DateTime.UtcNow
Cooldown = BeginnerProtectionHours * 60<mins> Cooldown = BeginnerProtectionHours * 60<mins>
Type = Shielding (int ItemId.Encryption) } Type = Shielding (string ItemId.ENCRYPTION) }
{ Timestamp = System.DateTime.UtcNow { Timestamp = System.DateTime.UtcNow
Cooldown = BeginnerProtectionHours * 60<mins> Cooldown = BeginnerProtectionHours * 60<mins>
Type = Shielding (int ItemId.Cypher) } Type = Shielding (string ItemId.CYPHER) }
] ]
let sendInitialEmbed (ctx : IDiscordContext) = let sendInitialEmbed (ctx : IDiscordContext) =

View File

@ -184,7 +184,7 @@ let getWhitelistItem () =
|> Sql.query """ |> Sql.query """
SELECT stock, buy_price FROM store_item SELECT stock, buy_price FROM store_item
JOIN item i on store_item.item_id = i.id JOIN item i on store_item.item_id = i.id
WHERE i.symbol = 'WHITELIST' WHERE i.id = 'WHITELIST'
""" """
|> Sql.executeRowAsync (fun read -> {| Stock = read.int "stock" ; Price = (read.int "buy_price") * 1<GBT> |}) |> Sql.executeRowAsync (fun read -> {| Stock = read.int "stock" ; Price = (read.int "buy_price") * 1<GBT> |})
|> Async.AwaitTask |> Async.AwaitTask
@ -195,7 +195,7 @@ let updateWhitelistStock () = async {
|> Sql.connect |> Sql.connect
|> Sql.query """ |> Sql.query """
UPDATE store_item SET stock = GREATEST(stock - 1, 0) UPDATE store_item SET stock = GREATEST(stock - 1, 0)
WHERE store_item.item_id = (SELECT id FROM item WHERE symbol = 'WHITELIST') WHERE store_item.item_id = (SELECT id FROM item WHERE id = 'WHITELIST')
""" """
|> Sql.executeNonQueryAsync |> Sql.executeNonQueryAsync
|> Async.AwaitTask |> Async.AwaitTask
@ -211,7 +211,7 @@ let setWhitelistStock amount = async {
|> Sql.parameters [ ( "amount" , Sql.int amount ) ] |> Sql.parameters [ ( "amount" , Sql.int amount ) ]
|> Sql.query """ |> Sql.query """
UPDATE store_item SET stock = @amount UPDATE store_item SET stock = @amount
WHERE store_item.item_id = (SELECT id FROM item WHERE symbol = 'WHITELIST') WHERE store_item.item_id = (SELECT id FROM item WHERE id = 'WHITELIST')
""" """
|> Sql.executeNonQueryAsync |> Sql.executeNonQueryAsync
|> Async.AwaitTask |> Async.AwaitTask