Getting defense command to work. Fixes and improvements
This commit is contained in:
		
							parent
							
								
									97bf07e7ec
								
							
						
					
					
						commit
						2f3a9fd1f9
					
				
							
								
								
									
										97
									
								
								Program.fs
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								Program.fs
									
									
									
									
									
								
							| @ -1,5 +1,4 @@ | |||||||
| open System | open System | ||||||
| open System.IO |  | ||||||
| open System.Threading.Tasks | open System.Threading.Tasks | ||||||
| open DSharpPlus | open DSharpPlus | ||||||
| open DSharpPlus.Entities | open DSharpPlus.Entities | ||||||
| @ -23,13 +22,19 @@ type Protection = | |||||||
|     | Hardening = 4 |     | Hardening = 4 | ||||||
|     | Sanitation = 5 |     | Sanitation = 5 | ||||||
| 
 | 
 | ||||||
|  | type DiscordPlayer = { | ||||||
|  |     Id : uint64 | ||||||
|  |     Name : string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type Attack = { | type Attack = { | ||||||
|     HackType : Hack |     HackType : Hack | ||||||
|  |     Target : DiscordPlayer | ||||||
|     Timestamp : DateTime |     Timestamp : DateTime | ||||||
| } | } | ||||||
|      |      | ||||||
| type Defense = { | type Defense = { | ||||||
|     DefenseType : Hack |     DefenseType : Protection | ||||||
|     Timestamp : DateTime |     Timestamp : DateTime | ||||||
| } | } | ||||||
|      |      | ||||||
| @ -62,13 +67,12 @@ let newPlayer (membr : uint64) = | |||||||
|       Bank = 0L |       Bank = 0L | ||||||
|       Defenses = [] } |       Defenses = [] } | ||||||
| 
 | 
 | ||||||
| let constructButtons (actionType : string) (playerId : uint64) (weapons : 'a list) = | let constructButtons (actionType : string) (playerInfo : string) (weapons : 'a list) = | ||||||
|     weapons |     weapons | ||||||
|     |> Seq.map (fun hack -> |     |> Seq.map (fun hack -> | ||||||
|         // TODO:L Button ID should be a GUID and we should keep an in-memory store of the buttons we're waiting for |  | ||||||
|         DiscordButtonComponent( |         DiscordButtonComponent( | ||||||
|                 ButtonStyle.Primary, |                 ButtonStyle.Primary, | ||||||
|                 $"{actionType}-{hack}-{playerId}", |                 $"{actionType}-{hack}-{playerInfo}", | ||||||
|                 $"{hack}")) |                 $"{hack}")) | ||||||
|              |              | ||||||
| let notRegisteredYetMessage (ctx : InteractionContext) = | let notRegisteredYetMessage (ctx : InteractionContext) = | ||||||
| @ -91,6 +95,17 @@ let removeExpiredActions timespan (timestamp : 'a -> DateTime) actions = | |||||||
|             then true |             then true | ||||||
|             else false) |             else false) | ||||||
| 
 | 
 | ||||||
|  | let constructEmbed message = | ||||||
|  |     let builder = DiscordEmbedBuilder() | ||||||
|  |     builder.Color <- Optional(DiscordColor.PhthaloGreen) | ||||||
|  |     builder.Description <- message | ||||||
|  |     let author = DiscordEmbedBuilder.EmbedAuthor() | ||||||
|  |     author.Name <- "Joebot Pro" | ||||||
|  |     author.Url <- "https://ferano.io" | ||||||
|  |     author.IconUrl <- "https://i.kym-cdn.com/entries/icons/original/000/028/861/cover3.jpg" | ||||||
|  |     builder.Author <- author | ||||||
|  |     builder.Build() | ||||||
|  | 
 | ||||||
