felt/mongodb/adapter.go

448 lines
11 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"
2023-07-08 05:56:41 +00:00
"go.mongodb.org/mongo-driver/bson/primitive"
"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"
2023-07-08 05:56:41 +00:00
const errNotAnArray string = "document property is not an array: %s<key=%s>.%s"
const ErrNotFound string = "this token doesn't exist at this table; forget about it"
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)
2023-07-08 05:56:41 +00:00
CheckToken(table models.TableKey, tokenId string) (bool, bool)
CreateToken(table models.TableKey, token models.Token) (string, error)
ActivateToken(table models.TableKey, tokenId string, active bool) error
MoveToken(table models.TableKey, token models.Token) error
DestroyToken(table models.TableKey, tokenId string) error
GetTokens(table models.TableKey, activeOnly 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"))
}
2023-07-08 05:56:41 +00:00
func (self *DbEngine) CheckToken(table models.TableKey, tokenId string) (bool, bool) {
mongoId, err := primitive.ObjectIDFromHex(tokenId)
if err != nil {
return false, false
}
tables := self.db.Collection("tables")
if tables != nil {
2023-07-08 05:56:41 +00:00
result := models.Table{}
err := tables.FindOne(self.mkCtx(10), bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
{"tokens", bson.E{"_id", mongoId}},
}).Decode(&result)
if err != nil {
return false, false
} else {
active := false
for _, t := range result.Tokens {
if *t.Id == tokenId && t.Active {
active = true
}
}
return true, active
}
2023-07-08 05:56:41 +00:00
}
return false, false
}
func (self *DbEngine) CreateToken(table models.TableKey, token models.Token) (string, error) {
tables := self.db.Collection("tables")
id := primitive.NewObjectID().Hex()
token.Id = &id
2023-07-08 05:56:41 +00:00
if tables != nil {
var result models.Table
err := tables.FindOneAndUpdate(
self.mkCtx(10),
bson.D{
{"name", table.Name},
{"passcode", table.Passcode},
},
bson.D{
2023-07-08 05:56:41 +00:00
{"$push", bson.D{{"tokens", token}}},
},
).Decode(&result)
2023-07-08 05:56:41 +00:00
if err == nil {
return id, err
2023-07-08 05:56:41 +00:00
} else {
return "", err
}
}
2023-07-08 05:56:41 +00:00
return "", errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
2023-07-08 05:56:41 +00:00
func (self *DbEngine) ActivateToken(table models.TableKey, tokenId string, active bool) error {
mongoId, err := primitive.ObjectIDFromHex(tokenId)
if err != nil {
return err
}
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},
2023-07-08 05:56:41 +00:00
{"tokens", bson.E{"_id", mongoId}},
},
bson.D{
2023-07-08 05:56:41 +00:00
{"$set", bson.D{{"tokens.$", bson.D{
{"active", active},
}}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
2023-07-08 05:56:41 +00:00
func (self *DbEngine) MoveToken(table models.TableKey, token models.Token) error {
mongoId, err := primitive.ObjectIDFromHex(*token.Id)
if err != nil {
return err
}
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},
2023-07-08 05:56:41 +00:00
{"tokens", bson.E{"_id", mongoId}},
},
bson.D{
2023-07-08 05:56:41 +00:00
{"$set", bson.D{{"tokens.$", bson.D{
{"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"))
}
2023-07-08 05:56:41 +00:00
func (self *DbEngine) DestroyToken(table models.TableKey, tokenId string) error {
mongoId, err := primitive.ObjectIDFromHex(tokenId)
if err != nil {
return err
}
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{
{"$pull", bson.D{{"tokens", bson.D{{"_id", mongoId}}}}},
},
).Decode(&result)
return err
}
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
}
func (self *DbEngine) GetTokens(table models.TableKey, activeOnly 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 {
2023-07-08 05:56:41 +00:00
tokens := []models.Token{}
for _, t := range result.Tokens {
if !activeOnly || t.Active {
tokens = append(tokens, t)
}
}
2023-07-08 05:56:41 +00:00
return tokens, nil
} else {
return nil, errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
}
}
return nil, errors.New(fmt.Sprintf(errNoCollection, "tables"))
}