99 lines
3.5 KiB
Forth
99 lines
3.5 KiB
Forth
module Degenz.DbService
|
|
|
|
open Degenz.Types
|
|
|
|
open System
|
|
open MongoDB.Bson
|
|
open MongoDB.Bson.Serialization
|
|
open MongoDB.Driver
|
|
open Npgsql.FSharp
|
|
|
|
type User = {
|
|
Name : string
|
|
DiscordId : uint64
|
|
Bank : int<GBT>
|
|
Strength : int
|
|
Inventory : int array
|
|
}
|
|
|
|
let mongo = MongoClient(Environment.GetEnvironmentVariable("CONN_STRING"))
|
|
let db = mongo.GetDatabase("degenz")
|
|
let players = db.GetCollection<BsonDocument>("players")
|
|
|
|
let tryWithDefault (bson : BsonDocument) field (defaultValue : 'a) (map : BsonValue -> 'a) =
|
|
try
|
|
let result , bval = bson.TryGetValue(field)
|
|
if result then map bval else defaultValue
|
|
with _ -> defaultValue
|
|
|
|
let mapBack user (bson : BsonDocument) : PlayerData =
|
|
{ DiscordId = user.DiscordId
|
|
Name = user.Name
|
|
Inventory =
|
|
user.Inventory
|
|
|> Array.map (fun iId ->
|
|
Armory.battleItems
|
|
|> Array.tryFind (fun i -> i.Id = iId)
|
|
|> function
|
|
| Some i -> [| i |]
|
|
| None -> [||])
|
|
|> Array.concat
|
|
Events = tryWithDefault bson "Events" [||] (fun v ->
|
|
v.AsBsonArray
|
|
|> Seq.map (fun (bv : BsonValue) ->
|
|
BsonSerializer.Deserialize<PlayerEvent>(bv.ToBsonDocument()))
|
|
|> Seq.toArray)
|
|
Traits = { PlayerTraits.empty with Strength = user.Strength }
|
|
// Achievements =
|
|
// tryWithDefault bson "Achievements" [||] (fun v ->
|
|
// v.AsBsonArray |> Seq.map (fun (bv : BsonValue) -> bv.AsString) |> Seq.toArray)
|
|
// XP = tryWithDefault bson "XP" 0 (fun v -> v.AsInt32)
|
|
Bank = user.Bank
|
|
}
|
|
|
|
let tryFindPlayer connStr (id : uint64) =
|
|
async {
|
|
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
|
|
let! player = players.FindAsync<BsonDocument>(filter) |> Async.AwaitTask
|
|
let! user =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.query "SELECT * FROM users WHERE discordId = @did"
|
|
|> Sql.parameters [ "did", Sql.int64 (int64 id) ]
|
|
|> Sql.executeAsync (fun read ->
|
|
{
|
|
DiscordId = read.int64 "discordId" |> uint64
|
|
Name = read.string "displayName"
|
|
Bank = read.int "gbt" * 1<GBT>
|
|
Strength = read.int "strength"
|
|
Inventory = read.intArray "inventory"
|
|
})
|
|
|> Async.AwaitTask
|
|
|
|
match player.FirstOrDefault() , List.tryHead user with
|
|
| null , _
|
|
| _ , None -> return None
|
|
| p , Some u ->
|
|
let v = p.GetValue("Player")
|
|
let playerData = mapBack u (v.ToBsonDocument())
|
|
return Some playerData
|
|
}
|
|
|
|
let insertNewPlayer (player : PlayerData) =
|
|
async {
|
|
do! BsonDocument("Player", player.ToBsonDocument()) |> players.InsertOneAsync |> Async.AwaitTask
|
|
}
|
|
|
|
let updatePlayer (player : PlayerData) =
|
|
async {
|
|
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", player.DiscordId)
|
|
let update = Builders<BsonDocument>.Update.Set("Player", player.ToBsonDocument())
|
|
do! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
|
|
}
|
|
|
|
let addAchievement (id : uint64) (achievement : string) =
|
|
async {
|
|
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
|
|
let update = Builders<BsonDocument>.Update.Push("Player.Achievements", achievement)
|
|
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
|
|
} |