felt/mongodb/adapter.go

299 lines
7.3 KiB
Go
Raw Normal View History

package dbengine
import (
"context"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"nilfm.cc/git/felt/models"
"time"
)
2022-11-11 07:23:53 +00:00
const errNoCollection string = "collection not found: felt.%s"
const errNoDocument string = "document with name/id '%s' doesn't exist in collection: %s"
const errNotAString string = "document property is not a string: %s<key=%s>.%s"
const errNotAnArray string = "doccument property is not an array: %s<key=%s>.%s"
2022-11-11 07:23:53 +00:00
type DbAdapter interface {
Init(mongoUri string) error
CreateTable(table models.TableKey) error
DestroyTable(table models.TableKey) error
InsertDiceRoll(table models.TableKey, diceRoll models.DiceRoll) error
GetDiceRolls(table models.TableKey) ([]models.DiceRoll, error)
SetMapImageUrl(table models.TableKey, url string) error
GetMapImageUrl(table models.TableKey) (string, error)
AddToken(table models.TableKey, token models.Token, active boolean) error
RemoveToken(table models.TableKey, tokenId string, active boolean) error
ModifyToken(table models.TableKey, token models.Token, active boolean) error
GetTokens(table models.TableKey, active boolean) ([]models.Token, error)
}
type DbEngine struct {
client mongo.Client
db mongo.Database
}
func (self *DbEngine) mkCtx(timeoutSec int) context.Context {
return context.WithTimeout(context.Background(), 10*time.Second)
}
func (self *DbEngine) Init(mongoUri string) error {
client, err := mongo.NewClient(options.Client().ApplyURI(mongoUri))
if err != nil {
return err
}
self.client = client
ctx, _ := self.mkCtx(10)
err = client.Connect(ctx)
if err != nil {
return err
}
db := client.Database("felt")
self.db = db
err = self.ensureCollections(db)
return err
}
func (self *DbEngine) ensureCollections(db mongo.Database) error {
tables := db.Collection("tables")
if tables == nil {
createCmd := bson.D{
{"create", "tables"},
{"clusteredIndex", {
{"key", {"name"}},
{"unique", true},
{"name", "idx_tables_unique_names"},
}},
}
var createResult bson.M
err := db.RunCommand(
self.mkCtx(10),
createCmd).Decode(&createResult)
if err != nil {
return err
}
}
return nil
}
func (self *DbEngine) CreateTable(table models.TableKey) error {
tables := self.db.Collection("tables")
if tables != nil {
2022-11-11 07:23:53 +00:00
_, err := tables.InsertOne(self.mkCtx(10), bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
{"mapImageUrl", ""},
{"diceRolls", bson.A{}},
{"tokens", bson.A{}},
{"availableTokens", bson.A{}},
})
2022-11-11 07:23:53 +00:00
return err
}
2022-11-11 07:23:53 +00:00
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
2022-11-11 07:23:53 +00:00
}
func (self *DbEngine) DestroyTable(table models.TableKey) error {
tables := self.db.Collection("tables")
if tables != nil {
_, err := tables.DeleteOne(self.mkCtx(10), bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
})
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) InsertDiceRoll(table models.TableKey, diceRoll models.DiceRoll) error {
tables := self.db.Collection("tables")
if tables != nil {
var result models.Table
err := tables.FindOneAndUpdate(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
},
bson.D{
{"$push", bson.D{
"diceRolls", bson.D{
{"$each", []models.DiceRoll{diceRoll}},
{"$slice", 1000},
},
}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) GetDiceRolls(table models.TableKey) ([]models.DiceRoll, error) {
tables := self.db.Colletion("tables")
if tables != nil {
var result models.Table
err := tables.findOne(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
}).Decode(&result)
if err == nil {
return result.DiceRolls, nil
} else {
return "", errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
}
}
return "", errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
2022-11-11 07:23:53 +00:00
func (self *DbEngine) SetMapImageUrl(table models.TableKey, url string) error {
tables := self.db.Collection("tables")
if tables != nil {
var result models.Table
err := tables.FindOneAndUpdate(
2022-11-11 07:23:53 +00:00
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
},
bson.D{
{"mapImageUrl", url},
},
).Decode(&result)
2022-11-11 07:23:53 +00:00
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) GetMapImageUrl(table models.TableKey) (string, error) {
tables := self.db.Collection("tables")
if tables != nil {
var result models.Table
err := tables.FindOne(
2022-11-11 07:23:53 +00:00
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
}).Decode(&result)
if err == nil {
return result.MapImageUrl, nil
2022-11-11 07:23:53 +00:00
} else {
return "", errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
}
}
return "", errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) AddToken(table models.TableKey, token models.Token, active boolean) error {
tables := self.db.Collection("tables")
if tables != nil {
tokenArrKey := "tokens"
if !active {
tokenArrKey = "availableTokens"
}
var result models.Table
err := tables.FindOneAndUpdate(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
},
bson.D{
{"$push", bson.D{tokenArrKey, token}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) RemoveToken(table models.TableKey, tokenId string, active boolean) error {
tables := self.db.Collection("tables")
if tables != nil {
tokenArrKey := "tokens"
if !active {
tokenArrKey = "availableTokens"
}
var result models.Table
err := tables.FindOneAndUpdate(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
},
bson.D{
{"$pull", bson.D{tokenArrKey, bson.D{"_id", tokenId}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) ModifyToken(table models.TableKey, token models.Token, active boolean) error {
tables := self.db.Collection("tables")
if tables != nil {
tokenArrKey := "tokens"
if !active {
tokenArrKey = "availableTokens"
}
var result models.Table
err := tables.FindOneAndUpdate(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
{tokenArrKey, bson.D{"_id", tokenId}},
},
bson.D{
{"$set", bson.D{tokenArrKey + ".$", bson.D{
{"name", token.Name},
{"spriteUri", token.SpriteUri},
{"x", token.X},
{"y", token.Y},
}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) GetTokens(table models.TableKey, active boolean) ([]models.Token, error) {
tables := self.db.Collection("tables")
if tables != nil {
var result models.Table
err := tables.FindOne(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
}).Decode(&result)
if err == nil {
if active {
return result.Tokens
} else {
return result.AvailableTokens
}
} else {
return nil, errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
}
}
return nil, errors.New(fmt.Sprintf(errNoCollection, "tables"))
}