WIP Compiler Errors: Adding DbService and PlayerRegistration components

This commit is contained in:
Joseph Ferano 2022-01-15 22:33:55 +07:00
parent e40fc42482
commit 7b2f6ba861
19 changed files with 285 additions and 111 deletions

39
DbService/DbService.fs Normal file
View File

@ -0,0 +1,39 @@
module DegenzGame.DbService
open DegenzGame.Shared
open DegenzGame.Shared
open MongoDB.Bson
open MongoDB.Driver
type PlayerEntry = {
Id : BsonObjectId
Player : Player
}
let mongo = MongoClient("mongodb://localhost:27017")
let db = mongo.GetDatabase("degenz-game")
let players = db.GetCollection<PlayerEntry>("players")
let tryFindPlayer (id : uint64) : Async<Player option> =
async {
let filter = Builders<PlayerEntry>.Filter.Eq((fun p -> p.Player.DiscordId), id)
let! player = players.FindAsync<PlayerEntry>(filter) |> Async.AwaitTask
return match player.ToEnumerable() |> Seq.toList with
| [] -> None
| entry::_ -> Some entry.Player
}
let insertNewPlayer (player : Player) =
async {
do! { Id = BsonObjectId(ObjectId.GenerateNewId()) ; Player = player }
|> players.InsertOneAsync
|> Async.AwaitTask
}
let removePlayer (memberId : uint64) =
async {
// TODO: Check the result of this delete operation
return! players.DeleteOneAsync (fun p -> p.Player.DiscordId = memberId)
|> Async.AwaitTask
|> Async.Ignore
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="DbService.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Shared.fsproj" />
</ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>

View File

@ -0,0 +1,7 @@
FSharp.Core
DSharpPlus
// DSharpPlus.CommandsNext
// DSharpPlus.Interactivity
DSharpPlus.SlashCommands
MongoDB.Driver

View File

@ -9,6 +9,10 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Shared", "Shared\Shared.fsp
EndProject EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Store", "Store\Store.fsproj", "{CD88B0A6-DE42-4087-9B33-48FF84201633}" Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Store", "Store\Store.fsproj", "{CD88B0A6-DE42-4087-9B33-48FF84201633}"
EndProject EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "PlayerRegistration", "PlayerRegistration\PlayerRegistration.fsproj", "{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "DbService", "DbService\DbService.fsproj", "{B1D3E1CC-451C-42D4-B054-D64E75E1A3B9}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -30,5 +34,13 @@ Global
{CD88B0A6-DE42-4087-9B33-48FF84201633}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD88B0A6-DE42-4087-9B33-48FF84201633}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD88B0A6-DE42-4087-9B33-48FF84201633}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD88B0A6-DE42-4087-9B33-48FF84201633}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD88B0A6-DE42-4087-9B33-48FF84201633}.Release|Any CPU.Build.0 = Release|Any CPU {CD88B0A6-DE42-4087-9B33-48FF84201633}.Release|Any CPU.Build.0 = Release|Any CPU
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.Build.0 = Release|Any CPU
{B1D3E1CC-451C-42D4-B054-D64E75E1A3B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1D3E1CC-451C-42D4-B054-D64E75E1A3B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1D3E1CC-451C-42D4-B054-D64E75E1A3B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1D3E1CC-451C-42D4-B054-D64E75E1A3B9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -6,7 +6,8 @@ open DSharpPlus
open DSharpPlus.Entities open DSharpPlus.Entities
open DSharpPlus.EventArgs open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands open DSharpPlus.SlashCommands
open DegenzGame.Types open DegenzGame.Shared
open DegenzGame.DbService
open DegenzGame.Functions open DegenzGame.Functions
open MongoDB.Driver open MongoDB.Driver
@ -16,60 +17,6 @@ open MongoDB.Driver
// My server // My server
let battleChannel = 927449884204867664uL let battleChannel = 927449884204867664uL
let mongo = MongoClient("mongodb://localhost:27017")
let db = mongo.GetDatabase("degenz-game")
let players = db.GetCollection<Player>("players")
let tryFindPlayer (id : uint64) : Async<Player option> =
async {
let filter = Builders<Player>.Filter.Eq((fun p -> p.DiscordId), id)
let! player = players.FindAsync<Player>(filter) |> Async.AwaitTask
return match player.ToEnumerable() |> Seq.toList with
| [] -> None
| p::_ -> Some p
}
let addHackerRole (ctx : InteractionContext) =
async {
let! player = tryFindPlayer ctx.Member.Id
let! newPlayer =
match player with
| Some _ -> async.Return false
| None ->
async {
let p = (newPlayer ctx.Member.Username ctx.Member.Id)
do! players.InsertOneAsync p |> Async.AwaitTask
for role in ctx.Guild.Roles do
if role.Value.Name = "Hacker" then
do! ctx.Member.GrantRoleAsync(role.Value)
|> Async.AwaitTask
return true
}
if newPlayer then
do! ctx.CreateResponseAsync("You are now an elite haxxor", true)
|> Async.AwaitTask
else
do! ctx.CreateResponseAsync("Already registered as an elite haxxor", true)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
let removeHackerRole (ctx : InteractionContext) =
async {
for role in ctx.Member.Roles do
if role.Name = "Hacker" then
do! ctx.Member.RevokeRoleAsync(role)
|> Async.AwaitTask
// TODO: Check the result of this delete operation
let! _ = players.DeleteOneAsync (fun p -> p.DiscordId = ctx.Member.Id) |> Async.AwaitTask
do! ctx.CreateResponseAsync("You are now lame", true)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
let attack (ctx : InteractionContext) (target : DiscordUser) = let attack (ctx : InteractionContext) (target : DiscordUser) =
async { async {

View File

@ -3,9 +3,7 @@ module DegenzGame.Functions
open System open System
open DSharpPlus open DSharpPlus
open DSharpPlus.Entities open DSharpPlus.Entities
open DSharpPlus.SlashCommands open DegenzGame.Shared
open DegenzGame.Types
open MongoDB.Bson
let hackDescription = "" let hackDescription = ""
@ -16,29 +14,6 @@ Active Hacks: {player.Attacks |> Array.toList}
Active Defenses: {player.Defenses |> Array.toList} Active Defenses: {player.Defenses |> Array.toList}
Bank: {player.Bank}" Bank: {player.Bank}"
let newPlayer nickname (membr : uint64) =
let h1 = [| Weapon.Virus ; Weapon.Ransom |]
let h2 = [| Weapon.DDos ; Weapon.Worm |]
let h3 = [| Weapon.Crack ; Weapon.Injection |]
let d1 = [| Shield.Firewall ; Shield.PortScan |]
let d2 = [| Shield.Encryption ; Shield.Cypher |]
let d3 = [| Shield.Hardening ; Shield.Sanitation |]
let rand = System.Random(System.Guid.NewGuid().GetHashCode())
let getRandom (actions : 'a array) = actions.[rand.Next(0,2)]
let weapons = [| getRandom h1 ; getRandom h2 ; getRandom h3 |]
let shields = [| getRandom d1 ; getRandom d2 ; getRandom d3 |]
{ Id = BsonObjectId(ObjectId.GenerateNewId())
DiscordId = membr
Name = nickname
Weapons = weapons
Shields = shields
Attacks = [||]
Defenses = [||]
Bank = 0f }
let constructButtons (actionType : string) (playerInfo : string) (weapons : 'a array) = let constructButtons (actionType : string) (playerInfo : string) (weapons : 'a array) =
weapons weapons
|> Seq.map (fun hack -> |> Seq.map (fun hack ->
@ -47,17 +22,6 @@ let constructButtons (actionType : string) (playerInfo : string) (weapons : 'a a
$"{actionType}-{hack}-{playerInfo}", $"{actionType}-{hack}-{playerInfo}",
$"{hack}")) $"{hack}"))
let createSimpleResponseAsync msg (ctx : InteractionContext) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.Content <- msg
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
let notYetAHackerMsg = createSimpleResponseAsync "You are not currently a hacker, first use the /redpill command to become one"
let removeExpiredActions timespan (timestamp : 'a -> DateTime) actions = let removeExpiredActions timespan (timestamp : 'a -> DateTime) actions =
actions actions
|> Array.filter (fun act -> |> Array.filter (fun act ->

View File

@ -17,8 +17,10 @@
<Compile Include="Functions.fs" /> <Compile Include="Functions.fs" />
<Compile Include="Commands.fs" /> <Compile Include="Commands.fs" />
<Compile Include="Program.fs" /> <Compile Include="Program.fs" />
<Content Include="paket.references" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DbService\DbService.fsproj" />
<ProjectReference Include="..\Shared\Shared.fsproj" /> <ProjectReference Include="..\Shared\Shared.fsproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" /> <Import Project="..\.paket\Paket.Restore.targets" />

View File

@ -1,27 +1,16 @@
module DegenzGame.Program open System.Threading.Tasks
open System
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 DegenzGame.Types open DegenzGame
open DegenzGame.Commands open DegenzGame.Commands
open MongoDB.Driver
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule () type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
type HackerGame() = type HackerGame() =
inherit ApplicationCommandModule () inherit ApplicationCommandModule ()
[<SlashCommand("redpill", "Take the redpill and become a hacker")>]
member _.AddHackerRole (ctx : InteractionContext) = Commands.addHackerRole ctx
[<SlashCommand("bluepill", "Take the bluepill and become lame")>]
member _.RemoveHackerRole (ctx : InteractionContext) = Commands.removeHackerRole ctx
[<SlashCommand("hack", "Send a hack attack to another player")>] [<SlashCommand("hack", "Send a hack attack to another player")>]
member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) = member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) =
Commands.attack ctx target Commands.attack ctx target

View File

@ -4,4 +4,4 @@ DSharpPlus
// DSharpPlus.Interactivity // DSharpPlus.Interactivity
DSharpPlus.SlashCommands DSharpPlus.SlashCommands
MongoDB.Driver // MongoDB.Driver

View File

@ -0,0 +1,25 @@
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.idea
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

View File

@ -0,0 +1,18 @@
FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PlayerRegistration/PlayerRegistration.fsproj", "PlayerRegistration/"]
RUN dotnet restore "PlayerRegistration/PlayerRegistration.fsproj"
COPY . .
WORKDIR "/src/PlayerRegistration"
RUN dotnet build "PlayerRegistration.fsproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "PlayerRegistration.fsproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "PlayerRegistration.dll"]

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<Content Include=".dockerignore" />
<Content Include="Dockerfile" />
<Content Include="paket.references" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DbService\DbService.fsproj" />
<ProjectReference Include="..\Shared\Shared.fsproj" />
</ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>

View File

@ -0,0 +1,115 @@
open System.Threading.Tasks
open DegenzGame.DbService
open DSharpPlus
open DSharpPlus.SlashCommands
open DegenzGame.Shared
module Commands =
let newPlayer nickname (membr : uint64) =
let h1 = [| Weapon.Virus ; Weapon.Ransom |]
let h2 = [| Weapon.DDos ; Weapon.Worm |]
let h3 = [| Weapon.Crack ; Weapon.Injection |]
let d1 = [| Shield.Firewall ; Shield.PortScan |]
let d2 = [| Shield.Encryption ; Shield.Cypher |]
let d3 = [| Shield.Hardening ; Shield.Sanitation |]
let rand = System.Random(System.Guid.NewGuid().GetHashCode())
let getRandom (actions : 'a array) = actions.[rand.Next(0,2)]
let weapons = [| getRandom h1 ; getRandom h2 ; getRandom h3 |]
let shields = [| getRandom d1 ; getRandom d2 ; getRandom d3 |]
{ DiscordId = membr
Name = nickname
Weapons = weapons
Shields = shields
Attacks = [||]
Defenses = [||]
Bank = 0f }
let addHackerRole (ctx : InteractionContext) =
async {
let! player = tryFindPlayer ctx.Member.Id
let! newPlayer =
match player with
| Some _ -> async.Return false
| None ->
async {
do! newPlayer ctx.Member.Username ctx.Member.Id
|> insertNewPlayer
for role in ctx.Guild.Roles do
if role.Value.Name = "Hacker" then
do! ctx.Member.GrantRoleAsync(role.Value)
|> Async.AwaitTask
return true
}
if newPlayer then
do! ctx.CreateResponseAsync("You are now an elite haxxor", true)
|> Async.AwaitTask
else
do! ctx.CreateResponseAsync("Already registered as an elite haxxor", true)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
let removeHackerRole (ctx : InteractionContext) =
async {
for role in ctx.Member.Roles do
if role.Name = "Hacker" then
do! ctx.Member.RevokeRoleAsync(role)
|> Async.AwaitTask
do! removePlayer ctx.Member.Id
do! ctx.CreateResponseAsync("You are now lame", true)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
type PlayerRegistration() =
inherit ApplicationCommandModule ()
[<SlashCommand("redpill", "Take the redpill and become a hacker")>]
member _.AddHackerRole (ctx : InteractionContext) = Commands.addHackerRole ctx
[<SlashCommand("bluepill", "Take the bluepill and become lame")>]
member _.RemoveHackerRole (ctx : InteractionContext) = Commands.removeHackerRole ctx
let config = DiscordConfiguration()
config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk"
config.TokenType <- TokenType.Bot
config.Intents <- DiscordIntents.All
//config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace
let client = new DiscordClient(config)
//client.add_ComponentInteractionCreated(AsyncEventHandler(handleButtonEvent))
let slash = client.UseSlashCommands()
// My server
slash.RegisterCommands<PlayerRegistration>(922419263275425832uL);
// Degenz
//slash.RegisterCommands<HackerGame>(922414052708327494uL);
client.ConnectAsync ()
|> Async.AwaitTask
|> Async.RunSynchronously
Task.Delay(-1)
|> Async.AwaitTask
|> Async.RunSynchronously
client.DisconnectAsync ()
|> Async.AwaitTask
|> Async.RunSynchronously

View File

@ -0,0 +1,7 @@
FSharp.Core
DSharpPlus
// DSharpPlus.CommandsNext
// DSharpPlus.Interactivity
DSharpPlus.SlashCommands
// MongoDB.Driver

View File

@ -6,6 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Types.fs" /> <Compile Include="Types.fs" />
<Content Include="paket.references" />
</ItemGroup> </ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" /> <Import Project="..\.paket\Paket.Restore.targets" />
</Project> </Project>

View File

@ -1,7 +1,9 @@
module DegenzGame.Types module DegenzGame.Shared
open System open System
open MongoDB.Bson open DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.SlashCommands
type ActionClass = type ActionClass =
| Network | Network
@ -54,7 +56,6 @@ type Defense = {
[<CLIMutable>] [<CLIMutable>]
type Player = { type Player = {
Id : BsonObjectId
DiscordId : uint64 DiscordId : uint64
Name : string Name : string
Weapons : Weapon array Weapons : Weapon array
@ -64,4 +65,13 @@ type Player = {
Bank : single Bank : single
} }
let createSimpleResponseAsync msg (ctx : InteractionContext) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.Content <- msg
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
let notYetAHackerMsg = createSimpleResponseAsync "You are not currently a hacker, first use the /redpill command to become one"

View File

@ -1,2 +1,3 @@
FSharp.Core FSharp.Core
MongoDB.Driver DSharpPlus
DSharpPlus.SlashCommands

View File

@ -11,8 +11,10 @@
<ItemGroup> <ItemGroup>
<Content Include=".dockerignore" /> <Content Include=".dockerignore" />
<Content Include="Dockerfile" /> <Content Include="Dockerfile" />
<Content Include="paket.references" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DbService\DbService.fsproj" />
<ProjectReference Include="..\Shared\Shared.fsproj" /> <ProjectReference Include="..\Shared\Shared.fsproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" /> <Import Project="..\.paket\Paket.Restore.targets" />

View File

@ -4,4 +4,4 @@ DSharpPlus
// DSharpPlus.Interactivity // DSharpPlus.Interactivity
DSharpPlus.SlashCommands DSharpPlus.SlashCommands
MongoDB.Driver // MongoDB.Driver