Hack flow with buttons

This commit is contained in:
Joseph Ferano 2022-01-09 04:07:05 +07:00
parent db7126e642
commit 043ed06572
3 changed files with 134 additions and 79 deletions

View File

@ -1,11 +1,11 @@
open System.IO open System
open System.IO
open System.Threading.Tasks open System.Threading.Tasks
open DSharpPlus open DSharpPlus
open DSharpPlus.Entities open DSharpPlus.Entities
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands open DSharpPlus.SlashCommands
open Emzi0767.Utilities open Emzi0767.Utilities
open LiteDB
open LiteDB.FSharp
type HackType = type HackType =
| Virus = 0 | Virus = 0
@ -13,37 +13,41 @@ type HackType =
| DDos = 2 | DDos = 2
| Worm = 3 | Worm = 3
| Crack = 4 | Crack = 4
| SomeOtherThing = 4 | Injection = 5
type DefenseType = type DefenseType =
| Firewall | Firewall = 0
| PortScan | PortScan = 1
| Encryption | Encryption = 2
| Cypher | Cypher = 3
| Hardening | Hardening = 4
| Sanitation = 5
[<CLIMutable>]
type Weapon = {
Id : int
Name : string
Damage : single
}
type Player = { type Player = {
Id : int DiscordId : uint64
Name : string Hacks : HackType list
Nickname : string Defenses : DefenseType list
DiscordId : uint16 Bank : int64
Weapons : int array
} }
type Match = let mutable players : Player list = []
{ scorePlayer1 : int
round : int
scorePlayer2 : int }
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule () type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
let newPlayer (membr : uint64) =
// let rand = System.Random(System.Guid.NewGuid().GetHashCode())
// let hacks =
// [0..2]
// |> Set.map (fun _ -> enum<HackType>(rand.Next(0, 6)))
// let defns =
// [0..2]
// |> Set.map (fun _ -> enum<DefenseType>(rand.Next(0, 6)))
{ DiscordId = membr
Hacks = [ HackType.Virus ; HackType.Worm ; HackType.Injection ]
Defenses = [ DefenseType.Cypher ; DefenseType.Sanitation ; DefenseType.Firewall ]
Bank = 0L }
type JoeBot() = type JoeBot() =
inherit ApplicationCommandModule () inherit ApplicationCommandModule ()
@ -54,8 +58,21 @@ type JoeBot() =
if role.Value.Name = "Hacker" then if role.Value.Name = "Hacker" then
do! ctx.Member.GrantRoleAsync(role.Value) do! ctx.Member.GrantRoleAsync(role.Value)
|> Async.AwaitTask |> Async.AwaitTask
do! ctx.CreateResponseAsync("You are now an elite haxxor", true)
|> Async.AwaitTask let player = players |> List.tryFind (fun p -> int64 p.DiscordId = int64 ctx.Member.Id)
players <-
match player with
| Some _ -> players
| None -> (newPlayer ctx.Member.Id)::players
if Option.isSome player then
do! ctx.CreateResponseAsync("Already registered as an elite haxxor", true)
|> Async.AwaitTask
else
do! ctx.CreateResponseAsync("You are now an elite haxxor", true)
|> Async.AwaitTask
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
@ -71,6 +88,51 @@ type JoeBot() =
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
[<SlashCommand("hack", "Send a hack attack to another player")>]
member this.Hack (ctx : InteractionContext, [<Option("player", "The player you want to hack")>] player : DiscordUser) =
let constructButtons (playerId : uint64) (weapons : 'a list) =
weapons
|> 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(
ButtonStyle.Primary,
$"Hack-{hack}-{player.Id}",
$"{hack}"))
players
|> List.tryFind (fun p -> p.DiscordId = ctx.Member.Id)
|> function
| Some player ->
async {
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (this.Embed()) |> ignore
constructButtons player.DiscordId player.Hacks
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
| None ->
async {
let builder = DiscordInteractionResponseBuilder()
builder.Content <- $"You are not currently a hacker, first use the /redpill command to become one"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
[<SlashCommand("challenge", "Challenge another user")>] [<SlashCommand("challenge", "Challenge another user")>]
member _.StartMatch (ctx : InteractionContext, [<Option("player", "Player you want to challenge")>] player : DiscordUser) = member _.StartMatch (ctx : InteractionContext, [<Option("player", "Player you want to challenge")>] player : DiscordUser) =
async { async {
@ -86,6 +148,15 @@ type JoeBot() =
ButtonStyle.Danger, ButtonStyle.Danger,
"second_button", "second_button",
"No thank you") "No thank you")
// let yes = DiscordButtonComponent(
// ButtonStyle.Primary,
// $"yes_for_{ctx.Member.Id}",
// "I do")
// let no = DiscordButtonComponent(
// ButtonStyle.Danger,
// $"no_for_{ctx.Member.Id}",
// "No thank you")
// builder.AddComponents(yes, no) |> ignore
let builder = DiscordMessageBuilder() let builder = DiscordMessageBuilder()
let builder = builder.AddComponents(yes, no) let builder = builder.AddComponents(yes, no)
use img = new FileStream("challenge.jpg", FileMode.Open) use img = new FileStream("challenge.jpg", FileMode.Open)
@ -116,53 +187,15 @@ type JoeBot() =
member _.Embed () = member _.Embed () =
let builder = DiscordEmbedBuilder() let builder = DiscordEmbedBuilder()
builder.Color <- Optional(DiscordColor.Blurple) builder.Color <- Optional(DiscordColor.PhthaloGreen)
builder.Description <- "This is a test embed" builder.Description <- "Pick the hack you wish to use. "
let author = DiscordEmbedBuilder.EmbedAuthor() let author = DiscordEmbedBuilder.EmbedAuthor()
author.Name <- "Joebot Pro" author.Name <- "Joebot Pro"
author.Url <- "https://ferano.io" author.Url <- "https://ferano.io"
author.IconUrl <- "https://i.kym-cdn.com/entries/icons/original/000/028/861/cover3.jpg" author.IconUrl <- "https://i.kym-cdn.com/entries/icons/original/000/028/861/cover3.jpg"
builder.Author <- author builder.Author <- author
let footer = DiscordEmbedBuilder.EmbedFooter()
footer.Text <- "This is a footer"
footer.IconUrl <- "https://dg8krxphbh767.cloudfront.net/exercises/bird-watcher.svg"
builder.Footer <- footer
builder.Title <- "THIS IS A TITLE"
builder.ImageUrl <- "https://avatars3.githubusercontent.com/u/2642263"
builder.Build() builder.Build()
[<SlashCommand("hack", "Send a hack attack to another player")>]
member this.Hack (ctx : InteractionContext, [<Option("player", "The player you want to hack")>] player : DiscordUser) =
let constructButtons (weapons : HackType list) =
weapons
|> 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(
ButtonStyle.Primary,
$"{hack}{System.Guid.NewGuid()}",
$"{hack}"))
async {
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (this.Embed()) |> ignore
constructButtons [ HackType.Virus ; HackType.Crack ; HackType.Ransom ; HackType.Worm ; HackType.DDos ]
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
constructButtons [ HackType.Virus ; HackType.Crack ; HackType.Ransom ; HackType.Worm ; HackType.DDos ]
|> Seq.cast<DiscordComponent>
|> builder.AddComponents
|> ignore
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
[<SlashCommand("test", "testing the embeds")>] [<SlashCommand("test", "testing the embeds")>]
member this.TestEmbed (ctx : InteractionContext) = member this.TestEmbed (ctx : InteractionContext) =
async { async {
@ -172,9 +205,38 @@ type JoeBot() =
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
let mapper = FSharpBsonMapper() let handleButtonEvent (client : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
async {
match event.Id with
| id when id.StartsWith("Hack") ->
let split = event.Id.Split("-")
let ( resultHack , hackType ) = Enum.TryParse(typedefof<HackType>, split.[1])
let ( resultId , target ) = UInt64.TryParse split.[2]
match resultHack , resultId with
| true , true ->
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Hack has been sent to {target}!"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask
let db = new LiteDatabase("hacker-game.db", mapper) let builder = DiscordMessageBuilder()
// builder..Add(UserMention(target))
builder.WithContent($"{event.User.Username} has sent a hack to ") |> ignore
let battleChannel = (event.Guild.GetChannel(927444uL))
do! battleChannel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
| _ ->
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- "Error parsing Button Id"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| _ -> ()
} |> Async.StartAsTask
:> Task
let config = DiscordConfiguration() let config = DiscordConfiguration()
config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk" config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk"
@ -184,12 +246,7 @@ config.Intents <- DiscordIntents.All
let client = new DiscordClient(config) let client = new DiscordClient(config)
client.add_ComponentInteractionCreated(AsyncEventHandler( client.add_ComponentInteractionCreated(AsyncEventHandler(handleButtonEvent))
fun client event ->
async {
return ()
} |> Async.StartAsTask
:> Task))
let slash = client.UseSlashCommands() let slash = client.UseSlashCommands()

View File

@ -11,4 +11,3 @@ nuget DSharpPlus >= 4.2.0-nightly-01054
nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01054 nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01054
nuget LiteDB.FSharp 2.16.0 nuget LiteDB.FSharp 2.16.0
nuget LiteDB 4.1.4

View File

@ -3,5 +3,4 @@ DSharpPlus
// DSharpPlus.CommandsNext // DSharpPlus.CommandsNext
// DSharpPlus.Interactivity // DSharpPlus.Interactivity
DSharpPlus.SlashCommands DSharpPlus.SlashCommands
LiteDB
LiteDB.FSharp LiteDB.FSharp