felt/mongodb/adapter.go

385 lines
9.3 KiB
Go
Raw Normal View History

2022-12-07 04:58:42 +00:00
package mongodb
import (
"context"
2022-12-22 04:45:15 +00:00
"errors"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"hacklab.nilfm.cc/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
2022-12-07 04:58:42 +00:00
CheckTable(table models.TableKey) bool
GetProtocols() ([]string, 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)
2022-12-22 04:45:15 +00:00
2022-12-07 04:58:42 +00:00
SetAuxMessage(table models.TableKey, message string) error
GetAuxMessage(table models.TableKey) (string, error)
AddToken(table models.TableKey, token models.Token, active bool) error
RemoveToken(table models.TableKey, tokenId string, active bool) error
ModifyToken(table models.TableKey, token models.Token, active bool) error
GetTokens(table models.TableKey, active bool) ([]models.Token, error)
}
type DbEngine struct {
2022-12-07 04:58:42 +00:00
client *mongo.Client
db *mongo.Database
}
func (self *DbEngine) mkCtx(timeoutSec int) context.Context {
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
return ctx
}
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
}
2022-12-07 04:58:42 +00:00
func (self *DbEngine) ensureCollections(db *mongo.Database) error {
tables := db.Collection("tables")
if tables == nil {
createCmd := bson.D{
{"create", "tables"},
2022-12-07 04:58:42 +00:00
{"clusteredIndex", bson.D{
{"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"))
}
2022-12-07 04:58:42 +00:00
func (self *DbEngine) CheckTable(table models.TableKey) bool {
tables := self.db.Collection("tables")
if tables != nil {
2022-12-07 04:58:42 +00:00
res := tables.FindOne(self.mkCtx(10), bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
})
2022-12-07 04:58:42 +00:00
return res != nil
}
return false
}
func (self *DbEngine) GetProtocols() ([]string, error) {
tables := self.db.Collection("tables")
if tables != nil {
var results []models.Table
cursor, err := tables.Find(self.mkCtx(10), bson.D{})
if err != nil {
return []string{}, err
}
if err = cursor.All(self.mkCtx(10), &results); err != nil {
return []string{}, err
}
var protocols []string
for _, t := range results {
protocols = append(protocols, fmt.Sprintf("%s.%s", t.Name, t.Passcode))
}
return protocols, nil
}
return []string{}, 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{
2022-12-07 04:58:42 +00:00
{"diceRolls", bson.D{
{"$each", []models.DiceRoll{diceRoll}},
{"$slice", 1000},
2022-12-07 04:58:42 +00:00
}},
}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) GetDiceRolls(table models.TableKey) ([]models.DiceRoll, error) {
2022-12-07 04:58:42 +00:00
tables := self.db.Collection("tables")
if tables != nil {
var result models.Table
2022-12-07 04:58:42 +00:00
err := tables.FindOne(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
}).Decode(&result)
if err == nil {
return result.DiceRolls, nil
} else {
2022-12-07 04:58:42 +00:00
return nil, errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
}
}
2022-12-07 04:58:42 +00:00
return nil, 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{
{"$set", bson.D{{"mapImageUrl", url}}},
2022-11-11 07:23:53 +00:00
},
).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"))
}
2022-12-07 04:58:42 +00:00
func (self *DbEngine) SetAuxMessage(table models.TableKey, message string) 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{
{"$set", bson.D{{"auxMessage", message}}},
2022-12-07 04:58:42 +00:00
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) GetAuxMessage(table models.TableKey) (string, 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 {
return result.AuxMessage, nil
} 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 bool) 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{
2022-12-07 04:58:42 +00:00
{"$push", bson.D{{tokenArrKey, token}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
2022-12-07 04:58:42 +00:00
func (self *DbEngine) RemoveToken(table models.TableKey, tokenId string, active bool) 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{
2022-12-22 04:45:15 +00:00
{"$pull", bson.D{{tokenArrKey, bson.D{{"_id", tokenId}}}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
2022-12-07 04:58:42 +00:00
func (self *DbEngine) ModifyToken(table models.TableKey, token models.Token, active bool) 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},
2022-12-07 04:58:42 +00:00
{tokenArrKey, bson.E{"_id", token.Id}},
},
bson.D{
2022-12-07 04:58:42 +00:00
{"$set", bson.D{{tokenArrKey + ".$", bson.D{
{"name", token.Name},
{"spriteUri", token.SpriteUri},
{"x", token.X},
{"y", token.Y},
2022-12-07 04:58:42 +00:00
}}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
2022-12-07 04:58:42 +00:00
func (self *DbEngine) GetTokens(table models.TableKey, active bool) ([]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 {
2022-12-07 04:58:42 +00:00
return result.Tokens, nil
} else {
2022-12-07 04:58:42 +00:00
return result.AvailableTokens, nil
}
} else {
return nil, errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
}
}
return nil, errors.New(fmt.Sprintf(errNoCollection, "tables"))
}