| type JoeBot() = | type JoeBot() = | ||||||
|     inherit ApplicationCommandModule () |     inherit ApplicationCommandModule () | ||||||
|      |      | ||||||
| @ -132,18 +147,23 @@ type JoeBot() = | |||||||
|         :> Task |         :> Task | ||||||
|      |      | ||||||
|     [<SlashCommand("hack", "Send a hack attack to another player")>] |     [<SlashCommand("hack", "Send a hack attack to another player")>] | ||||||
|     member this.Attack (ctx : InteractionContext, [<Option("player", "The player you want to hack")>] player : DiscordUser) = |     member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) = | ||||||
|  |         // TODO: We need to check if the player has any active hacks going, if not they can cheat | ||||||
|         players |         players | ||||||
|         |> List.tryFind (fun p -> p.DiscordId = ctx.Member.Id) |         |> List.tryFind (fun p -> p.DiscordId = ctx.Member.Id) | ||||||
|         |> function |         |> function | ||||||
|            | Some player -> |            | Some player -> | ||||||
|                 let updatedAttacks = removeExpiredActions (TimeSpan.FromMinutes(5)) (fun (atk : Attack) -> atk.Timestamp) player.Attacks |                 let updatedAttacks = removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp) player.Attacks | ||||||
|                 if updatedAttacks.Length <= 3 then |                 players <- | ||||||
|  |                     players | ||||||
|  |                     |> List.map (fun p -> if p.DiscordId = player.DiscordId then { p with Attacks = updatedAttacks } else p) | ||||||
|  |                 if updatedAttacks.Length < 1 then | ||||||
|                     async { |                     async { | ||||||
|                         let builder = DiscordInteractionResponseBuilder() |                         let builder = DiscordInteractionResponseBuilder() | ||||||
|                         builder.AddEmbed (this.Embed("Pick the hack you wish to use. ")) |> ignore |                         builder.AddEmbed (constructEmbed "Pick the hack you wish to use.") |> ignore | ||||||
|                          |                          | ||||||
|                         constructButtons "Attack" player.DiscordId player.Hacks |                         let targetInfo = $"{target.Id}-{target.Username}"  | ||||||
|  |                         constructButtons "Attack" targetInfo player.Hacks | ||||||
|                         |> Seq.cast<DiscordComponent> |                         |> Seq.cast<DiscordComponent> | ||||||
|                         |> builder.AddComponents |                         |> builder.AddComponents | ||||||
|                         |> ignore |                         |> ignore | ||||||
| @ -158,7 +178,8 @@ type JoeBot() = | |||||||
|                 else |                 else | ||||||
|                     async { |                     async { | ||||||
|                         let builder = DiscordInteractionResponseBuilder() |                         let builder = DiscordInteractionResponseBuilder() | ||||||
|                         builder.Content <- "You have no more hacks available, please wait for another hack to cooldown" |                         let timeRemaining = TimeSpan.FromMinutes(15) - (DateTime.UtcNow - updatedAttacks.Head.Timestamp) | ||||||
|  |                         builder.Content <- $"You already hacked, please wait {timeRemaining.Minutes} minutes and {timeRemaining.Seconds} seconds to attempt another hack" | ||||||
|                          |                          | ||||||
|                         builder.AsEphemeral true |> ignore |                         builder.AsEphemeral true |> ignore | ||||||
|                          |                          | ||||||
| @ -171,16 +192,20 @@ type JoeBot() = | |||||||
| 
 | 
 | ||||||
|      |      | ||||||
|     [<SlashCommand("defend", "Create a passive defense that will last a certain amount of time")>] |     [<SlashCommand("defend", "Create a passive defense that will last a certain amount of time")>] | ||||||
|     member this.Defend (ctx : InteractionContext) = |     member this.DefendCommand (ctx : InteractionContext) = | ||||||
|         players |         players | ||||||
|         |> List.tryFind (fun p -> p.DiscordId = ctx.Member.Id) |         |> List.tryFind (fun p -> p.DiscordId = ctx.Member.Id) | ||||||
|         |> function |         |> function | ||||||
|            | Some player -> |            | Some player -> | ||||||
|                 async { |                 async { | ||||||
|  |                     let updatedDefenses = removeExpiredActions (TimeSpan.FromMinutes(60)) (fun (pro : Defense) -> pro.Timestamp) player.Defenses | ||||||
|  |                     players <- | ||||||
|  |                         players | ||||||
|  |                         |> List.map (fun p -> if p.DiscordId = player.DiscordId then { p with Defenses = updatedDefenses } else p) | ||||||
|                     let builder = DiscordInteractionResponseBuilder() |                     let builder = DiscordInteractionResponseBuilder() | ||||||
|                     builder.AddEmbed (this.Embed("Pick a defense to mount for a duration of time")) |> ignore |                     builder.AddEmbed (constructEmbed "Pick a defense to mount for a duration of time") |> ignore | ||||||
|                      |                      | ||||||
|                     constructButtons "Defense" player.DiscordId player.Protections |                     constructButtons "Defense" (string player.DiscordId) player.Protections | ||||||
|                     |> Seq.cast<DiscordComponent> |                     |> Seq.cast<DiscordComponent> | ||||||
|                     |> builder.AddComponents |                     |> builder.AddComponents | ||||||
|                     |> ignore |                     |> ignore | ||||||
| @ -194,36 +219,27 @@ type JoeBot() = | |||||||
|                 :> Task |                 :> Task | ||||||
|            | None -> notRegisteredYetMessage ctx |            | None -> notRegisteredYetMessage ctx | ||||||
|      |      | ||||||
|     member _.Embed message = |  | ||||||
|         let builder = DiscordEmbedBuilder() |  | ||||||
|         builder.Color <- Optional(DiscordColor.PhthaloGreen) |  | ||||||
|         builder.Description <- message |  | ||||||
|         let author = DiscordEmbedBuilder.EmbedAuthor() |  | ||||||
|         author.Name <- "Joebot Pro" |  | ||||||
|         author.Url <- "https://ferano.io" |  | ||||||
|         author.IconUrl <- "https://i.kym-cdn.com/entries/icons/original/000/028/861/cover3.jpg" |  | ||||||
|         builder.Author <- author |  | ||||||
|         builder.Build() |  | ||||||
| 
 |  | ||||||
| let handleAttack (event : ComponentInteractionCreateEventArgs) = | let handleAttack (event : ComponentInteractionCreateEventArgs) = | ||||||
|     async { |     async { | ||||||
|         let split = event.Id.Split("-") |         let split = event.Id.Split("-") | ||||||
|         let ( resultHack , hackType ) = Enum.TryParse(typedefof<Hack>, split.[1]) |         let ( resultHack , hackType ) = Enum.TryParse(typedefof<Hack>, split.[1]) | ||||||
|         let ( resultId , target ) = UInt64.TryParse split.[2] |         let ( resultId , targetId ) = UInt64.TryParse split.[2] | ||||||
|         match resultHack , resultId with |         match resultHack , resultId with | ||||||
|         | true , true -> |         | true , true -> | ||||||
|  |             let hackType = hackType :?> Hack | ||||||
|             let builder = DiscordInteractionResponseBuilder() |             let builder = DiscordInteractionResponseBuilder() | ||||||
|             builder.IsEphemeral <- true |             builder.IsEphemeral <- true | ||||||
|             builder.Content <- $"Hack has been sent to {target}!" |             builder.Content <- $"Sent {hackType} to {split.[3]}!" | ||||||
|             do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |             do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) | ||||||
|                 |> Async.AwaitTask |                 |> Async.AwaitTask | ||||||
|                  |                  | ||||||
|  |             let attack = { HackType = hackType ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } } | ||||||
|             players <- |             players <- | ||||||
|                 players |                 players | ||||||
|                 |> List.map (fun p -> { p with Attacks = { HackType = hackType :?> Hack ; Timestamp = DateTime.UtcNow }::p.Attacks }) |                 |> List.map (fun p -> if p.DiscordId = event.User.Id then { p with Attacks = attack::p.Attacks } else p) | ||||||
|                  |                  | ||||||
|             let builder = DiscordMessageBuilder() |             let builder = DiscordMessageBuilder() | ||||||
|             builder.WithContent($"{event.User.Username} has sent a hack to <@{target}>") |> ignore |             builder.WithContent($"{event.User.Username} has sent a hack to <@{targetId}>") |> ignore | ||||||
|             let battleChannel = (event.Guild.GetChannel(927449884204867664uL)) |             let battleChannel = (event.Guild.GetChannel(927449884204867664uL)) | ||||||
|             do! battleChannel.SendMessageAsync(builder) |             do! battleChannel.SendMessageAsync(builder) | ||||||
|                 |> Async.AwaitTask |                 |> Async.AwaitTask | ||||||
| @ -239,16 +255,21 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) = | |||||||
| let handleDefense (event : ComponentInteractionCreateEventArgs) = | let handleDefense (event : ComponentInteractionCreateEventArgs) = | ||||||
|     async { |     async { | ||||||
|         let split = event.Id.Split("-") |         let split = event.Id.Split("-") | ||||||
|         let ( resultHack , hackType ) = Enum.TryParse(typedefof<Hack>, split.[1]) |         let ( resultHack , protectionType ) = Enum.TryParse(typedefof<Protection>, split.[1]) | ||||||
|         let ( resultId , target ) = UInt64.TryParse split.[2] |         match resultHack with | ||||||
|         match resultHack , resultId with |         | true -> | ||||||
|         | true , true -> |             let protectionType = protectionType :?> Protection | ||||||
|             let builder = DiscordInteractionResponseBuilder() |             let builder = DiscordInteractionResponseBuilder() | ||||||
|             builder.IsEphemeral <- true |             builder.IsEphemeral <- true | ||||||
|             builder.Content <- $"Hack has been sent to your target!" |             builder.Content <- $"Mounted a {protectionType} defense for 1 hour" | ||||||
|             do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |             do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) | ||||||
|                 |> Async.AwaitTask |                 |> Async.AwaitTask | ||||||
|                  |                  | ||||||
|  |             let defense = { DefenseType = protectionType ; Timestamp = DateTime.UtcNow } | ||||||
|  |             players <- | ||||||
|  |                 players | ||||||
|  |                 |> List.map (fun p -> { p with Defenses = defense::p.Defenses }) | ||||||
|  |                  | ||||||
|             let builder = DiscordMessageBuilder() |             let builder = DiscordMessageBuilder() | ||||||
|             builder.WithContent($"{event.User.Username} has protected their system!") |> ignore |             builder.WithContent($"{event.User.Username} has protected their system!") |> ignore | ||||||
|             let battleChannel = (event.Guild.GetChannel(927449884204867664uL)) |             let battleChannel = (event.Guild.GetChannel(927449884204867664uL)) | ||||||
| @ -265,10 +286,10 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) = | |||||||
|      |      | ||||||
| let handleButtonEvent (client : DiscordClient) (event : ComponentInteractionCreateEventArgs) = | let handleButtonEvent (client : DiscordClient) (event : ComponentInteractionCreateEventArgs) = | ||||||
|     async { |     async { | ||||||
|         return match event.Id with |         return! match event.Id with | ||||||
|                | id when id.StartsWith("Attack") -> handleAttack event |                 | id when id.StartsWith("Attack") -> handleAttack event | ||||||
|                | id when id.StartsWith("Defend") -> handleDefense event |                 | id when id.StartsWith("Defend") -> handleDefense event | ||||||
|                | _ -> async { return () } |                 | _ -> async { return () } | ||||||
|     } |> Async.StartAsTask |     } |> Async.StartAsTask | ||||||
|     :> Task |     :> Task | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user