diff --git a/Bot/Bot.fsproj b/Bot/Bot.fsproj
index 16fe536..81c8a2a 100644
--- a/Bot/Bot.fsproj
+++ b/Bot/Bot.fsproj
@@ -4,14 +4,16 @@
Exe
net6.0
Linux
- PlayerRegistration
+ Degenz
PreserveNewest
+
+
diff --git a/Bot/Embeds.fs b/Bot/Embeds.fs
new file mode 100644
index 0000000..b360615
--- /dev/null
+++ b/Bot/Embeds.fs
@@ -0,0 +1,85 @@
+module Degenz.Embeds
+
+open DSharpPlus.EventArgs
+open Degenz.Shared
+open DSharpPlus.Entities
+open AsciiTableFormatter
+
+let constructEmbed message =
+ let builder = DiscordEmbedBuilder()
+ builder.Color <- Optional(DiscordColor.PhthaloGreen)
+ builder.Description <- message
+ let author = DiscordEmbedBuilder.EmbedAuthor()
+ author.Name <- "Degenz Hacker Game"
+ author.Url <- "https://twitter.com/degenzgame"
+ author.IconUrl <- "https://pbs.twimg.com/profile_images/1473192843359309825/cqjm0VQ4_400x400.jpg"
+ builder.Author <- author
+ builder.Build()
+
+let pickDefense actionId player =
+ let buttons =
+ constructButtons actionId (string player.DiscordId) player.Shields
+ |> Seq.cast
+
+ let embed =
+ DiscordEmbedBuilder()
+ .WithColor(DiscordColor.PhthaloGreen)
+ .WithDescription("Pick a defense to mount for 10 hours")
+ .WithImageUrl("https://s10.gifyu.com/images/Defense-Degenz-V2.gif")
+
+ DiscordInteractionResponseBuilder()
+ .AddComponents(buttons)
+ .AddEmbed(embed)
+ .AsEphemeral true
+
+let pickHack actionId attacker defender =
+ let buttons =
+ constructButtons actionId $"{defender.DiscordId}-{defender.Name}" attacker.Weapons
+ |> Seq.cast
+
+ let embed =
+ DiscordEmbedBuilder()
+ .WithColor(DiscordColor.PhthaloGreen)
+ .WithDescription("Pick the hack that you want to use")
+ .WithImageUrl("https://s10.gifyu.com/images/Hacker-Degenz-V2.gif")
+
+ DiscordInteractionResponseBuilder()
+ .AddComponents(buttons)
+ .AddEmbed(embed.Build())
+ .AsEphemeral true
+
+let eventSuccessfulHack (event : ComponentInteractionCreateEventArgs) targetId prize =
+ DiscordMessageBuilder()
+ .WithContent($"{event.User.Username} successfully hacked <@{targetId}> for a total of {prize} GoodBoyTokenz")
+
+[]
+type Table = {
+ Name : string
+ Cost : string
+ Class : string
+}
+
+let storeListing store =
+ let embeds =
+ store
+ |> Array.map (fun ( itemType , items ) ->
+ items
+ |> Array.map (fun (item : Item) ->
+ let itemClass =
+ if itemType = ItemType.Hack
+ then weaponInventory
+ |> Array.find (fun w -> item.Name = string w)
+ |> int
+ |> getClass
+ else shieldInventory
+ |> Array.find (fun w -> item.Name = string w)
+ |> int
+ |> getClass
+ { Name = item.Name ; Cost = string item.Cost ; Class = string itemClass })
+ |> Formatter.Format
+ |> sprintf "**%A**\n``` %s ```" itemType
+ |> constructEmbed)
+
+ DiscordInteractionResponseBuilder()
+ .AddEmbeds(embeds)
+ .AsEphemeral(true)
diff --git a/Bot/GameConfig.fs b/Bot/GameConfig.fs
new file mode 100644
index 0000000..a4d0894
--- /dev/null
+++ b/Bot/GameConfig.fs
@@ -0,0 +1 @@
+module Degenz.GameConfig
diff --git a/Bot/HackerBattle.fs b/Bot/HackerBattle.fs
index a061759..3d017c4 100644
--- a/Bot/HackerBattle.fs
+++ b/Bot/HackerBattle.fs
@@ -11,7 +11,6 @@ open Degenz.Shared
let attack (ctx : InteractionContext) (target : DiscordUser) =
async {
- // TODO: We need to check if the player has any active embed hacks going, if not they can cheat
let! attacker = DbService.tryFindPlayer ctx.Member.Id
let! defender = DbService.tryFindPlayer target.Id
match attacker , defender with
@@ -21,23 +20,9 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
|> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
do! DbService.updatePlayer <| { attacker with Attacks = updatedAttacks }
if updatedAttacks.Length < 2 then
- let embed = DiscordEmbedBuilder()
- embed.Color <- Optional(DiscordColor.PhthaloGreen)
- embed.Description <- "Pick the hack that you want to use"
- embed.ImageUrl <- "https://s10.gifyu.com/images/Hacker-Degenz-V2.gif"
+ let embed = Embeds.pickHack "Attack" attacker defender
- let builder = DiscordInteractionResponseBuilder()
- builder.AddEmbed (embed.Build()) |> ignore
-
- let defenderInfo = $"{defender.DiscordId}-{target.Username}"
- constructButtons "Attack" defenderInfo attacker.Weapons
- |> Seq.cast
- |> builder.AddComponents
- |> ignore
-
- builder.AsEphemeral true |> ignore
-
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask
else
@@ -64,17 +49,9 @@ let defend (ctx : InteractionContext) =
let updatedDefenses = removeExpiredActions (TimeSpan.FromHours(24)) (fun (pro : Defense) -> pro.Timestamp) player.Defenses
do! DbService.updatePlayer <| { player with Defenses = updatedDefenses }
if updatedDefenses.Length < 3 then
- let builder = DiscordInteractionResponseBuilder()
- builder.AddEmbed (constructEmbed "Pick a defense to mount for 24 hours") |> ignore
+ let embed = Embeds.pickDefense "Defend" player
- constructButtons "Defend" (string player.DiscordId) player.Shields
- |> Seq.cast
- |> builder.AddComponents
- |> ignore
-
- builder.AsEphemeral true |> ignore
-
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask
else
let builder = DiscordInteractionResponseBuilder()
@@ -115,9 +92,11 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
// let prize = 1.337f // LEET
let prize = 13
let attack = { HackType = enum(int weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } }
- // TODO: Make a single update instead of two
- do! DbService.updatePlayer <| updatePlayer prize attack player
- do! DbService.updatePlayer { target with Bank = Math.Max(target.Bank - prize, 0)}
+
+ let! _ =
+ [ DbService.updatePlayer <| updatePlayer prize attack player
+ DbService.updatePlayer { target with Bank = Math.Max(target.Bank - prize, 0)} ]
+ |> Async.Parallel
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
@@ -125,9 +104,8 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask
- let builder = DiscordMessageBuilder()
- builder.WithContent($"{event.User.Username} successfully hacked <@{targetId}> for a total of {prize} GoodBoyTokenz") |> ignore
- let channel = (event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle))
+ let builder = Embeds.eventSuccessfulHack event targetId prize
+ let channel = event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle)
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
diff --git a/Bot/Store.fs b/Bot/Store.fs
index 944c7a6..f80c099 100644
--- a/Bot/Store.fs
+++ b/Bot/Store.fs
@@ -6,9 +6,9 @@ open DSharpPlus
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz
+open Degenz.Embeds
open Degenz.Shared
open Newtonsoft.Json
-open AsciiTableFormatter
let store =
try
@@ -17,52 +17,9 @@ let store =
|> Array.groupBy (fun (i : Item) -> i.ItemType)
with _ -> [||]
-//[]
-//type Table() =
-// member val Name = "" with get , set
-// member val Cost = "" with get , set
-// member val Class = "" with get , set
-//
-
-[]
-type Table = {
- Name : string
- Cost : string
- Class : string
-}
-
-
-let storeListing =
- store
- |> Array.map (fun ( itemType , items ) ->
- let itemsData =
- items
- |> Array.map (fun (item : Item) ->
- let itemClass =
- if itemType = ItemType.Hack
- then weaponInventory
- |> Array.find (fun w -> item.Name = string w)
- |> int
- |> getClass
- else shieldInventory
- |> Array.find (fun w -> item.Name = string w)
- |> int
- |> getClass
- { Name = item.Name ; Cost = string item.Cost ; Class = string itemClass })
-
- let table = Formatter.Format(ResizeArray(itemsData))
-
- (constructEmbed $"**{itemType}s**\n```{table}```"))
-
let viewStore (ctx : InteractionContext) =
async {
- let builder = DiscordInteractionResponseBuilder()
-
- builder.AddEmbeds(storeListing)
- .AsEphemeral(true)
- |> ignore
-
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing store)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
diff --git a/Bot/Trainer.fs b/Bot/Trainer.fs
index ebe23aa..ce2ff83 100644
--- a/Bot/Trainer.fs
+++ b/Bot/Trainer.fs
@@ -7,47 +7,6 @@ open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz.Shared
-module Message =
- let sendFollowUpMessage (event : ComponentInteractionCreateEventArgs) msg =
- async {
- let builder = DiscordFollowupMessageBuilder()
- builder.IsEphemeral <- true
- builder.Content <- msg
- do! event.Interaction.CreateFollowupMessageAsync(builder)
- |> Async.AwaitTask
- |> Async.Ignore
- }
-
- let sendFollowUpMessageWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg =
- async {
- let builder = DiscordFollowupMessageBuilder()
- let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent
- builder.AddComponents [| button |] |> ignore
- builder.IsEphemeral <- true
- builder.Content <- msg
- do! event.Interaction.CreateFollowupMessageAsync(builder)
- |> Async.AwaitTask
- |> Async.Ignore
- }
-
- let sendInteractionEvent (event : ComponentInteractionCreateEventArgs) msg =
- async {
- let builder = DiscordInteractionResponseBuilder()
- builder.IsEphemeral <- true
- builder.Content <- msg
- do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
- }
-
- let sendInteractionEventWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg =
- async {
- let builder = DiscordInteractionResponseBuilder()
- let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent
- builder.AddComponents [| button |] |> ignore
- builder.IsEphemeral <- true
- builder.Content <- msg
- do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
- }
-
let sendInitialEmbed (client : DiscordClient) =
async {
let! channel = client.GetChannelAsync(GuildEnvironment.channelTraining) |> Async.AwaitTask
@@ -92,17 +51,9 @@ let defend (ctx : InteractionContext) =
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with
| Some player ->
- let builder = DiscordInteractionResponseBuilder()
- builder.AddEmbed (constructEmbed "Pick a defense to mount for 8 hours") |> ignore
+ let embed = Embeds.pickDefense "Trainer-3" player
- constructButtons "Trainer-3" (string player.DiscordId) player.Shields
- |> Seq.cast
- |> builder.AddComponents
- |> ignore
-
- builder.AsEphemeral true |> ignore
-
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask
| None ->
let builder = DiscordInteractionResponseBuilder()
@@ -158,17 +109,9 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match isRightTarget , playerResult with
| true , Some player ->
- let builder = DiscordInteractionResponseBuilder()
- builder.AddEmbed (constructEmbed "Pick an attack to use on your target") |> ignore
+ let embed = Embeds.pickHack "Trainer-5" player player
- constructButtons "Trainer-5" (string player.DiscordId) player.Weapons
- |> Seq.cast
- |> builder.AddComponents
- |> ignore
-
- builder.AsEphemeral true |> ignore
-
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask
| false , _ ->
let builder = DiscordInteractionResponseBuilder()
diff --git a/Shared/Shared.fs b/Shared/Shared.fs
index 4413a44..5861f51 100644
--- a/Shared/Shared.fs
+++ b/Shared/Shared.fs
@@ -3,6 +3,7 @@ module Degenz.Shared
open System
open DSharpPlus
open DSharpPlus.Entities
+open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
type ItemType =
@@ -105,17 +106,6 @@ let constructButtons (actionType: string) (playerInfo: string) (weapons: 'a arra
let removeExpiredActions timespan (timestamp: 'a -> DateTime) actions =
actions |> Array.filter (fun act -> DateTime.UtcNow - (timestamp act) < timespan)
-let constructEmbed message =
- let builder = DiscordEmbedBuilder()
- builder.Color <- Optional(DiscordColor.PhthaloGreen)
- builder.Description <- message
- let author = DiscordEmbedBuilder.EmbedAuthor()
- author.Name <- "Degenz Hacker Game"
- author.Url <- "https://twitter.com/degenzgame"
- author.IconUrl <- "https://pbs.twimg.com/profile_images/1473192843359309825/cqjm0VQ4_400x400.jpg"
- builder.Author <- author
- builder.Build()
-
let calculateDamage (hack: int) (shield: int) =
let hackClass = getClass hack
let protectionClass = getClass shield
@@ -123,3 +113,45 @@ let calculateDamage (hack: int) (shield: int) =
match hackClass, protectionClass with
| h, p when h = p -> Weak
| _ -> Strong
+
+module Message =
+ let sendFollowUpMessage (event : ComponentInteractionCreateEventArgs) msg =
+ async {
+ let builder = DiscordFollowupMessageBuilder()
+ builder.IsEphemeral <- true
+ builder.Content <- msg
+ do! event.Interaction.CreateFollowupMessageAsync(builder)
+ |> Async.AwaitTask
+ |> Async.Ignore
+ }
+
+ let sendFollowUpMessageWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg =
+ async {
+ let builder = DiscordFollowupMessageBuilder()
+ let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent
+ builder.AddComponents [| button |] |> ignore
+ builder.IsEphemeral <- true
+ builder.Content <- msg
+ do! event.Interaction.CreateFollowupMessageAsync(builder)
+ |> Async.AwaitTask
+ |> Async.Ignore
+ }
+
+ let sendInteractionEvent (event : ComponentInteractionCreateEventArgs) msg =
+ async {
+ let builder = DiscordInteractionResponseBuilder()
+ builder.IsEphemeral <- true
+ builder.Content <- msg
+ do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
+ }
+
+ let sendInteractionEventWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg =
+ async {
+ let builder = DiscordInteractionResponseBuilder()
+ let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent
+ builder.AddComponents [| button |] |> ignore
+ builder.IsEphemeral <- true
+ builder.Content <- msg
+ do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
+ }
+