diff --git a/Bot/DbService.fs b/Bot/DbService.fs index 8997795..322f98d 100644 --- a/Bot/DbService.fs +++ b/Bot/DbService.fs @@ -122,6 +122,25 @@ let getStoreItems (storeId : string) = }) |> Async.AwaitTask +let getAllActiveStoreItems () = + connStr + |> Sql.connect + |> Sql.query """ + 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 + FROM store_item + JOIN item i on store_item.item_id = i.id + WHERE store_item.unlisted = false + """ + |> Sql.executeAsync (fun reader -> { + StoreId = reader.string "store_id" + Stock = reader.int "stock" + LimitStock = reader.bool "limit_stock" + Available = reader.bool "available" + StoreItem.Item = readItem reader + }) + |> Async.AwaitTask + let getStoreItemBySymbol (itemSymbol : string) = connStr |> Sql.connect diff --git a/Bot/Embeds.fs b/Bot/Embeds.fs index 7e8011b..d37fe70 100644 --- a/Bot/Embeds.fs +++ b/Bot/Embeds.fs @@ -1,6 +1,7 @@ module Degenz.Embeds open System +open DSharpPlus open Degenz open Degenz.Messaging open DSharpPlus.Entities @@ -10,6 +11,7 @@ let shieldGif = "https://s10.gifyu.com/images/Defense-Degenz-V2-min.gif" let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) (items : Inventory) ignoreCooldown = items + |> List.sortBy (fun item -> item.Id) |> List.map (fun item -> let action = player.Events @@ -42,7 +44,13 @@ let pickDefense actionId player isTrainer = for shield in Inventory.getShields player.Inventory do let hours = TimeSpan.FromMinutes(int shield.Cooldown).TotalHours |> int let against = WeaponClass.getGoodAgainst shield.Class |> snd - embed.AddField(shield.Name, $"Active {hours} hours\nDefeats {against}", true) |> ignore + let emoji = + match shield.Id with + | "FIREWALL" -> "<:firewall_shield:971620988649340989>" + | "ENCRYPTION" -> "<:encryption_shield:971620979912605727>" + | "CYPHER" -> "<:cypher_shield:971620965576503326>" + | _ -> "" + embed.AddField($"{emoji} {shield.Name}", $"Active {hours} hours\nDefeats {against}", true) |> ignore DiscordFollowupMessageBuilder() .AddComponents(buttons) @@ -58,19 +66,19 @@ let pickHack actionId attacker defender bonus isTrainer = let ( outcomeMsg , bonusMsg ) = if attacker.Stats.Strength.Amount > defender.Stats.Strength.Amount then - "\nYou're stronger so you'll steal more!!!\n" , $"\n**__Potential Bonus:__**\n{bonus} 💰$GBT" + "\nYou're **STRONGER** so you'll **HACK MORE!!!** `💰$GBT`\n" , $"\n**__Potential Bonus:__**\n`{bonus} 💰$GBT`" else - "\nYou're not stronger than them, you need to eat more!" , "" + "\nYou're **NOT STRONGER** than them, you need to **EAT MORE!**" , "" let stealMsg = if not isTrainer then $""" - {defender.Name} has **{defender.Bank} $GBT** we can take from them. + **{defender.Name}** has `{defender.Bank} 💰$GBT` we can take from them. **__Your Strength:__** - 💪 {attacker.Stats.Strength.Amount} + `💪 {attacker.Stats.Strength.Amount}` **__Their Strength:__** - 💪 {defender.Stats.Strength.Amount} + `💪 {defender.Stats.Strength.Amount}` {outcomeMsg}{bonusMsg}""" else "" let embed = @@ -79,9 +87,20 @@ let pickHack actionId attacker defender bonus isTrainer = .WithDescription($"{stealMsg}\n\nPick the hack you want to use.") if not isTrainer then - for hack in Inventory.getHacks attacker.Inventory do + let hacks = Inventory.getHacks attacker.Inventory |> List.sortBy (fun h -> h.Id) + for hack in hacks do let amount = if hack.Power > int defender.Bank then int defender.Bank else hack.Power - embed.AddField(hack.Name, $"Cooldown {hack.Cooldown} mins\nExtract {amount} $GBT", true) |> ignore + let emoji = + match hack.Id with + | "REMOTE" -> "<:remote_access:971621009981571132>" + | "VIRUS" -> "<:virus_hack:971636840580927510>" + | "WORM" -> "<:worm_hack:971636842640310312>" + | _ -> "" + let fieldMsg = $""" + Hack Base: `{hack.Power} 💰$GBT` + Bonus: `{bonus} 💰$GBT` + **Hack Total:** `{amount + bonus} 💰$GBT`""" + embed.AddField($"{emoji} __{hack.Name}__", fieldMsg, true) |> ignore DiscordFollowupMessageBuilder() .AddComponents(buttons) @@ -121,7 +140,8 @@ let responseCreatedShield (shield : ShieldItem) = let eventSuccessfulHack (ctx : IDiscordContext) target prize = DiscordMessageBuilder() - .WithContent($"{ctx.GetDiscordMember().Username} successfully hacked <@{target.DiscordId}> and took {prize} GoodBoyTokenz") + .WithAllowedMention(UserMention(target.DiscordId)) + .WithContent($"**{ctx.GetDiscordMember().Username}** successfully hacked **{target.Name}** and took {prize} $GBT! - <@!{target.DiscordId}>") let getArsenalEmbed (player : PlayerData) = DiscordFollowupMessageBuilder() diff --git a/Bot/Games/HackerBattle.fs b/Bot/Games/HackerBattle.fs index c693712..0b3ccfe 100644 --- a/Bot/Games/HackerBattle.fs +++ b/Bot/Games/HackerBattle.fs @@ -66,7 +66,7 @@ let checkPlayerHasShieldSlotsAvailable player = let checkTargetHasFunds target player = match target.Bank <= 0 with - | true -> Error $"Looks like the poor bastard has no $GBT... pick a different victim." + | true -> Error $"Looks like the poor bastard has no 💰$GBT... pick a different victim." | false -> Ok player let strengthBonus attacker defender = @@ -129,13 +129,13 @@ let successfulHack (ctx : IDiscordContext) attacker defender (hack : HackItem) = let failedHack (ctx : IDiscordContext) attacker defender (hack : HackItem) = async { let lostAmount = if hack.Power < int attacker.Bank then hack.Power else int attacker.Bank - let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {lostAmount} $GBT!" + let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {lostAmount} 💰$GBT!" do! sendFollowUpMessage ctx msg do! updateCombatants false attacker defender hack (-lostAmount * 1) let builder = DiscordMessageBuilder() - builder.WithContent($"Hacking attempt failed! <@{defender.DiscordId}> defended hack from {ctx.GetDiscordMember().Username} and took {lostAmount} $GBT from them! ") |> ignore + builder.WithContent($"Hacking attempt failed! **{defender.Name}** defended hack from **{ctx.GetDiscordMember().Username}** and took {lostAmount} 💰$GBT from them! <@!{defender.DiscordId}>") |> ignore let channel = (ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)) do! channel.SendMessageAsync(builder) |> Async.AwaitTask @@ -223,7 +223,7 @@ let handleDefense (ctx : IDiscordContext) = } do! DbService.addPlayerEvent p.DiscordId defense |> Async.Ignore let builder = DiscordMessageBuilder() - builder.WithContent($"{ctx.GetDiscordMember().Username} has protected their system!") |> ignore + builder.WithContent($"**{ctx.GetDiscordMember().Username}** has protected their system!") |> ignore let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle) do! channel.SendMessageAsync(builder) |> Async.AwaitTask diff --git a/Bot/Games/Store.fs b/Bot/Games/Store.fs index 79bba8b..3b5e137 100644 --- a/Bot/Games/Store.fs +++ b/Bot/Games/Store.fs @@ -105,7 +105,7 @@ let getItemEmbeds owned (items : StoreItem list) = | Stackable max -> if owned then embed.AddField($"Owned", $"{count}", true) - else embed.AddField($"Max Allowed", $"{max}", true) + else embed.AddField($"Max Allowed", (if max > 1000 then "Unlimited" else string max), true) |> ignore // let totalOwned = getTotalOwnedOfItem item.Item (items |> List.map (fun i -> i.Item)) |> Option.defaultValue 1 // titleText <- $"{totalOwned}x " + titleText @@ -208,10 +208,11 @@ let getSellEmbed (items : Inventory) = .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.map (fun i -> { StoreId = "" ; Item = i ; Stock = 1 ; LimitStock = false ; Available = true ; RequiresInvites = None ; RequiresRole = None }) + |> 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 -> @@ -395,6 +396,9 @@ let handleStoreEvents _ (event : ComponentInteractionCreateEventArgs) = 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 { @@ -447,4 +451,4 @@ type JpegStore() = // [] // member this.Inventory (ctx : InteractionContext) = -// showJpegsEmbed (DiscordInteractionContext ctx) \ No newline at end of file +// showJpegsEmbed (DiscordInteractionContext ctx) diff --git a/Bot/InviteTracker.fs b/Bot/InviteTracker.fs index 394142d..a37f31f 100644 --- a/Bot/InviteTracker.fs +++ b/Bot/InviteTracker.fs @@ -246,7 +246,7 @@ let getInvitedUsersForId (user : DiscordUser) (ctx : IDiscordContext) = let mutable count = 0 for user in users do count <- count + 1 - sb.AppendLine($"{count}.) <@{user}>") |> ignore + sb.AppendLine($"{count}.) <@!{user}>") |> ignore let msg = let str = if users.Length > 0 then @@ -300,7 +300,7 @@ let acceptInvite (guild : DiscordGuild) discordId memberName = do! match GuildEnvironment.botClientRecruit with | Some recruitBot -> async { let builder = DiscordMessageBuilder() - builder.WithContent($"{memberName} was recruited and is now a Degen. <@{player.DiscordId}> just earned {InviteRewardAmount} 💰$GBT for their efforts!") |> ignore + builder.WithContent($"{memberName} was recruited and is now a Degen. **{player.Name}** just earned `{InviteRewardAmount} 💰$GBT` for their efforts! - <@!{player.DiscordId}>") |> ignore let channel = guild.GetChannel(GuildEnvironment.channelEventsHackerBattle) do! recruitBot.SendMessageAsync(channel, builder) |> Async.AwaitTask @@ -355,9 +355,9 @@ let showWalletStatus (ctx : IDiscordContext) = try match! getWalletAddress player.DiscordId with | Some address -> do! Messaging.sendFollowUpMessage ctx $""" -🚀 __Mint Date:__ 31st May, 18:00 UTC +🚀 __Mint Date:__ Mid June ✅ __Status:__ We have successfully received your wallet address: {address}""" - | None -> do! Messaging.sendFollowUpMessage ctx "You have no submitted your wallet yet. Type `/submit`, paste your **Solana Wallet Address**, then press enter" + | None -> do! Messaging.sendFollowUpMessage ctx "You haven't submitted a wallet yet. Type `/submit`, paste your **Solana Wallet Address**, then press enter" with ex -> printfn $"{ex.Message}" do! Messaging.sendFollowUpMessage ctx "Something went wrong retrieving your wallet address" @@ -452,7 +452,7 @@ let handleMemberUpdated (client : DiscordClient) (event : GuildMemberUpdateEvent let handleMessageCreated _ (event : MessageCreateEventArgs) = task { - let bot = GuildEnvironment.botClientRecruit.Value + let bot = GuildEnvironment.botClientRecruit.Value if event.Channel.Id = GuildEnvironment.channelSubmitWallet && event.Author.Id <> bot.CurrentUser.Id then do! Async.Sleep 100 do! event.Message.DeleteAsync() @@ -492,13 +492,13 @@ let submitAddress (address : string) (ctx : IDiscordContext) = do! Messaging.sendFollowUpMessage ctx $""" -🚀 __Mint Date:__ 31st May 18:00 UTC +🚀 __Mint Date:__ Mid June ✅ {msg} {address} Keep an eye on <#{GuildEnvironment.channelAnnouncements}> for updates.""" let builder = DiscordMessageBuilder() - builder.WithContent($"{ctx.GetDiscordMember().Username} submitted their wallet address in <#{GuildEnvironment.channelSubmitWallet}> and confirmed whitelist") |> ignore + builder.WithContent($"**{ctx.GetDiscordMember().Username}** submitted their wallet address in <#{GuildEnvironment.channelSubmitWallet}> and confirmed whitelist") |> ignore let channel = (ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)) do! channel.SendMessageAsync(builder) |> Async.AwaitTask @@ -508,7 +508,6 @@ Keep an eye on <#{GuildEnvironment.channelAnnouncements}> for updates.""" do! Messaging.sendFollowUpMessage ctx "⚠️ That's not a valid Solana address, please try again" do! Analytics.invalidWalletSubmit (ctx.GetDiscordMember()) with ex -> - printfn $"{ex.Message}" do! Messaging.sendFollowUpMessage ctx "⚠️ That's not a valid Solana address, please try again" do! Analytics.invalidWalletSubmit (ctx.GetDiscordMember()) }) diff --git a/Bot/Scripts/GetWhitelisted.fsx b/Bot/Scripts/GetWhitelisted.fsx index fb947cb..0014d55 100644 --- a/Bot/Scripts/GetWhitelisted.fsx +++ b/Bot/Scripts/GetWhitelisted.fsx @@ -3,6 +3,7 @@ open Npgsql.FSharp open DSharpPlus open DSharpPlus.Entities +open Solnet.Programs open dotenv.net let prodEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.prod.env" ]))