72 lines
2.9 KiB
Forth

module Degenz.DbService
open Degenz.Types
open System
open MongoDB.Bson
open MongoDB.Bson.Serialization
open MongoDB.Driver
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 (bson : BsonDocument) : PlayerData =
{ DiscordId = tryWithDefault bson "DiscordId" 0uL (fun v -> v.AsInt64 |> uint64)
Name = tryWithDefault bson "Name" "Empty" (fun v -> v.AsString)
Inventory =
tryWithDefault bson "Inventory" [||] (fun v ->
v.AsBsonArray
|> Seq.map (fun (bv : BsonValue) -> BsonSerializer.Deserialize<Item>(bv.ToBsonDocument()))
|> Seq.toArray)
Events = tryWithDefault bson "Events" [||] (fun v ->
v.AsBsonArray
|> Seq.map (fun (bv : BsonValue) ->
BsonSerializer.Deserialize<PlayerEvent>(bv.ToBsonDocument()))
|> Seq.toArray)
Traits =
tryWithDefault bson "Traits" PlayerTraits.empty (fun v ->
BsonSerializer.Deserialize<PlayerTraits>(v.ToBsonDocument()))
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 = tryWithDefault bson "Bank" 0<GBT> (fun v -> v.AsInt32 * 1<GBT>)
}
let tryFindPlayer (id : uint64) =
async {
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
let! player = players.FindAsync<BsonDocument>(filter) |> Async.AwaitTask
match player.FirstOrDefault() with
| null -> return None
| p ->
let v = p.GetValue("Player")
let playerData = v.ToBsonDocument() |> mapBack
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
}