backend token logic
This commit is contained in:
parent
f4513a28f7
commit
01fccb55f0
11 changed files with 313 additions and 132 deletions
|
@ -48,8 +48,7 @@ func apiGetTableData(next http.Handler, udb auth.UserStore, dbAdapter mongodb.Db
|
|||
if dbAdapter.CheckTable(tableKey) {
|
||||
mapUrl, _ := dbAdapter.GetMapImageUrl(tableKey)
|
||||
auxMessage, _ := dbAdapter.GetAuxMessage(tableKey)
|
||||
availableTokens, _ := dbAdapter.GetTokens(tableKey, true)
|
||||
activeTokens, _ := dbAdapter.GetTokens(tableKey, false)
|
||||
tokens, _ := dbAdapter.GetTokens(tableKey, true)
|
||||
diceRolls, _ := dbAdapter.GetDiceRolls(tableKey)
|
||||
|
||||
AddContextValue(req, "tableData", models.Table{
|
||||
|
@ -57,8 +56,7 @@ func apiGetTableData(next http.Handler, udb auth.UserStore, dbAdapter mongodb.Db
|
|||
Passcode: tableKey.Passcode,
|
||||
DiceRolls: diceRolls,
|
||||
MapImageUrl: mapUrl,
|
||||
Tokens: activeTokens,
|
||||
AvailableTokens: availableTokens,
|
||||
Tokens: tokens,
|
||||
AuxMessage: auxMessage,
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -192,8 +192,7 @@ func (self *GameTableServer) getCurrentState(tableKey models.TableKey) []byte {
|
|||
if self.dbAdapter.CheckTable(tableKey) {
|
||||
mapUrl, _ := self.dbAdapter.GetMapImageUrl(tableKey)
|
||||
auxMessage, _ := self.dbAdapter.GetAuxMessage(tableKey)
|
||||
availableTokens, _ := self.dbAdapter.GetTokens(tableKey, true)
|
||||
activeTokens, _ := self.dbAdapter.GetTokens(tableKey, false)
|
||||
tokens, _ := self.dbAdapter.GetTokens(tableKey, false)
|
||||
diceRolls, _ := self.dbAdapter.GetDiceRolls(tableKey)
|
||||
|
||||
table := models.Table{
|
||||
|
@ -201,8 +200,7 @@ func (self *GameTableServer) getCurrentState(tableKey models.TableKey) []byte {
|
|||
Passcode: tableKey.Passcode,
|
||||
DiceRolls: diceRolls,
|
||||
MapImageUrl: mapUrl,
|
||||
Tokens: activeTokens,
|
||||
AvailableTokens: availableTokens,
|
||||
Tokens: tokens,
|
||||
AuxMessage: auxMessage,
|
||||
}
|
||||
data, err := json.Marshal(table)
|
||||
|
@ -223,8 +221,41 @@ func (self *GameTableServer) writeToDB(tableMsg *models.TableMessage) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if tableMsg.Token != nil && tableMsg.Token.Id != nil {
|
||||
t := *tableMsg.Token
|
||||
exists, active := self.dbAdapter.CheckToken(key, *t.Id)
|
||||
if exists {
|
||||
if active {
|
||||
if !t.Active {
|
||||
err := self.dbAdapter.ActivateToken(key, *t.Id, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tableMsg.Token.X = nil
|
||||
tableMsg.Token.Y = nil
|
||||
} else if t.X != nil && t.Y != nil {
|
||||
err := self.dbAdapter.MoveToken(key, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if t.Active {
|
||||
err := self.dbAdapter.ActivateToken(key, *t.Id, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// respond to nonextant IDs as if they were destroyed
|
||||
tableMsg.Token.X = nil
|
||||
tableMsg.Token.Y = nil
|
||||
tableMsg.Token.Active = false
|
||||
}
|
||||
}
|
||||
|
||||
// map image change, aux message, and token addition/removal require admin authorization
|
||||
// map image change, aux message, and token creation/deletion require admin authorization
|
||||
if tableMsg.Auth != nil {
|
||||
authorized, _ := self.udb.ValidateToken(*tableMsg.Auth)
|
||||
if authorized {
|
||||
|
@ -240,6 +271,22 @@ func (self *GameTableServer) writeToDB(tableMsg *models.TableMessage) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if tableMsg.Token != nil {
|
||||
t := *tableMsg.Token
|
||||
if t.Id == nil {
|
||||
id, err := self.dbAdapter.CreateToken(key, t)
|
||||
if err == nil {
|
||||
*tableMsg.Token.Id = id
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if t.X == nil && t.Y == nil && !t.Active {
|
||||
err := self.dbAdapter.DestroyToken(key, *t.Id)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
10
go.mod
10
go.mod
|
@ -3,7 +3,7 @@ module hacklab.nilfm.cc/felt
|
|||
go 1.19
|
||||
|
||||
require (
|
||||
go.mongodb.org/mongo-driver v1.11.0
|
||||
go.mongodb.org/mongo-driver v1.12.0
|
||||
golang.org/x/time v0.1.0
|
||||
hacklab.nilfm.cc/quartzgun v0.3.0
|
||||
nhooyr.io/websocket v1.8.7
|
||||
|
@ -15,10 +15,10 @@ require (
|
|||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.1 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
)
|
||||
|
|
30
go.sum
30
go.sum
|
@ -55,6 +55,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
|
@ -68,31 +69,60 @@ github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
|||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
|
||||
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
||||
go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE=
|
||||
go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -18,11 +18,16 @@ type DiceRoll struct {
|
|||
}
|
||||
|
||||
type Token struct {
|
||||
Id string `json:"id"`
|
||||
Id *string `json:"id" bson:"_id"`
|
||||
Name string `json:"name"`
|
||||
SpriteUri string `json:"spriteUrl"`
|
||||
Sprite string `json:"sprite"`
|
||||
W int `json:"w"`
|
||||
H int `json:"h"`
|
||||
OX int `json:"oX"`
|
||||
OY int `json:"oY"`
|
||||
X *int `json:"x"`
|
||||
Y *int `json:"y"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
||||
type Table struct {
|
||||
|
@ -31,7 +36,6 @@ type Table struct {
|
|||
MapImageUrl string `json:"mapImg"`
|
||||
DiceRolls []DiceRoll `json:"diceRolls"`
|
||||
Tokens []Token `json:"tokens"`
|
||||
AvailableTokens []Token `json:"availableTokens"`
|
||||
AuxMessage string `json:"auxMsg"`
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"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"
|
||||
|
@ -14,7 +15,9 @@ import (
|
|||
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"
|
||||
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"
|
||||
|
||||
type DbAdapter interface {
|
||||
Init(mongoUri string) error
|
||||
|
@ -34,10 +37,12 @@ type DbAdapter interface {
|
|||
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)
|
||||
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 {
|
||||
|
@ -284,13 +289,37 @@ func (self *DbEngine) GetAuxMessage(table models.TableKey) (string, error) {
|
|||
return "", errors.New(fmt.Sprintf(errNoCollection, "tables"))
|
||||
}
|
||||
|
||||
func (self *DbEngine) AddToken(table models.TableKey, token models.Token, active bool) error {
|
||||
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 {
|
||||
tokenArrKey := "tokens"
|
||||
if !active {
|
||||
tokenArrKey = "availableTokens"
|
||||
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
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (self *DbEngine) CreateToken(table models.TableKey, token models.Token) (string, error) {
|
||||
tables := self.db.Collection("tables")
|
||||
if tables != nil {
|
||||
var result models.Table
|
||||
err := tables.FindOneAndUpdate(
|
||||
self.mkCtx(10),
|
||||
|
@ -299,7 +328,39 @@ func (self *DbEngine) AddToken(table models.TableKey, token models.Token, active
|
|||
{"passcode", table.Passcode},
|
||||
},
|
||||
bson.D{
|
||||
{"$push", bson.D{{tokenArrKey, token}}},
|
||||
{"$push", bson.D{{"tokens", token}}},
|
||||
},
|
||||
).Decode(&result)
|
||||
if err == nil {
|
||||
newId := result.Tokens[len(result.Tokens)-1].Id
|
||||
return *newId, nil
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return "", errors.New(fmt.Sprintf(errNoCollection, "tables"))
|
||||
|
||||
}
|
||||
|
||||
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},
|
||||
{"tokens", bson.E{"_id", mongoId}},
|
||||
},
|
||||
bson.D{
|
||||
{"$set", bson.D{{"tokens.$", bson.D{
|
||||
{"active", active},
|
||||
}}}},
|
||||
},
|
||||
).Decode(&result)
|
||||
return err
|
||||
|
@ -307,48 +368,23 @@ func (self *DbEngine) AddToken(table models.TableKey, token models.Token, active
|
|||
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
|
||||
}
|
||||
|
||||
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{
|
||||
{"$pull", bson.D{{tokenArrKey, bson.D{{"_id", tokenId}}}}},
|
||||
},
|
||||
).Decode(&result)
|
||||
func (self *DbEngine) MoveToken(table models.TableKey, token models.Token) error {
|
||||
mongoId, err := primitive.ObjectIDFromHex(*token.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
|
||||
}
|
||||
|
||||
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},
|
||||
{tokenArrKey, bson.E{"_id", token.Id}},
|
||||
{"tokens", bson.E{"_id", mongoId}},
|
||||
},
|
||||
bson.D{
|
||||
{"$set", bson.D{{tokenArrKey + ".$", bson.D{
|
||||
{"name", token.Name},
|
||||
{"spriteUri", token.SpriteUri},
|
||||
{"$set", bson.D{{"tokens.$", bson.D{
|
||||
{"x", token.X},
|
||||
{"y", token.Y},
|
||||
}}}},
|
||||
|
@ -359,7 +395,30 @@ func (self *DbEngine) ModifyToken(table models.TableKey, token models.Token, act
|
|||
return errors.New(fmt.Sprintf(errNoCollection, "tables"))
|
||||
}
|
||||
|
||||
func (self *DbEngine) GetTokens(table models.TableKey, active bool) ([]models.Token, error) {
|
||||
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
|
||||
|
@ -370,11 +429,14 @@ func (self *DbEngine) GetTokens(table models.TableKey, active bool) ([]models.To
|
|||
{"passcode", table.Passcode},
|
||||
}).Decode(&result)
|
||||
if err == nil {
|
||||
if active {
|
||||
return result.Tokens, nil
|
||||
} else {
|
||||
return result.AvailableTokens, nil
|
||||
tokens := []models.Token{}
|
||||
for _, t := range result.Tokens {
|
||||
if !activeOnly || t.Active {
|
||||
tokens = append(tokens, t)
|
||||
}
|
||||
|
||||
}
|
||||
return tokens, nil
|
||||
} else {
|
||||
return nil, errors.New(fmt.Sprintf(errNoDocument, table.Name, "tables"))
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ const tokenCY = document.getElementById("token_cy");
|
|||
const previewZone = document.getElementById("tokenPreview_zone");
|
||||
const tokenAspect = document.getElementById("tokenKeepAspect");
|
||||
const aspectLockLabel = document.getElementById("aspectLockLabel");
|
||||
const tokenZone = document.getElementById("tokenZone");
|
||||
|
||||
async function getTable(name, pass) {
|
||||
try {
|
||||
|
@ -41,8 +42,9 @@ async function getTable(name, pass) {
|
|||
document.getElementById("input_table_name").value = name;
|
||||
document.getElementById("input_table_pass").value = pass;
|
||||
dial();
|
||||
const table = await res.json()
|
||||
infoHtml = "<a href='#' onclick='getTables()'>← table list</a><br>";
|
||||
infoHtml += `<textarea id='auxMsgZone'>${(await res.json()).auxMsg}</textarea><br><button onclick='publishAuxMsg()'>Set Status</button>`
|
||||
infoHtml += `<textarea id='auxMsgZone'>${table.auxMsg}</textarea><br><button onclick='publishAuxMsg()'>Set Status</button>`
|
||||
infoHtml += "<button onclick='destroyTable()'>Destroy Table</button><br/>";
|
||||
infoHtml += "<input id='map_img_upload' type='file'/><button onclick='uploadMapImg()'>Upload Map</button><br/>"
|
||||
if (mapImgs.ok) {
|
||||
|
@ -70,18 +72,14 @@ async function getTable(name, pass) {
|
|||
}
|
||||
tokenListHTML += "</ul>";
|
||||
fillSpriteDropdown(tokens);
|
||||
redrawTokenMasterList();
|
||||
} else {
|
||||
tokenListHTML += "<label>Sprites couldn't be retrieved</label>"
|
||||
}
|
||||
|
||||
spriteZone.innerHTML = tokenListHTML;
|
||||
|
||||
|
||||
|
||||
tokenWrapper.style.display = "inline";
|
||||
|
||||
// also, we have to fill and toggle the tokens window
|
||||
|
||||
} else {
|
||||
console.log(res.status);
|
||||
}
|
||||
|
@ -90,6 +88,15 @@ async function getTable(name, pass) {
|
|||
}
|
||||
}
|
||||
|
||||
function redrawTokenMasterList() {
|
||||
if (tokenZone) {
|
||||
const headers = new Headers();
|
||||
headers.set('Authorization', 'Bearer ' + adminToken.access_token);
|
||||
|
||||
const res = await fetch(`/`
|
||||
}
|
||||
}
|
||||
|
||||
function fillSpriteDropdown(tokens) {
|
||||
let options = "<option value=''>select</option>";
|
||||
for (const t of tokens) {
|
||||
|
@ -127,7 +134,6 @@ function toggleAspectLock() {
|
|||
|
||||
function scaleSpritePreview(source) {
|
||||
if (mapImg && mapImg._image) {
|
||||
console.log(mapImg);
|
||||
const scaleFactor = mapImg._image.clientWidth / mapImg._image.naturalWidth;
|
||||
const keepAspect = tokenAspect.checked;
|
||||
const img = previewZone.children[0];
|
||||
|
@ -162,19 +168,20 @@ function drawTokenOrigin() {
|
|||
const img = previewZone.children[0];
|
||||
const x = Number(tokenWidth.value) / Number(tokenCX.value);
|
||||
const y = Number(tokenHeight.value) / Number(tokenCY.value);
|
||||
|
||||
const origin = {x: img.width/x, y: img.height/y};
|
||||
const originImg = document.createElement("img");
|
||||
|
||||
originImg.src="/table/origin.png";
|
||||
originImg.style.position = "absolute";
|
||||
originImg.style.left = (origin.x - 2) + "px";
|
||||
originImg.style.top = (origin.y - 2) + "px";
|
||||
|
||||
if (previewZone.children.length > 1) {
|
||||
previewZone.replaceChild(originImg, previewZone.children[1]);
|
||||
} else {
|
||||
previewZone.appendChild(originImg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function reinitializeSpritePreview() {
|
||||
|
@ -206,24 +213,19 @@ function createToken() {
|
|||
const img = tokenSpriteDropdown[tokenSpriteDropdown.selectedIndex].value;
|
||||
const name = tokenName.value;
|
||||
|
||||
console.log("creating token");
|
||||
if (!isNaN(w) && !isNaN(h) && !isNaN(oX) && !isNaN(oY) && img && name) {
|
||||
console.log("all green");
|
||||
const self = {
|
||||
sz: [w, h],
|
||||
m: L.marker(getCascadingPos(), {
|
||||
icon: L.icon({
|
||||
iconUrl: img,
|
||||
iconSize: [w,h],
|
||||
}),
|
||||
title: name,
|
||||
draggable: true,
|
||||
autoPan: true
|
||||
}),
|
||||
};
|
||||
|
||||
// create on the frontend for testing
|
||||
/*
|
||||
const self = NewToken(w, h, oX, oY, img, name);
|
||||
tokens.push(self);
|
||||
self.m.addTo(map);
|
||||
resizeMarkers();
|
||||
*/
|
||||
|
||||
// really though we have to send it on the websocket and wait for it to come back
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -236,10 +238,19 @@ function publishAuxMsg() {
|
|||
}
|
||||
|
||||
function sendMapImg(url) {
|
||||
console.log("sending " + url);
|
||||
publish({mapImg: url, auth: adminToken.access_token});
|
||||
}
|
||||
|
||||
function sendToken(t) {
|
||||
publish({token: t, auth: adminToken.access_token});
|
||||
}
|
||||
|
||||
function revokeToken(t) {
|
||||
t.x = null;
|
||||
t.y = null;
|
||||
sendToken(t);
|
||||
}
|
||||
|
||||
async function uploadMapImg() {
|
||||
try {
|
||||
var input = document.getElementById("map_img_upload");
|
||||
|
@ -446,5 +457,9 @@ async function createTable() {
|
|||
if (res.ok) {
|
||||
getTables();
|
||||
setTableCreateFormVisible(false);
|
||||
} else if (res.status === 422) {
|
||||
setErr('Table name and passcode must be only alphanumeric and underscores');
|
||||
} else {
|
||||
setErr('Error creating table');
|
||||
}
|
||||
}
|
|
@ -88,7 +88,7 @@
|
|||
<div id="adminWrapper_tokens">
|
||||
<details id="admin_token_win" class="ui_win admin_win"><summary>tokens</summary>
|
||||
<button onclick="setTokenCreateFormVisible(true)">New Token</button>
|
||||
<form onsubmit="return false" id="createTokenForm">
|
||||
<form onsubmit="return false" id="createTokenForm" style="display:none;">
|
||||
<label>Sprite<select id="token_combobox" onchange="previewSprite(this)"></select></label><br/>
|
||||
<label>Name<input id="token_name"/></label><br/>
|
||||
|
||||
|
@ -96,9 +96,9 @@
|
|||
<label>Height<input type="number" id="token_height" min="1" max="9999" onchange="previewSprite(this)"/></label><br/>
|
||||
<label>cX<input type="number" id="token_cx" min="0" max="9999" onchange="previewSprite(this)"/></label><br/>
|
||||
<label>cY<input type="number" id="token_cy" min="0" max="9999" onchange="previewSprite(this)"/></label><br/>
|
||||
<div id="tokenPreview_zone"></div>
|
||||
<button type="submit" onclick="createToken()">Create</button>
|
||||
<button onclick="setTokenCreateFormVisible(false)">Cancel</button>
|
||||
<div id="tokenPreview_zone"></div>
|
||||
</form>
|
||||
<div id="tokenZone"></div>
|
||||
</details><br/>
|
||||
|
|
|
@ -4,7 +4,9 @@ let tokens = [];
|
|||
const worldBounds = [[180, -180],[-180, 180]];
|
||||
|
||||
function initializeMap(mapImgUrl) {
|
||||
let init = false;
|
||||
if (!map) {
|
||||
init = true;
|
||||
map = L.map('map', { minZoom: 0, maxZoom: 4, crs: L.CRS.Simple });
|
||||
map.on("zoomend", ()=>{resizeMarkers();scaleSpritePreview();});
|
||||
}
|
||||
|
@ -14,7 +16,9 @@ function initializeMap(mapImgUrl) {
|
|||
mapImg = L.imageOverlay(mapImgUrl, worldBounds);
|
||||
mapImg.addTo(map);
|
||||
map.setMaxBounds(worldBounds);
|
||||
if (init) {
|
||||
map.setView([0,0], 2);
|
||||
}
|
||||
while (tokens.some(t=>t)) {
|
||||
tokens[0].m.removeFrom(map);
|
||||
tokens.shift();
|
||||
|
@ -39,6 +43,21 @@ function getCascadingPos() {
|
|||
return topLeft;
|
||||
}
|
||||
|
||||
function NewToken(w, h, oX, oY, img, name, x, y) {
|
||||
return {
|
||||
sz: [w, h],
|
||||
m: L.marker((x && y) ? [y,x] : getCascadingPos(), {
|
||||
icon: L.icon({
|
||||
iconUrl: img,
|
||||
iconSize: [w,h],
|
||||
}),
|
||||
title: name,
|
||||
draggable: true,
|
||||
autoPan: true
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function addToken(token) {
|
||||
const self = { sz: token.sz, m: L.marker(token.pos, {
|
||||
icon: L.icon({
|
||||
|
|
|
@ -19,15 +19,17 @@ function fmtLeading(n) {
|
|||
}
|
||||
|
||||
function formatDice(r) {
|
||||
console.log(r);
|
||||
const date = new Date(r.timestamp)
|
||||
const p = document.createElement("p");
|
||||
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
const seconds = date.getSeconds();
|
||||
|
||||
p.innerHTML = `${date.getFullYear()}-${fmtLeading(month)}-${fmtLeading(day)} ${fmtLeading(hours)}:${fmtLeading(minutes)}:${fmtLeading(seconds)} ${r.player} rolled ${r.roll.length}d${r.faces} ${(r.note ? "(" + r.note + ")" : "")}<br>[${r.roll}] (total ${r.roll.reduce((a,c)=>a+c,0)})`;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,10 @@ pre {
|
|||
color: var(--fg_color);
|
||||
}
|
||||
|
||||
.ui_win ul {
|
||||
max-height: 10em;
|
||||
}
|
||||
|
||||
#admin_section {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue