New rewrite with svelte and pocketbase
This commit is contained in:
parent
72bfc2ed89
commit
160617af60
95 changed files with 4402 additions and 0 deletions
295
backend/cache.go
Normal file
295
backend/cache.go
Normal file
|
@ -0,0 +1,295 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
type CacheBrawlsetListItem struct {
|
||||
Name string
|
||||
SanitizedName string
|
||||
IconsSvgUri []string
|
||||
}
|
||||
|
||||
type CacheCarteListItem struct {
|
||||
Name string
|
||||
Url string
|
||||
Layout string
|
||||
SmallImage string
|
||||
SmallImageBack string
|
||||
NormalImage string
|
||||
NormalImageBack string
|
||||
Price float64
|
||||
CardmarketUri string
|
||||
NumberOfDecks int
|
||||
NumberOfPossibleDecks int
|
||||
PercentageOfDecks float64
|
||||
Synergy float64
|
||||
}
|
||||
|
||||
type CacheCarteListItemWithSynergy struct {
|
||||
MainCard CacheCarteListItem
|
||||
CanBeCommander bool
|
||||
Cards map[string][]CacheCarteListItem
|
||||
}
|
||||
|
||||
type CacheCarteSearch struct {
|
||||
Name string
|
||||
Url string
|
||||
SetName string
|
||||
}
|
||||
|
||||
type CacheBrawlsetData struct {
|
||||
Name string
|
||||
SanitizedName string
|
||||
Cards map[string][]CacheCarteListItem
|
||||
}
|
||||
|
||||
func (app *application) SetupCache() {
|
||||
app.pb.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
GenerateCache(e.App)
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func GenerateCache(pb core.App) {
|
||||
log.Println("Creating json data cache...")
|
||||
defer timer("Generating cache")()
|
||||
var totalSize int64
|
||||
|
||||
brawlsets := []Brawlset{}
|
||||
mtgSetsQuery := []MtgSet{}
|
||||
mtgSets := map[string]MtgSet{}
|
||||
cardsQuery := []Carte{}
|
||||
cards := map[string]Carte{}
|
||||
cacheCardsSearch := []CacheCarteSearch{}
|
||||
cardsBySet := map[string][]Carte{}
|
||||
decks := []Deck{}
|
||||
decksByBset := map[string][]Deck{}
|
||||
|
||||
err := pb.DB().
|
||||
NewQuery("SELECT * FROM brawlset").
|
||||
All(&brawlsets)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
||||
}
|
||||
|
||||
err = pb.DB().
|
||||
NewQuery("SELECT * FROM mtg_set").
|
||||
All(&mtgSetsQuery)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
||||
}
|
||||
|
||||
err = pb.DB().
|
||||
NewQuery("SELECT * FROM deck").
|
||||
All(&decks)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
||||
}
|
||||
|
||||
for _, v := range decks {
|
||||
decksByBset[v.Brawlset] = append(decksByBset[v.Brawlset], v)
|
||||
}
|
||||
|
||||
err = pb.DB().
|
||||
NewQuery("SELECT * FROM carte").
|
||||
All(&cardsQuery)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
||||
}
|
||||
|
||||
for _, v := range mtgSetsQuery {
|
||||
mtgSets[v.ID] = v
|
||||
}
|
||||
|
||||
for _, v := range cardsQuery {
|
||||
cards[v.ID] = v
|
||||
cardsBySet[v.MtgSet] = append(cardsBySet[v.MtgSet], v)
|
||||
cacheCardsSearch = append(cacheCardsSearch, CacheCarteSearch{ Name: v.Name, Url: fmt.Sprintf("/card/%s-%s", v.SetCode,v.SanitizedName), SetName: mtgSets[v.MtgSet].Name})
|
||||
}
|
||||
|
||||
totalSize += int64(unsafe.Sizeof(cacheCardsSearch))
|
||||
pb.Store().Set("searchData", cacheCardsSearch)
|
||||
|
||||
cacheBrawlsetList := []CacheBrawlsetListItem{}
|
||||
for _, v := range brawlsets {
|
||||
setIconList := []string{}
|
||||
numberOfDecksPerColorIdentity := map[string]int{}
|
||||
cacheBrawlsetData := CacheBrawlsetData{Name: v.Name, SanitizedName: v.SanitizedName, Cards: map[string][]CacheCarteListItem{}}
|
||||
numberOfDecksPerCard := map[string]int{}
|
||||
synergyPerCards := map[string]map[string]int{}
|
||||
|
||||
for _, d := range decksByBset[v.ID] {
|
||||
|
||||
possibleColorIdentities := GetAllColorCombination(d.ColorIdentity)
|
||||
for _, color := range possibleColorIdentities {
|
||||
if _, ok := numberOfDecksPerColorIdentity[color]; ok {
|
||||
numberOfDecksPerColorIdentity[color]++
|
||||
} else {
|
||||
numberOfDecksPerColorIdentity[color] += 1
|
||||
}
|
||||
}
|
||||
// Increment number of deck for commander
|
||||
if _, ok := numberOfDecksPerCard[fmt.Sprintf("c-%s",d.Commander)]; ok {
|
||||
numberOfDecksPerCard[fmt.Sprintf("c-%s",d.Commander)]++
|
||||
} else {
|
||||
numberOfDecksPerCard[fmt.Sprintf("c-%s",d.Commander)] = 1
|
||||
}
|
||||
|
||||
// Increment number of deck for each card
|
||||
for _, c := range d.Cards {
|
||||
if _, ok := synergyPerCards[fmt.Sprintf("c-%s",d.Commander)]; !ok {
|
||||
synergyPerCards[fmt.Sprintf("c-%s", d.Commander)] = map[string]int{}
|
||||
}
|
||||
if _, ok := synergyPerCards[fmt.Sprintf("c-%s",d.Commander)][c.ID]; ok {
|
||||
synergyPerCards[fmt.Sprintf("c-%s",d.Commander)][c.ID]++
|
||||
} else {
|
||||
synergyPerCards[fmt.Sprintf("c-%s",d.Commander)][c.ID] = 1
|
||||
}
|
||||
|
||||
// Add number of decks per card
|
||||
if _, ok := numberOfDecksPerCard[c.ID]; ok {
|
||||
numberOfDecksPerCard[c.ID]++
|
||||
} else {
|
||||
numberOfDecksPerCard[c.ID] = 1
|
||||
}
|
||||
|
||||
// Add number of decks with the two same cards for synergy
|
||||
for _, tc := range d.Cards {
|
||||
if _, ok := synergyPerCards[c.ID]; !ok {
|
||||
synergyPerCards[c.ID] = map[string]int{}
|
||||
}
|
||||
|
||||
if _, ok := synergyPerCards[c.ID][tc.ID]; ok {
|
||||
synergyPerCards[c.ID][tc.ID]++
|
||||
} else {
|
||||
synergyPerCards[c.ID][tc.ID] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range v.Sets {
|
||||
setIconList = append(setIconList, mtgSets[s].IconUri)
|
||||
for _, c := range cardsBySet[s] {
|
||||
obj := CreateCardData(c, decksByBset, numberOfDecksPerColorIdentity, numberOfDecksPerCard, v.ID)
|
||||
cacheBrawlsetData.Cards[c.CardType] = append(cacheBrawlsetData.Cards[c.CardType], obj)
|
||||
|
||||
if c.CanBeCommander {
|
||||
obj.NumberOfDecks = numberOfDecksPerCard[fmt.Sprintf("c-%s",c.ID)]
|
||||
obj.Url = fmt.Sprintf("/commander/%s-%s", c.SetCode,c.SanitizedName)
|
||||
cacheBrawlsetData.Cards["commander"] = append(cacheBrawlsetData.Cards["commander"], obj)
|
||||
|
||||
detailsObj := CacheCarteListItemWithSynergy{
|
||||
MainCard: obj,
|
||||
CanBeCommander: true,
|
||||
Cards: map[string][]CacheCarteListItem{},
|
||||
}
|
||||
|
||||
// Add each card that already appeared in a deck
|
||||
for k := range synergyPerCards[fmt.Sprintf("c-%s",c.ID)] {
|
||||
synergyObj := CreateCardData(cards[k], decksByBset, numberOfDecksPerColorIdentity, numberOfDecksPerCard, v.ID)
|
||||
|
||||
synergy := 0 - synergyObj.PercentageOfDecks
|
||||
if numberOfDecksPerCard[fmt.Sprintf("c-%s",c.ID)] != 0 {
|
||||
synergy = (float64(synergyPerCards[fmt.Sprintf("c-%s",c.ID)][k]) / float64(numberOfDecksPerCard[fmt.Sprintf("c-%s",c.ID)])) - synergyObj.PercentageOfDecks
|
||||
}
|
||||
synergyObj.Synergy = synergy
|
||||
|
||||
detailsObj.Cards[cards[k].CardType] = append(detailsObj.Cards[cards[k].CardType], synergyObj)
|
||||
}
|
||||
|
||||
for k := range detailsObj.Cards {
|
||||
sort.Slice(detailsObj.Cards[k], func(i, j int) bool {
|
||||
if detailsObj.Cards[k][i].Synergy == detailsObj.Cards[k][j].Synergy {
|
||||
return detailsObj.Cards[k][i].PercentageOfDecks > detailsObj.Cards[k][j].PercentageOfDecks
|
||||
}
|
||||
return detailsObj.Cards[k][i].Synergy > detailsObj.Cards[k][j].Synergy
|
||||
})
|
||||
}
|
||||
|
||||
totalSize += int64(unsafe.Sizeof(detailsObj))
|
||||
pb.Store().Set(fmt.Sprintf("json/commander/%s-%s", c.SetCode, c.SanitizedName), detailsObj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range cacheBrawlsetData.Cards {
|
||||
if k == "commander" {
|
||||
sort.Slice(cacheBrawlsetData.Cards[k], func(i, j int) bool { return cacheBrawlsetData.Cards[k][i].NumberOfDecks > cacheBrawlsetData.Cards[k][j].NumberOfDecks})
|
||||
} else {
|
||||
sort.Slice(cacheBrawlsetData.Cards[k], func(i, j int) bool {
|
||||
if cacheBrawlsetData.Cards[k][i].PercentageOfDecks == cacheBrawlsetData.Cards[k][j].PercentageOfDecks {
|
||||
return cacheBrawlsetData.Cards[k][i].NumberOfDecks > cacheBrawlsetData.Cards[k][j].NumberOfDecks
|
||||
}
|
||||
return cacheBrawlsetData.Cards[k][i].PercentageOfDecks > cacheBrawlsetData.Cards[k][j].PercentageOfDecks
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
cacheBrawlsetList = append(cacheBrawlsetList, CacheBrawlsetListItem{Name: v.Name, SanitizedName: v.SanitizedName, IconsSvgUri: setIconList})
|
||||
|
||||
totalSize += int64(unsafe.Sizeof(cacheBrawlsetData))
|
||||
pb.Store().Set("json/brawlset/" + v.SanitizedName, cacheBrawlsetData)
|
||||
}
|
||||
|
||||
totalSize += int64(unsafe.Sizeof(cacheBrawlsetList))
|
||||
pb.Store().Set("json/misc/brawlsets", cacheBrawlsetList)
|
||||
|
||||
log.Println(fmt.Sprintf("Total cache size : %d", totalSize))
|
||||
}
|
||||
|
||||
func GetAllColorCombination(s []string) []string {
|
||||
res := []string{strings.Join(s,"")}
|
||||
for i := 1; i < len(s); i++ {
|
||||
combinations := CreateCombination(s, i)
|
||||
res = append(res, combinations...)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func CreateCardData(c Carte, decksByBset map[string][]Deck, numberOfDecksPerColorIdentity map[string]int, numberOfDecksPerCard map[string]int, bsetID string) CacheCarteListItem {
|
||||
price, err := strconv.ParseFloat(c.Price, 64)
|
||||
if err != nil {
|
||||
price = 0.0
|
||||
}
|
||||
|
||||
numberOfPossibleDecks := 0
|
||||
if len(c.ColorIdentity) == 0 {
|
||||
numberOfPossibleDecks = len(decksByBset[bsetID])
|
||||
} else {
|
||||
numberOfPossibleDecks = numberOfDecksPerColorIdentity[strings.Join(c.ColorIdentity,"")]
|
||||
}
|
||||
|
||||
percentageOfDecks := 0.0
|
||||
if numberOfPossibleDecks != 0 {
|
||||
percentageOfDecks = float64(numberOfDecksPerCard[c.ID]) / float64(numberOfPossibleDecks)
|
||||
}
|
||||
|
||||
return CacheCarteListItem{
|
||||
Name: c.Name,
|
||||
Url: fmt.Sprintf("/card/%s-%s", c.SetCode,c.SanitizedName),
|
||||
Layout: c.Layout,
|
||||
SmallImage: c.SmallImage,
|
||||
SmallImageBack: c.SmallImageBack,
|
||||
NormalImage: c.NormalImage,
|
||||
NormalImageBack: c.NormalImageBack,
|
||||
Price: price,
|
||||
CardmarketUri: c.CardmarketUri,
|
||||
NumberOfDecks: numberOfDecksPerCard[c.ID],
|
||||
NumberOfPossibleDecks: numberOfPossibleDecks,
|
||||
PercentageOfDecks: percentageOfDecks,
|
||||
}
|
||||
}
|
70
backend/crons.go
Normal file
70
backend/crons.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (app *application) SetupCrons() {
|
||||
app.pb.Cron().MustAdd("update_sets_and_cards", "0 3 * * *", func() {
|
||||
log.Println("Started updating sets and cards...")
|
||||
|
||||
scryfallSets := fetchApiSets()
|
||||
|
||||
insertQuery := CreateBulkSetsInsertQuery(scryfallSets)
|
||||
_, err := app.pb.DB().
|
||||
NewQuery(insertQuery).
|
||||
Execute()
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v",err))
|
||||
}
|
||||
log.Println(fmt.Sprintf("Updated %d sets", len(scryfallSets)))
|
||||
|
||||
setsCodesQuery := []MtgSet{}
|
||||
err = app.pb.DB().
|
||||
NewQuery("SELECT id, code FROM mtg_set").
|
||||
All(&setsCodesQuery)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v",err))
|
||||
}
|
||||
|
||||
setsCodes := map[string]string{}
|
||||
for _,v := range setsCodesQuery {
|
||||
setsCodes[v.ID] = v.Code
|
||||
}
|
||||
|
||||
selectedSets := []Brawlset{}
|
||||
selectedSetsCodes := []string{}
|
||||
err = app.pb.DB().
|
||||
NewQuery("SELECT sets FROM brawlset").
|
||||
All(&selectedSets)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v",err))
|
||||
}
|
||||
for _, v := range selectedSets {
|
||||
for _, set := range v.Sets {
|
||||
selectedSetsCodes = append(selectedSetsCodes, setsCodes[set])
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(fmt.Sprintf("Fetching %d sets...", len(selectedSetsCodes)))
|
||||
allCards := []ScryfallCard{}
|
||||
for _, v := range selectedSetsCodes {
|
||||
url := "https://api.scryfall.com/cards/search?q=(game%3Apaper)+set%3A" + v
|
||||
allCards = fetchApiCards(url, allCards)
|
||||
}
|
||||
|
||||
upsertQuery := CreateBulkCardsUpsertQuery(allCards)
|
||||
_, err = app.pb.DB().
|
||||
NewQuery(upsertQuery).
|
||||
Execute()
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("[ERROR] %v",err))
|
||||
}
|
||||
log.Println(fmt.Sprintf("Updated %d cards", len(allCards)))
|
||||
})
|
||||
|
||||
app.pb.Cron().MustAdd("regenerate_cache_json", "30 3 * * *", func() {
|
||||
GenerateCache(app.pb.App)
|
||||
})
|
||||
}
|
BIN
backend/custom_pocketbase
Executable file
BIN
backend/custom_pocketbase
Executable file
Binary file not shown.
47
backend/go.mod
Normal file
47
backend/go.mod
Normal file
|
@ -0,0 +1,47 @@
|
|||
module brawlset
|
||||
|
||||
go 1.24.1
|
||||
|
||||
require (
|
||||
github.com/labstack/echo v3.3.10+incompatible
|
||||
github.com/pocketbase/pocketbase v0.26.6
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/ganigeorgiev/fexpr v0.4.1 // indirect
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.27 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/pocketbase/dbx v1.11.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/cobra v1.9.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/image v0.25.0 // indirect
|
||||
golang.org/x/net v0.37.0 // indirect
|
||||
golang.org/x/oauth2 v0.28.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
modernc.org/libc v1.61.13 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.8.2 // indirect
|
||||
modernc.org/sqlite v1.36.3 // indirect
|
||||
)
|
164
backend/go.sum
Normal file
164
backend/go.sum
Normal file
|
@ -0,0 +1,164 @@
|
|||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8=
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/ganigeorgiev/fexpr v0.4.1 h1:hpUgbUEEWIZhSDBtf4M9aUNfQQ0BZkGRaMePy7Gcx5k=
|
||||
github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
|
||||
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU=
|
||||
github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU=
|
||||
github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
|
||||
github.com/pocketbase/pocketbase v0.26.6 h1:ya+D2QK5DP3ynntCEJPj5Sc6hl9KZ+ZsfxVKp9UCB4o=
|
||||
github.com/pocketbase/pocketbase v0.26.6/go.mod h1:Pd+NfdYGBHXJOi9OI5WHS/Shn7J0iDSv5rNcCZ93LJM=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
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.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
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/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
||||
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
|
||||
modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
|
||||
modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
|
||||
modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=
|
||||
modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.36.3 h1:qYMYlFR+rtLDUzuXoST1SDIdEPbX8xzuhdF90WsX1ss=
|
||||
modernc.org/sqlite v1.36.3/go.mod h1:ADySlx7K4FdY5MaJcEv86hTJ0PjedAloTUuif0YS3ws=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
52
backend/main.go
Normal file
52
backend/main.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"log"
|
||||
|
||||
"github.com/pocketbase/pocketbase"
|
||||
)
|
||||
|
||||
// Copied from https://github.com/s-petr/longhabit/blob/main/backend/main.go
|
||||
|
||||
// application holds the core application state and configuration.
|
||||
type application struct {
|
||||
pb *pocketbase.PocketBase
|
||||
config appConfig
|
||||
}
|
||||
|
||||
// appConfig holds the application's configuration settings.
|
||||
type appConfig struct {
|
||||
dbDir string
|
||||
}
|
||||
|
||||
// newApplication creates and initializes a new application instance.
|
||||
func newApplication() *application {
|
||||
dbDir := getEnvOrDefault("DB_DIR", "pb_data")
|
||||
|
||||
return &application{
|
||||
pb: pocketbase.NewWithConfig(pocketbase.Config{DefaultDataDir: dbDir}),
|
||||
config: appConfig{
|
||||
dbDir: dbDir,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := newApplication()
|
||||
|
||||
app.SetupCache()
|
||||
app.SetupCrons()
|
||||
app.SetupRoutes()
|
||||
|
||||
log.Fatal(app.pb.Start())
|
||||
}
|
||||
|
||||
// getEnvOrDefault retrieves the value of an environment variable by key.
|
||||
// If the environment variable is empty or not set, it returns the defaultValue.
|
||||
func getEnvOrDefault(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
178
backend/pb_migrations/1744049420_created_carte.js
Normal file
178
backend/pb_migrations/1744049420_created_carte.js
Normal file
|
@ -0,0 +1,178 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3273110370",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "sanitized_name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3520360348",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "released_at",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text976907234",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "layout",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1456686396",
|
||||
"name": "small_image",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2615033119",
|
||||
"name": "small_image_back",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2291853061",
|
||||
"name": "normal_image",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2961008824",
|
||||
"name": "normal_image_back",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2363381545",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "type",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "select3054531206",
|
||||
"maxSelect": 2,
|
||||
"name": "color_identity",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "select",
|
||||
"values": [
|
||||
"B",
|
||||
"W",
|
||||
"R",
|
||||
"G",
|
||||
"U"
|
||||
]
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_1905410326",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "carte",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
101
backend/pb_migrations/1744049617_created_set.js
Normal file
101
backend/pb_migrations/1744049617_created_set.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3273110370",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "sanitized_name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1997877400",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "code",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "date3520360348",
|
||||
"max": "",
|
||||
"min": "",
|
||||
"name": "released_at",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url659239397",
|
||||
"name": "icon_uri",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}
|
||||
],
|
||||
"id": "pbc_3912384429",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "set",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
78
backend/pb_migrations/1744049690_created_brawlset.js
Normal file
78
backend/pb_migrations/1744049690_created_brawlset.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3273110370",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "sanitized_name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_3912384429",
|
||||
"hidden": false,
|
||||
"id": "relation2492286417",
|
||||
"maxSelect": 999,
|
||||
"minSelect": 0,
|
||||
"name": "sets",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}
|
||||
],
|
||||
"id": "pbc_749385185",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "brawlset",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_749385185");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
45
backend/pb_migrations/1744049710_updated_carte.js
Normal file
45
backend/pb_migrations/1744049710_updated_carte.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text3520360348")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(10, new Field({
|
||||
"hidden": false,
|
||||
"id": "date3520360348",
|
||||
"max": "",
|
||||
"min": "",
|
||||
"name": "released_at",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "date"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(3, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3520360348",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "released_at",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("date3520360348")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
94
backend/pb_migrations/1744049818_updated_carte.js
Normal file
94
backend/pb_migrations/1744049818_updated_carte.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(11, new Field({
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_3912384429",
|
||||
"hidden": false,
|
||||
"id": "relation3860080092",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "set",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(12, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3805467153",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "set_code",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(13, new Field({
|
||||
"hidden": false,
|
||||
"id": "number3402113753",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "price",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(14, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url518645060",
|
||||
"name": "cardmarket_url",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(15, new Field({
|
||||
"hidden": false,
|
||||
"id": "bool1734659578",
|
||||
"name": "can_be_commander",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "bool"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("relation3860080092")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text3805467153")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("number3402113753")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url518645060")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("bool1734659578")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
140
backend/pb_migrations/1744049951_created_deck.js
Normal file
140
backend/pb_migrations/1744049951_created_deck.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "select3054531206",
|
||||
"maxSelect": 2,
|
||||
"name": "color_identity",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "select",
|
||||
"values": [
|
||||
"B",
|
||||
"R",
|
||||
"G",
|
||||
"U",
|
||||
"W"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "_pb_users_auth_",
|
||||
"hidden": false,
|
||||
"id": "relation3479234172",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "owner",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_1905410326",
|
||||
"hidden": false,
|
||||
"id": "relation3635975509",
|
||||
"maxSelect": 999,
|
||||
"minSelect": 0,
|
||||
"name": "cartes",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_1905410326",
|
||||
"hidden": false,
|
||||
"id": "relation1121130682",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "commander",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_749385185",
|
||||
"hidden": false,
|
||||
"id": "relation1826942456",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "brawlset",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_1755402631",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "deck",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
42
backend/pb_migrations/1744049967_updated_brawlset.js
Normal file
42
backend/pb_migrations/1744049967_updated_brawlset.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_749385185")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": true,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_749385185")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
74
backend/pb_migrations/1744049979_updated_carte.js
Normal file
74
backend/pb_migrations/1744049979_updated_carte.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": true,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(12, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3805467153",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "set_code",
|
||||
"pattern": "",
|
||||
"presentable": true,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(12, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3805467153",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "set_code",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
42
backend/pb_migrations/1744049986_updated_deck.js
Normal file
42
backend/pb_migrations/1744049986_updated_deck.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": true,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
42
backend/pb_migrations/1744049999_updated_set.js
Normal file
42
backend/pb_migrations/1744049999_updated_set.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": true,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
28
backend/pb_migrations/1744051259_updated_set.js
Normal file
28
backend/pb_migrations/1744051259_updated_set.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"createRule": "",
|
||||
"deleteRule": "",
|
||||
"listRule": "",
|
||||
"updateRule": "",
|
||||
"viewRule": ""
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"listRule": null,
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
20
backend/pb_migrations/1744119600_updated_set.js
Normal file
20
backend/pb_migrations/1744119600_updated_set.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"name": "mtg_set"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"name": "set"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
42
backend/pb_migrations/1744119800_updated_deck.js
Normal file
42
backend/pb_migrations/1744119800_updated_deck.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(0, new Field({
|
||||
"autogeneratePattern": "[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 36,
|
||||
"min": 36,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9\\-]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(0, new Field({
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
42
backend/pb_migrations/1744119839_updated_mtg_set.js
Normal file
42
backend/pb_migrations/1744119839_updated_mtg_set.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(0, new Field({
|
||||
"autogeneratePattern": "[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 36,
|
||||
"min": 36,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9\\-]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(0, new Field({
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
29
backend/pb_migrations/1744125643_updated_mtg_set.js
Normal file
29
backend/pb_migrations/1744125643_updated_mtg_set.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(6, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2363381545",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "type",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text2363381545")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
42
backend/pb_migrations/1744126008_updated_mtg_set.js
Normal file
42
backend/pb_migrations/1744126008_updated_mtg_set.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(6, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2363381545",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "type",
|
||||
"pattern": "",
|
||||
"presentable": true,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3912384429")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(6, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2363381545",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "type",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
95
backend/pb_migrations/1744128064_created_posts.js
Normal file
95
backend/pb_migrations/1744128064_created_posts.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text724990059",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "title",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "_pb_users_auth_",
|
||||
"hidden": false,
|
||||
"id": "relation3182418120",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "author",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"convertURLs": false,
|
||||
"hidden": false,
|
||||
"id": "editor37359206",
|
||||
"maxSize": 0,
|
||||
"name": "article",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "editor"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_1125843985",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "posts",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1125843985");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
95
backend/pb_migrations/1744128183_deleted_posts.js
Normal file
95
backend/pb_migrations/1744128183_deleted_posts.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1125843985");
|
||||
|
||||
return app.delete(collection);
|
||||
}, (app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text724990059",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "title",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "_pb_users_auth_",
|
||||
"hidden": false,
|
||||
"id": "relation3182418120",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "author",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"convertURLs": false,
|
||||
"hidden": false,
|
||||
"id": "editor37359206",
|
||||
"maxSize": 0,
|
||||
"name": "article",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "editor"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_1125843985",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "posts",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
})
|
42
backend/pb_migrations/1744133653_updated_carte.js
Normal file
42
backend/pb_migrations/1744133653_updated_carte.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(0, new Field({
|
||||
"autogeneratePattern": "[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 36,
|
||||
"min": 36,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9\\-]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(0, new Field({
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
40
backend/pb_migrations/1744140479_updated_carte.js
Normal file
40
backend/pb_migrations/1744140479_updated_carte.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(11, new Field({
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_3912384429",
|
||||
"hidden": false,
|
||||
"id": "relation3860080092",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "mtg_set",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// update field
|
||||
collection.fields.addAt(11, new Field({
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_3912384429",
|
||||
"hidden": false,
|
||||
"id": "relation3860080092",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "set",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
25
backend/pb_migrations/1744149166_updated_carte.js
Normal file
25
backend/pb_migrations/1744149166_updated_carte.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("autodate3332085495")
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1905410326")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(16, new Field({
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
})
|
28
backend/pb_migrations/1744150791_updated_deck.js
Normal file
28
backend/pb_migrations/1744150791_updated_deck.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"createRule": "@request.auth.id != \"\"",
|
||||
"deleteRule": "owner ?= @request.auth.id",
|
||||
"listRule": "owner ?= @request.auth.id",
|
||||
"updateRule": "owner ?= @request.auth.id",
|
||||
"viewRule": "owner ?= @request.auth.id"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1755402631")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"listRule": null,
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
176
backend/routes.go
Normal file
176
backend/routes.go
Normal file
|
@ -0,0 +1,176 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"os"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
)
|
||||
|
||||
const frontEndDevPort = "5173"
|
||||
const frontEndProdPort = "3000"
|
||||
|
||||
type DeckImportCard struct {
|
||||
Name string `json:"name"`
|
||||
Amount int `json:"amount"`
|
||||
}
|
||||
|
||||
|
||||
type DeckImport struct {
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
SelectedBset string `json:"selected_bset"`
|
||||
Commander string `json:"commander_name"`
|
||||
Cards []DeckImportCard `json:"cards"`
|
||||
}
|
||||
|
||||
func (app *application) SetupRoutes() {
|
||||
app.pb.OnServe().BindFunc(func(se *core.ServeEvent) error {
|
||||
mode := os.Getenv("GO_ENV")
|
||||
path := ""
|
||||
if mode == "" {
|
||||
log.Fatal("You must the env variable GO_ENV to either 'dev' or 'production'")
|
||||
}
|
||||
|
||||
if mode == "dev" {
|
||||
path = fmt.Sprintf("http://localhost:%s", frontEndDevPort)
|
||||
} else if mode == "production" {
|
||||
path = fmt.Sprintf("http://localhost:%s", frontEndProdPort)
|
||||
} else {
|
||||
log.Fatal(fmt.Sprintf("Error, unrecognized GO_ENV : %s\nSet it to either 'dev' or 'production'", mode))
|
||||
}
|
||||
|
||||
target, err := url.Parse(path)
|
||||
if err != nil {
|
||||
log.Println("[ERROR] failed to parse proxy target URL: %w", err)
|
||||
}
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(target)
|
||||
|
||||
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, fmt.Sprintf("proxy error: %v", err), http.StatusBadGateway)
|
||||
}
|
||||
|
||||
// Cache Route
|
||||
se.Router.GET("/json/{path...}", func(re *core.RequestEvent) error {
|
||||
path := fmt.Sprintf("json/%s",re.Request.PathValue("path"))
|
||||
|
||||
cacheVal := app.pb.Store().Get(path)
|
||||
if cacheVal != nil {
|
||||
return re.JSON(http.StatusOK, cacheVal)
|
||||
} else {
|
||||
return re.JSON(http.StatusNotFound, map[string]string{"message": "json not found in cache"})
|
||||
}
|
||||
})
|
||||
|
||||
// Search API
|
||||
se.Router.GET("/api/search", func(re *core.RequestEvent) error {
|
||||
searchData := app.pb.Store().Get("searchData").([]CacheCarteSearch)
|
||||
search := re.Request.URL.Query().Get("q")
|
||||
|
||||
resultData := filter(searchData, func(card CacheCarteSearch) bool { return strings.Contains(strings.ToLower(card.Name), strings.ToLower(search)) })
|
||||
return re.JSON(http.StatusOK, resultData)
|
||||
})
|
||||
|
||||
// Create deck API
|
||||
se.Router.POST("/api/deck/create", func(re *core.RequestEvent) error {
|
||||
authRecord := re.Auth
|
||||
|
||||
data := DeckImport{}
|
||||
if err := re.BindBody(&data); err != nil {
|
||||
log.Println(err)
|
||||
return re.BadRequestError("Failed to read request data", err)
|
||||
}
|
||||
|
||||
selectedBrawlset := Brawlset{}
|
||||
err := app.pb.DB().
|
||||
NewQuery(fmt.Sprintf("SELECT id, sets FROM brawlset WHERE sanitized_name = '%v'", data.SelectedBset)).
|
||||
One(&selectedBrawlset)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return re.BadRequestError("No brawlsets with this id", err)
|
||||
}
|
||||
|
||||
possibleCards := []Carte{}
|
||||
setsIds := []string{}
|
||||
for _, v := range selectedBrawlset.Sets {
|
||||
setsIds = append(setsIds, fmt.Sprintf("'%s'", v))
|
||||
}
|
||||
query := ""
|
||||
if len(selectedBrawlset.Sets) > 1 {
|
||||
query = fmt.Sprintf("SELECT id, name, color_identity FROM carte WHERE mtg_set IN (%s)", strings.Join(setsIds, ", "))
|
||||
} else {
|
||||
query = fmt.Sprintf("SELECT id, name, color_identity FROM carte WHERE mtg_set = %s", setsIds[0])
|
||||
}
|
||||
err = app.pb.DB().
|
||||
NewQuery(query).
|
||||
All(&possibleCards)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return re.BadRequestError("Error with cards query", err)
|
||||
}
|
||||
|
||||
collection, err := app.pb.FindCollectionByNameOrId("deck")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("name", data.Name)
|
||||
record.Set("url", data.Url)
|
||||
record.Set("brawlset", selectedBrawlset.ID)
|
||||
record.Set("owner", authRecord.Id)
|
||||
|
||||
for _, c := range possibleCards {
|
||||
if data.Commander == strings.Split(c.Name, " // ")[0] {
|
||||
record.Set("commander", c.ID)
|
||||
record.Set("color_identity", c.ColorIdentity)
|
||||
}
|
||||
}
|
||||
|
||||
cardInDeck := []DeckCard{}
|
||||
for _, v := range data.Cards {
|
||||
cardId := ""
|
||||
for _, c := range possibleCards {
|
||||
if v.Name == strings.Split(c.Name, " // ")[0] {
|
||||
cardId = c.ID
|
||||
}
|
||||
}
|
||||
if cardId == "" {
|
||||
log.Println(fmt.Sprintf("Card not found : %s",v.Name))
|
||||
}
|
||||
cardInDeck = append(cardInDeck, DeckCard{ID: cardId, Amount: v.Amount})
|
||||
}
|
||||
record.Set("cartes", cardInDeck)
|
||||
|
||||
err = app.pb.Save(record)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
re.BadRequestError("Problem with creating deck", err)
|
||||
}
|
||||
return re.JSON(http.StatusOK, map[string]string{"message": "deck created"})
|
||||
}).Bind(apis.RequireAuth())
|
||||
|
||||
// Proxy to svelte app
|
||||
se.Router.Any("/{path...}", func(re *core.RequestEvent) error {
|
||||
proxy.ServeHTTP(re.Response, re.Request)
|
||||
return nil
|
||||
})
|
||||
|
||||
return se.Next()
|
||||
})
|
||||
}
|
||||
|
||||
func filter(ss []CacheCarteSearch, test func(CacheCarteSearch) bool) (ret []CacheCarteSearch) {
|
||||
for _, s := range ss {
|
||||
if test(s) {
|
||||
ret = append(ret, s)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
252
backend/scryfall_api.go
Normal file
252
backend/scryfall_api.go
Normal file
|
@ -0,0 +1,252 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ScryfallCard struct {
|
||||
Object string `json:"object"`
|
||||
ID string `json:"id"`
|
||||
OracleID string `json:"oracle_id"`
|
||||
MultiverseIds []int `json:"multiverse_ids"`
|
||||
MtgoID int `json:"mtgo_id"`
|
||||
MtgoFoilID int `json:"mtgo_foil_id"`
|
||||
TcgplayerID int `json:"tcgplayer_id"`
|
||||
CardmarketID int `json:"cardmarket_id"`
|
||||
Name string `json:"name"`
|
||||
Lang string `json:"lang"`
|
||||
ReleasedAt string `json:"released_at"`
|
||||
URI string `json:"uri"`
|
||||
ScryfallURI string `json:"scryfall_uri"`
|
||||
Layout string `json:"layout"`
|
||||
HighresImage bool `json:"highres_image"`
|
||||
ImageStatus string `json:"image_status"`
|
||||
ImageUris struct {
|
||||
Small string `json:"small"`
|
||||
Normal string `json:"normal"`
|
||||
Large string `json:"large"`
|
||||
Png string `json:"png"`
|
||||
ArtCrop string `json:"art_crop"`
|
||||
BorderCrop string `json:"border_crop"`
|
||||
} `json:"image_uris"`
|
||||
CardFaces []struct {
|
||||
Object string `json:"object"`
|
||||
Name string `json:"name"`
|
||||
ManaCost string `json:"mana_cost"`
|
||||
TypeLine string `json:"type_line"`
|
||||
OracleText string `json:"oracle_text"`
|
||||
Colors []string `json:"colors"`
|
||||
Power string `json:"power"`
|
||||
Toughness string `json:"toughness"`
|
||||
Artist string `json:"artist"`
|
||||
ArtistID string `json:"artist_id"`
|
||||
IllustrationID string `json:"illustration_id"`
|
||||
ImageUris struct {
|
||||
Small string `json:"small"`
|
||||
Normal string `json:"normal"`
|
||||
Large string `json:"large"`
|
||||
Png string `json:"png"`
|
||||
ArtCrop string `json:"art_crop"`
|
||||
BorderCrop string `json:"border_crop"`
|
||||
} `json:"image_uris"`
|
||||
ColorIndicator []string `json:"color_indicator,omitempty"`
|
||||
} `json:"card_faces"`
|
||||
ManaCost string `json:"mana_cost"`
|
||||
Cmc float32 `json:"cmc"`
|
||||
TypeLine string `json:"type_line"`
|
||||
OracleText string `json:"oracle_text"`
|
||||
Power string `json:"power"`
|
||||
Toughness string `json:"toughness"`
|
||||
Colors []string `json:"colors"`
|
||||
ColorIdentity []string `json:"color_identity"`
|
||||
Keywords []string `json:"keywords"`
|
||||
Legalities struct {
|
||||
Standard string `json:"standard"`
|
||||
Future string `json:"future"`
|
||||
Historic string `json:"historic"`
|
||||
Timeless string `json:"timeless"`
|
||||
Gladiator string `json:"gladiator"`
|
||||
Pioneer string `json:"pioneer"`
|
||||
Explorer string `json:"explorer"`
|
||||
Modern string `json:"modern"`
|
||||
Legacy string `json:"legacy"`
|
||||
Pauper string `json:"pauper"`
|
||||
Vintage string `json:"vintage"`
|
||||
Penny string `json:"penny"`
|
||||
Commander string `json:"commander"`
|
||||
Oathbreaker string `json:"oathbreaker"`
|
||||
Standardbrawl string `json:"standardbrawl"`
|
||||
Brawl string `json:"brawl"`
|
||||
Alchemy string `json:"alchemy"`
|
||||
Paupercommander string `json:"paupercommander"`
|
||||
Duel string `json:"duel"`
|
||||
Oldschool string `json:"oldschool"`
|
||||
Premodern string `json:"premodern"`
|
||||
Predh string `json:"predh"`
|
||||
} `json:"legalities"`
|
||||
Games []string `json:"games"`
|
||||
Reserved bool `json:"reserved"`
|
||||
GameChanger bool `json:"game_changer"`
|
||||
Foil bool `json:"foil"`
|
||||
Nonfoil bool `json:"nonfoil"`
|
||||
Finishes []string `json:"finishes"`
|
||||
Oversized bool `json:"oversized"`
|
||||
Promo bool `json:"promo"`
|
||||
Reprint bool `json:"reprint"`
|
||||
Variation bool `json:"variation"`
|
||||
SetID string `json:"set_id"`
|
||||
Set string `json:"set"`
|
||||
SetName string `json:"set_name"`
|
||||
SetType string `json:"set_type"`
|
||||
SetURI string `json:"set_uri"`
|
||||
SetSearchURI string `json:"set_search_uri"`
|
||||
ScryfallSetURI string `json:"scryfall_set_uri"`
|
||||
RulingsURI string `json:"rulings_uri"`
|
||||
PrintsSearchURI string `json:"prints_search_uri"`
|
||||
CollectorNumber string `json:"collector_number"`
|
||||
Digital bool `json:"digital"`
|
||||
Rarity string `json:"rarity"`
|
||||
CardBackID string `json:"card_back_id"`
|
||||
Artist string `json:"artist"`
|
||||
ArtistIds []string `json:"artist_ids"`
|
||||
IllustrationID string `json:"illustration_id"`
|
||||
BorderColor string `json:"border_color"`
|
||||
Frame string `json:"frame"`
|
||||
FullArt bool `json:"full_art"`
|
||||
Textless bool `json:"textless"`
|
||||
Booster bool `json:"booster"`
|
||||
StorySpotlight bool `json:"story_spotlight"`
|
||||
EdhrecRank int `json:"edhrec_rank"`
|
||||
PennyRank int `json:"penny_rank"`
|
||||
Prices struct {
|
||||
Usd string `json:"usd"`
|
||||
UsdFoil string `json:"usd_foil"`
|
||||
UsdEtched interface{} `json:"usd_etched"`
|
||||
Eur string `json:"eur"`
|
||||
EurFoil string `json:"eur_foil"`
|
||||
Tix string `json:"tix"`
|
||||
} `json:"prices"`
|
||||
RelatedUris struct {
|
||||
Gatherer string `json:"gatherer"`
|
||||
TcgplayerInfiniteArticles string `json:"tcgplayer_infinite_articles"`
|
||||
TcgplayerInfiniteDecks string `json:"tcgplayer_infinite_decks"`
|
||||
Edhrec string `json:"edhrec"`
|
||||
} `json:"related_uris"`
|
||||
PurchaseUris struct {
|
||||
Tcgplayer string `json:"tcgplayer"`
|
||||
Cardmarket string `json:"cardmarket"`
|
||||
Cardhoarder string `json:"cardhoarder"`
|
||||
} `json:"purchase_uris"`
|
||||
}
|
||||
|
||||
type ScryfallCardAPI struct {
|
||||
Object string `json:"object"`
|
||||
TotalCards int `json:"total_cards"`
|
||||
HasMore bool `json:"has_more"`
|
||||
NextPage string `json:"next_page"`
|
||||
Data []ScryfallCard `json:"data"`
|
||||
}
|
||||
|
||||
type ScryfallSet struct {
|
||||
Object string `json:"object"`
|
||||
ID string `json:"id"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Uri string `json:"uri"`
|
||||
ScryfallUri string `json:"scryfall_uri"`
|
||||
SearchUri string `json:"search_uri"`
|
||||
ReleasedAt string `json:"released_at"`
|
||||
SetType string `json:"set_type"`
|
||||
CardCount int `json:"card_count"`
|
||||
ParentSetCode string `json:"parent_set_code"`
|
||||
Digital bool `json:"digital"`
|
||||
NonfoilOnly bool `json:"nonfoil_only"`
|
||||
FoilOnly bool `json:"foil_only"`
|
||||
IconSvgUri string `json:"icon_svg_uri"`
|
||||
}
|
||||
|
||||
type ScryfallSetAPI struct {
|
||||
Object string `json:"object"`
|
||||
HasMore bool `json:"has_more"`
|
||||
Data []ScryfallSet `json:"data"`
|
||||
}
|
||||
|
||||
func fetchApiCards(url string, cards []ScryfallCard) []ScryfallCard {
|
||||
reqClient := http.Client{
|
||||
Timeout: time.Second * 30, // Timeout after 2 seconds
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "brawlset")
|
||||
|
||||
res, err := reqClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var scryfallData ScryfallCardAPI
|
||||
err = json.Unmarshal(body, &scryfallData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cards = append(cards, scryfallData.Data...)
|
||||
if scryfallData.HasMore {
|
||||
return fetchApiCards(scryfallData.NextPage, cards)
|
||||
} else {
|
||||
return cards
|
||||
}
|
||||
}
|
||||
|
||||
func fetchApiSets() []ScryfallSet {
|
||||
url := "https://api.scryfall.com/sets"
|
||||
|
||||
reqClient := http.Client{
|
||||
Timeout: time.Second * 30, // Timeout after 2 seconds
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "brawlset")
|
||||
|
||||
res, err := reqClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var scryFallData ScryfallSetAPI
|
||||
err = json.Unmarshal(body, &scryFallData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return scryFallData.Data
|
||||
}
|
56
backend/types.go
Normal file
56
backend/types.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
type MtgSet struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Code string `db:"code" json:"code"`
|
||||
Name string `db:"name" json:"name"`
|
||||
SanitizedName string `db:"sanitized_name" json:"sanitized_name"`
|
||||
ReleasedAt string `db:"release_at" json:"released_at"`
|
||||
IconUri string `db:"icon_uri" json:"icon_uri"`
|
||||
SetType string `db:"type" json:"type"`
|
||||
}
|
||||
|
||||
type Brawlset struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
SanitizedName string `db:"sanitized_name" json:"sanitized_name"`
|
||||
Sets types.JSONArray[string] `db:"sets" json:"sets"`
|
||||
}
|
||||
|
||||
type Carte struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
SanitizedName string `db:"sanitized_name" json:"sanitized_name"`
|
||||
Layout string `db:"layout" json:"layout"`
|
||||
SmallImage string `db:"small_image" json:"small_image"`
|
||||
SmallImageBack string `db:"small_image_back" json:"small_image_back"`
|
||||
NormalImage string `db:"normal_image" json:"normal_image"`
|
||||
NormalImageBack string `db:"normal_image_back" json:"normal_image_back"`
|
||||
CardType string `db:"type" json:"type"`
|
||||
ColorIdentity types.JSONArray[string] `db:"color_identity" json:"color_identity"`
|
||||
ReleasedAt string `db:"released_at" json:"released_at"`
|
||||
MtgSet string `db:"mtg_set" json:"mtg_set"`
|
||||
SetCode string `db:"set_code" json:"set_code"`
|
||||
Price string `db:"price" json:"price"`
|
||||
CardmarketUri string `db:"cardmarket_url" json:"cardmarket_url"`
|
||||
CanBeCommander bool `db:"can_be_commander" json:"can_be_commander"`
|
||||
}
|
||||
|
||||
type DeckCard struct {
|
||||
ID string `json:"id"`
|
||||
Amount int `json:"amount"`
|
||||
}
|
||||
|
||||
type Deck struct {
|
||||
ID string `db:"id"`
|
||||
Name string `db:"name"`
|
||||
ColorIdentity types.JSONArray[string] `db:"color_identity"`
|
||||
Owner string `db:"owner"`
|
||||
Commander string `db:"commander"`
|
||||
Brawlset string `db:"brawlset"`
|
||||
Cards types.JSONArray[DeckCard] `db:"cartes"`
|
||||
}
|
273
backend/utils.go
Normal file
273
backend/utils.go
Normal file
|
@ -0,0 +1,273 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"unicode/utf8"
|
||||
"slices"
|
||||
"strings"
|
||||
"sort"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// https://stackoverflow.com/a/75996347
|
||||
var defaultDiacriticsRemovalMap = []struct {
|
||||
base string
|
||||
letters string
|
||||
}{
|
||||
{"A", "\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F"},
|
||||
{"AA", "\uA732"},
|
||||
{"AE", "\u00C6\u01FC\u01E2"},
|
||||
{"AO", "\uA734"},
|
||||
{"AU", "\uA736"},
|
||||
{"AV", "\uA738\uA73A"},
|
||||
{"AY", "\uA73C"},
|
||||
{"B", "\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181"},
|
||||
{"C", "\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E"},
|
||||
{"D", "\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0"},
|
||||
{"DZ", "\u01F1\u01C4"},
|
||||
{"Dz", "\u01F2\u01C5"},
|
||||
{"E", "\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E"},
|
||||
{"F", "\u0046\u24BB\uFF26\u1E1E\u0191\uA77B"},
|
||||
{"G", "\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E"},
|
||||
{"H", "\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"},
|
||||
{"I", "\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"},
|
||||
{"J", "\u004A\u24BF\uFF2A\u0134\u0248"},
|
||||
{"K", "\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"},
|
||||
{"L", "\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"},
|
||||
{"LJ", "\u01C7"},
|
||||
{"Lj", "\u01C8"},
|
||||
{"M", "\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C"},
|
||||
{"N", "\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4"},
|
||||
{"NJ", "\u01CA"},
|
||||
{"Nj", "\u01CB"},
|
||||
{"O", "\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C"},
|
||||
{"OI", "\u01A2"},
|
||||
{"OO", "\uA74E"},
|
||||
{"OU", "\u0222"},
|
||||
{"OE", "\u008C\u0152"},
|
||||
{"oe", "\u009C\u0153"},
|
||||
{"P", "\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"},
|
||||
{"Q", "\u0051\u24C6\uFF31\uA756\uA758\u024A"},
|
||||
{"R", "\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"},
|
||||
{"S", "\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"},
|
||||
{"T", "\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"},
|
||||
{"TZ", "\uA728"},
|
||||
{"U", "\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244"},
|
||||
{"V", "\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245"},
|
||||
{"VY", "\uA760"},
|
||||
{"W", "\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"},
|
||||
{"X", "\u0058\u24CD\uFF38\u1E8A\u1E8C"},
|
||||
{"Y", "\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"},
|
||||
{"Z", "\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"},
|
||||
{"a", "\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250"},
|
||||
{"aa", "\uA733"},
|
||||
{"ae", "\u00E6\u01FD\u01E3"},
|
||||
{"ao", "\uA735"},
|
||||
{"au", "\uA737"},
|
||||
{"av", "\uA739\uA73B"},
|
||||
{"ay", "\uA73D"},
|
||||
{"b", "\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253"},
|
||||
{"c", "\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184"},
|
||||
{"d", "\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A"},
|
||||
{"dz", "\u01F3\u01C6"},
|
||||
{"e", "\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD"},
|
||||
{"f", "\u0066\u24D5\uFF46\u1E1F\u0192\uA77C"},
|
||||
{"g", "\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F"},
|
||||
{"h", "\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"},
|
||||
{"hv", "\u0195"},
|
||||
{"i", "\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"},
|
||||
{"j", "\u006A\u24D9\uFF4A\u0135\u01F0\u0249"},
|
||||
{"k", "\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"},
|
||||
{"l", "\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747"},
|
||||
{"lj", "\u01C9"},
|
||||
{"m", "\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F"},
|
||||
{"n", "\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5"},
|
||||
{"nj", "\u01CC"},
|
||||
{"o", "\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275"},
|
||||
{"oi", "\u01A3"},
|
||||
{"ou", "\u0223"},
|
||||
{"oo", "\uA74F"},
|
||||
{"p", "\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755"},
|
||||
{"q", "\u0071\u24E0\uFF51\u024B\uA757\uA759"},
|
||||
{"r", "\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"},
|
||||
{"s", "\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B"},
|
||||
{"t", "\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"},
|
||||
{"tz", "\uA729"},
|
||||
{"u", "\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289"},
|
||||
{"v", "\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C"},
|
||||
{"vy", "\uA761"},
|
||||
{"w", "\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"},
|
||||
{"x", "\u0078\u24E7\uFF58\u1E8B\u1E8D"},
|
||||
{"y", "\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"},
|
||||
{"z", "\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"},
|
||||
}
|
||||
|
||||
var diacriticsMap = map[rune]string{}
|
||||
|
||||
func removeDiacritics(str string) string {
|
||||
for _, mapping := range defaultDiacriticsRemovalMap {
|
||||
letters := mapping.letters
|
||||
for _, letter := range letters {
|
||||
diacriticsMap[letter] = mapping.base
|
||||
}
|
||||
}
|
||||
|
||||
reg := regexp.MustCompile("[^\u0000-\u007E]")
|
||||
return reg.ReplaceAllStringFunc(str, func(a string) string {
|
||||
r, _ := utf8.DecodeRuneInString(a)
|
||||
if replacement, ok := diacriticsMap[rune(r)]; ok {
|
||||
return replacement
|
||||
}
|
||||
return a
|
||||
})
|
||||
}
|
||||
|
||||
func SanitizeName(str string) string {
|
||||
re := regexp.MustCompile(`[^a-zA-Z0-9]+`)
|
||||
return strings.ToLower(re.ReplaceAllString(removeDiacritics(str), "-"))
|
||||
}
|
||||
|
||||
|
||||
// Function to create a SQL query to Upsert cards
|
||||
// Used in : crons.go
|
||||
func CreateBulkCardsUpsertQuery(data []ScryfallCard) string {
|
||||
totalCards := len(data)
|
||||
twoFacedLayouts := []string{"transform","modal_dfc","double_faced_token","reversible_card"}
|
||||
values := make([]string, totalCards)
|
||||
for i := 0; i < totalCards; i++ {
|
||||
id := data[i].ID
|
||||
name := data[i].Name
|
||||
sanitizedName := SanitizeName(data[i].Name) // Sanitized Name
|
||||
layout := data[i].Layout
|
||||
smallImage := ""
|
||||
smallImageBack := ""
|
||||
normalImage := ""
|
||||
normalImageBack := ""
|
||||
// Two Faced
|
||||
if slices.Contains(twoFacedLayouts,data[i].Layout) {
|
||||
smallImage = data[i].CardFaces[0].ImageUris.Small
|
||||
smallImageBack = data[i].CardFaces[0].ImageUris.Normal
|
||||
normalImage = data[i].CardFaces[1].ImageUris.Small
|
||||
normalImageBack = data[i].CardFaces[1].ImageUris.Normal
|
||||
} else {
|
||||
smallImage = data[i].ImageUris.Small
|
||||
normalImage = data[i].ImageUris.Normal
|
||||
}
|
||||
// Type
|
||||
cardTypeLine := strings.ToLower(data[i].TypeLine)
|
||||
cardType := ""
|
||||
if strings.Contains(cardTypeLine, "creature") {
|
||||
cardType = "creature"
|
||||
} else if strings.Contains(cardTypeLine, "planeswalker") {
|
||||
cardType = "planeswalker"
|
||||
} else if strings.Contains(cardTypeLine, "artifact") {
|
||||
cardType = "artifact"
|
||||
} else if strings.Contains(cardTypeLine, "instant") {
|
||||
cardType = "instant"
|
||||
} else if strings.Contains(cardTypeLine, "enchantment") {
|
||||
cardType = "enchantment"
|
||||
} else if strings.Contains(cardTypeLine, "sorcery") {
|
||||
cardType = "sorcery"
|
||||
} else if strings.Contains(cardTypeLine, "land") {
|
||||
cardType = "land"
|
||||
} else {
|
||||
cardType = "unknown"
|
||||
}
|
||||
colorIdentityBytes, err := json.Marshal(data[i].ColorIdentity)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
colorIdentity := string(colorIdentityBytes)
|
||||
releasedAt := data[i].ReleasedAt
|
||||
setId := data[i].SetID
|
||||
setCode := data[i].Set
|
||||
price := data[i].Prices.Eur
|
||||
cardmarketUri := data[i].PurchaseUris.Cardmarket
|
||||
canBeCommander := (strings.Contains(cardTypeLine, "legendary") && cardType == "creature") || cardType == "planeswalker"
|
||||
|
||||
values[i] = fmt.Sprintf(`("%v", "%s", "%v", "%v", "%v", "%v", "%v", "%v", "%v", '%v', "%v", "%v", "%v", "%v", "%v", "%v")`,id, name, sanitizedName, layout, smallImage, smallImageBack, normalImage, normalImageBack, cardType, colorIdentity, releasedAt, setId, setCode, price, cardmarketUri, canBeCommander)
|
||||
}
|
||||
|
||||
upsertQuery := fmt.Sprintf("INSERT INTO carte(id, name, sanitized_name, layout, small_image, small_image_back, normal_image, normal_image_back, type, color_identity, released_at, mtg_set, set_code, price, cardmarket_url, can_be_commander) VALUES %s ON CONFLICT (id) DO UPDATE SET price = excluded.price", strings.Join(values, ", "))
|
||||
|
||||
return upsertQuery
|
||||
}
|
||||
|
||||
// Function to create a SQL query to Insert sets
|
||||
// Used in : crons.go
|
||||
func CreateBulkSetsInsertQuery(data []ScryfallSet) string {
|
||||
totalSets := len(data)
|
||||
values := make([]string, totalSets)
|
||||
for i := 0; i < totalSets; i++ {
|
||||
values[i] = fmt.Sprintf(`("%v", "%v", "%v", "%v", "%v", "%v", "%v")`,data[i].ID, data[i].Name, SanitizeName(data[i].Name), data[i].Code, data[i].IconSvgUri, data[i].SetType, data[i].ReleasedAt)
|
||||
}
|
||||
|
||||
insertQuery := fmt.Sprintf("INSERT OR IGNORE INTO mtg_set(id, name, sanitized_name, code, icon_uri, type, released_at) VALUES %s", strings.Join(values, ", "))
|
||||
|
||||
return insertQuery
|
||||
}
|
||||
|
||||
// Timer used to time a function
|
||||
// Used in : cache.go
|
||||
func timer(name string) func() {
|
||||
start := time.Now()
|
||||
return func() {
|
||||
log.Printf("%s took %v\n", name, time.Since(start))
|
||||
}
|
||||
}
|
||||
|
||||
// Function to create all possible combinations of an array with a said length
|
||||
// Used in : cache.go
|
||||
// Source (in java) : https://hmkcode.com/calculate-find-all-possible-combinations-of-an-array-using-java/
|
||||
func CreateCombination(s []string, k int) []string {
|
||||
res := []string{}
|
||||
ignore := make([]int, len(s) - k)
|
||||
combination := make([]string, k)
|
||||
for w := 0; w < len(ignore); w++ {
|
||||
ignore[w] = len(s) - 1 - w
|
||||
}
|
||||
// Edit fonction above to make it ascending by default
|
||||
sort.Slice(ignore, func(i, j int) bool { return ignore[i] < ignore[j]})
|
||||
|
||||
i := 0
|
||||
r := 0
|
||||
g := 0
|
||||
|
||||
terminate := false
|
||||
for !terminate {
|
||||
for i < len(s) && r < k {
|
||||
if i != ignore[g] {
|
||||
combination[r] = s[i];
|
||||
r++
|
||||
i++
|
||||
} else {
|
||||
if g != len(ignore) - 1 {
|
||||
g++
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
i = 0
|
||||
r = 0
|
||||
g = 0
|
||||
|
||||
res = append(res, strings.Join(combination,""))
|
||||
terminate = true
|
||||
|
||||
for w := 0; w < len(ignore); w++ {
|
||||
if ignore[w] > w {
|
||||
ignore[w]--
|
||||
|
||||
if w > 0 {
|
||||
ignore[w-1] = ignore[w]-1
|
||||
}
|
||||
terminate = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue