diff --git a/cmd/twhelp/app.go b/cmd/twhelp/app.go new file mode 100644 index 0000000..c386c38 --- /dev/null +++ b/cmd/twhelp/app.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "log/slog" + + "github.com/urfave/cli/v2" +) + +const ( + appModeProduction = "production" + appModeDevelopment = "development" +) + +var ( + appFlagMode = &cli.GenericFlag{ + Name: "mode", + Value: &EnumValue{ + Enum: []string{appModeDevelopment, appModeProduction}, + Default: appModeDevelopment, + }, + Usage: fmt.Sprintf("%s or %s", appModeProduction, appModeDevelopment), + EnvVars: []string{"APP_MODE"}, + } + appFlags = []cli.Flag{ + appFlagMode, + } +) + +type appWrapper struct { + *cli.App + logger *slog.Logger +} + +func newApp(name, version string) *appWrapper { + app := &appWrapper{App: cli.NewApp(), logger: slog.Default()} + app.Name = name + app.HelpName = name + app.Version = version + app.Commands = []*cli.Command{cmdDB} + app.Flags = appFlags + app.Before = app.handleBefore + return app +} + +func (a *appWrapper) handleBefore(c *cli.Context) error { + c.Context = loggerToCtx(c.Context, a.logger) + + a.logger.Debug("executing command", slog.Any("args", c.Args().Slice())) + + return nil +} diff --git a/cmd/twhelp/bun.go b/cmd/twhelp/bun.go new file mode 100644 index 0000000..540f7bd --- /dev/null +++ b/cmd/twhelp/bun.go @@ -0,0 +1,114 @@ +package main + +import ( + "context" + "database/sql" + "fmt" + "runtime" + "time" + + "github.com/uptrace/bun" + "github.com/uptrace/bun/dialect/pgdialect" + "github.com/uptrace/bun/driver/pgdriver" + "github.com/urfave/cli/v2" +) + +var ( + dbFlagConnectionString = &cli.StringFlag{ + Name: "db.connectionString", + Required: true, + EnvVars: []string{"DB_CONNECTION_STRING"}, + Usage: "https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING", + } + dbFlagMaxIdleConns = &cli.IntFlag{ + Name: "db.maxIdleConns", + Value: 2, + EnvVars: []string{"DB_MAX_IDLE_CONNS"}, + Usage: "https://pkg.go.dev/database/sql#DB.SetMaxIdleConns", + } + dbFlagMaxOpenConns = &cli.IntFlag{ + Name: "db.maxOpenConns", + Value: runtime.NumCPU() * 4, + EnvVars: []string{"DB_MAX_OPEN_CONNS"}, + Usage: "https://pkg.go.dev/database/sql#DB.SetMaxOpenConns", + } + dbFlagConnMaxLifetime = &cli.DurationFlag{ + Name: "db.connMaxLifetime", + Value: 30 * time.Minute, + EnvVars: []string{"DB_CONN_MAX_LIFETIME"}, + Usage: "https://pkg.go.dev/database/sql#DB.SetConnMaxLifetime", + } + dbFlagReadTimeout = &cli.DurationFlag{ + Name: "db.readTimeout", + Value: 10 * time.Second, + EnvVars: []string{"DB_READ_TIMEOUT"}, + } + dbFlagWriteTimeout = &cli.DurationFlag{ + Name: "db.writeTimeout", + Value: 5 * time.Second, + EnvVars: []string{"DB_WRITE_TIMEOUT"}, + } + dbFlags = []cli.Flag{ + dbFlagConnectionString, + dbFlagMaxIdleConns, + dbFlagMaxOpenConns, + dbFlagConnMaxLifetime, + dbFlagReadTimeout, + dbFlagWriteTimeout, + } +) + +func newBunDBFromFlags(c *cli.Context) (*bun.DB, error) { + return newBunDB(bundDBConfig{ + connectionString: c.String(dbFlagConnectionString.Name), + maxOpenConns: c.Int(dbFlagMaxOpenConns.Name), + maxIdleConns: c.Int(dbFlagMaxIdleConns.Name), + connMaxLifetime: c.Duration(dbFlagConnMaxLifetime.Name), + writeTimeout: c.Duration(dbFlagWriteTimeout.Name), + readTimeout: c.Duration(dbFlagReadTimeout.Name), + }) +} + +type bundDBConfig struct { + connectionString string + maxOpenConns int + maxIdleConns int + connMaxLifetime time.Duration + readTimeout time.Duration + writeTimeout time.Duration +} + +func newBunDB(cfg bundDBConfig) (*bun.DB, error) { + db := bun.NewDB(newSQLDB(cfg), pgdialect.New()) + + if err := pingDB(db); err != nil { + return nil, err + } + + return db, nil +} + +func newSQLDB(cfg bundDBConfig) *sql.DB { + db := sql.OpenDB(pgdriver.NewConnector( + pgdriver.WithDSN(cfg.connectionString), + pgdriver.WithReadTimeout(cfg.readTimeout), + pgdriver.WithWriteTimeout(cfg.writeTimeout), + )) + db.SetMaxOpenConns(cfg.maxOpenConns) + db.SetMaxIdleConns(cfg.maxIdleConns) + db.SetConnMaxLifetime(cfg.connMaxLifetime) + return db +} + +const dbPingTimeout = 10 * time.Second + +func pingDB(db *bun.DB) error { + ctx, cancel := context.WithTimeout(context.Background(), dbPingTimeout) + defer cancel() + + if err := db.PingContext(ctx); err != nil { + return fmt.Errorf("couldn't ping db: %w", err) + } + + return nil +} diff --git a/cmd/twhelp/cmd_db.go b/cmd/twhelp/cmd_db.go new file mode 100644 index 0000000..d34e52a --- /dev/null +++ b/cmd/twhelp/cmd_db.go @@ -0,0 +1,196 @@ +package main + +import ( + "fmt" + "log/slog" + "strings" + + "gitea.dwysokinski.me/twhelp/corev3/internal/migrations" + "github.com/uptrace/bun/migrate" + "github.com/urfave/cli/v2" +) + +const migrationGoTemplate = `package %s + +import ( + "context" + "fmt" + + "github.com/uptrace/bun" +) + +func init() { + migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + fmt.Print(" [up migration] ") + return nil + }, func(ctx context.Context, db *bun.DB) error { + fmt.Print(" [down migration] ") + return nil + }) +} +` + +var cmdDB = &cli.Command{ + Name: "db", + Usage: "Manages database migrations", + Subcommands: []*cli.Command{ + { + Name: "migrate", + Usage: "Migrate database", + Flags: dbFlags, + Action: func(c *cli.Context) error { + logger := loggerFromCtx(c.Context) + + bunDB, err := newBunDBFromFlags(c) + if err != nil { + return err + } + defer func() { + logger.Debug("closing db connections...") + if dbCloseErr := bunDB.Close(); dbCloseErr != nil { + logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr)) + } + }() + + migrator := migrations.NewMigrator(bunDB) + + if err = migrator.Init(c.Context); err != nil { + return fmt.Errorf("couldn't init migrator: %w", err) + } + + if err = migrator.Lock(c.Context); err != nil { + return fmt.Errorf("couldn't lock db: %w", err) + } + defer func() { + logger.Debug("unlocking db...") + if unlockErr := migrator.Unlock(c.Context); unlockErr != nil { + logger.Warn("couldn't unlock db", slog.Any("error", unlockErr)) + } + }() + + group, err := migrator.Migrate(c.Context) + if err != nil { + return fmt.Errorf("migration failed: %w", err) + } + + if group.ID == 0 { + logger.Info("there are no new migrations to run") + return nil + } + + logger.Info( + "migrations have been successfully applied", + slog.Int64("group.id", group.ID), + slog.String("group.migrations", group.Migrations.String()), + ) + + return nil + }, + }, + { + Name: "rollback", + Usage: "Rollback the last migration group", + Flags: dbFlags, + Action: func(c *cli.Context) error { + logger := loggerFromCtx(c.Context) + + bunDB, err := newBunDBFromFlags(c) + if err != nil { + return err + } + defer func() { + logger.Debug("closing db connections...") + if dbCloseErr := bunDB.Close(); dbCloseErr != nil { + logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr)) + } + }() + + migrator := migrations.NewMigrator(bunDB) + + if err = migrator.Lock(c.Context); err != nil { + return fmt.Errorf("couldn't lock db: %w", err) + } + defer func() { + logger.Debug("unlocking db...") + if unlockErr := migrator.Unlock(c.Context); unlockErr != nil { + logger.Warn("couldn't unlock db", slog.Any("error", unlockErr)) + } + }() + + group, err := migrator.Rollback(c.Context) + if err != nil { + return fmt.Errorf("couldn't rollback last migration: %w", err) + } + + if group.ID == 0 { + logger.Info("there are no groups to roll back") + return nil + } + + logger.Info( + "last migration group has been rolled back", + slog.Int64("group.id", group.ID), + slog.String("group.migrations", group.Migrations.String()), + ) + + return nil + }, + }, + { + Name: "create", + Usage: "Create migration", + Subcommands: []*cli.Command{ + { + Name: "go", + Usage: "Create Go migration", + Action: func(c *cli.Context) error { + logger := loggerFromCtx(c.Context) + + migrator := migrations.NewMigrator(nil) + + mf, err := migrator.CreateGoMigration( + c.Context, + strings.Join(c.Args().Slice(), "_"), + migrate.WithGoTemplate(migrationGoTemplate), + ) + if err != nil { + return fmt.Errorf("couldn't create Go migration: %w", err) + } + + logger.Info( + "Go migration has been created", + slog.String("migration.path", mf.Path), + slog.String("migration.name", mf.Name), + ) + + return nil + }, + }, + { + Name: "sql", + Usage: "Create SQL migration", + Action: func(c *cli.Context) error { + logger := loggerFromCtx(c.Context) + + migrator := migrations.NewMigrator(nil) + + files, err := migrator.CreateSQLMigrations(c.Context, strings.Join(c.Args().Slice(), "_")) + if err != nil { + return fmt.Errorf("couldn't create sql migration: %w", err) + } + + for _, mf := range files { + logger.Info( + "SQL migration has been created", + slog.String("migration.path", mf.Path), + slog.String("migration.name", mf.Name), + ) + } + + return nil + }, + }, + }, + }, + }, +} diff --git a/cmd/twhelp/enum_value.go b/cmd/twhelp/enum_value.go new file mode 100644 index 0000000..d618b2d --- /dev/null +++ b/cmd/twhelp/enum_value.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "strings" +) + +type EnumValue struct { + Enum []string + Default string + selected string +} + +func (e *EnumValue) Set(value string) error { + for _, enum := range e.Enum { + if enum == value { + e.selected = value + return nil + } + } + + return fmt.Errorf("allowed values are %s", strings.Join(e.Enum, ", ")) +} + +func (e *EnumValue) String() string { + if e.selected == "" { + return e.Default + } + return e.selected +} diff --git a/cmd/twhelp/logger.go b/cmd/twhelp/logger.go new file mode 100644 index 0000000..873f2a0 --- /dev/null +++ b/cmd/twhelp/logger.go @@ -0,0 +1,17 @@ +package main + +import ( + "context" + "log/slog" +) + +type loggerCtxKey struct{} + +func loggerToCtx(ctx context.Context, l *slog.Logger) context.Context { + return context.WithValue(ctx, loggerCtxKey{}, l) +} + +func loggerFromCtx(ctx context.Context) *slog.Logger { + logger, _ := ctx.Value(loggerCtxKey{}).(*slog.Logger) + return logger +} diff --git a/cmd/twhelp/main.go b/cmd/twhelp/main.go new file mode 100644 index 0000000..ac9e239 --- /dev/null +++ b/cmd/twhelp/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "log/slog" + "os" +) + +const appName = "wendia" + +// this flag will be set by the build flags +var version = "development" + +func main() { + app := newApp(appName, version) + if err := app.Run(os.Args); err != nil { + app.logger.Error("app run failed", slog.Any("error", err)) + os.Exit(1) + } +} diff --git a/go.mod b/go.mod index c01f8b7..9a96413 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,28 @@ go 1.21 require ( github.com/elliotchance/phpserialize v1.3.3 + github.com/go-chi/chi/v5 v5.0.10 + github.com/google/go-cmp v0.6.0 github.com/stretchr/testify v1.8.4 + github.com/uptrace/bun v1.1.16 + github.com/uptrace/bun/dialect/pgdialect v1.1.16 + github.com/uptrace/bun/driver/pgdriver v1.1.16 + github.com/urfave/cli/v2 v2.26.0 ) require ( + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + golang.org/x/crypto v0.13.0 // indirect + golang.org/x/sys v0.12.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + mellium.im/sasl v0.3.1 // indirect ) diff --git a/go.sum b/go.sum index 176eb19..60d3770 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,54 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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/elliotchance/phpserialize v1.3.3 h1:hV4QVmGdCiYgoBbw+ADt6fNgyZ2mYX0OgpnON1adTCM= github.com/elliotchance/phpserialize v1.3.3/go.mod h1:gt7XX9+ETUcLXbtTKEuyrqW3lcLUAeS/AnGZ2e49TZs= +github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= +github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 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/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= +github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= +github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= +github.com/uptrace/bun/dialect/pgdialect v1.1.16 h1:eUPZ+YCJ69BA+W1X1ZmpOJSkv1oYtinr0zCXf7zCo5g= +github.com/uptrace/bun/dialect/pgdialect v1.1.16/go.mod h1:KQjfx/r6JM0OXfbv0rFrxAbdkPD7idK8VitnjIV9fZI= +github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= +github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI= +github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= +mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= diff --git a/internal/chislog/chislog.go b/internal/chislog/chislog.go new file mode 100644 index 0000000..6c35387 --- /dev/null +++ b/internal/chislog/chislog.go @@ -0,0 +1,82 @@ +package chislog + +import ( + "context" + "log/slog" + "net/http" + "time" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" +) + +type Slogger interface { + Log(ctx context.Context, level slog.Level, msg string, args ...any) +} + +// Logger returns a go-chi middleware that logs requests using the given Slogger. +func Logger(logger Slogger, opts ...Option) func(next http.Handler) http.Handler { + cfg := newConfig(opts...) + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for _, f := range cfg.filters { + if !f(r) { + next.ServeHTTP(w, r) + return + } + } + + ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) + start := time.Now() + + next.ServeHTTP(ww, r) + + end := time.Now() + status := ww.Status() + + logger.Log( + r.Context(), + statusLevel(status), + statusLabel(status), + slog.String("routePattern", chi.RouteContext(r.Context()).RoutePattern()), + slog.String("httpRequest.method", r.Method), + slog.String("httpRequest.uri", r.RequestURI), + slog.String("httpRequest.referer", r.Referer()), + slog.String("httpRequest.userAgent", r.UserAgent()), + slog.String("httpRequest.proto", r.Proto), + slog.String("httpRequest.ip", cfg.ipExtractor(r)), + slog.Int("httpResponse.status", status), + slog.Int("httpResponse.bytes", ww.BytesWritten()), + slog.Float64("httpResponse.duration", float64(end.Sub(start).Nanoseconds())/1000000.0), // in milliseconds + ) + }) + } +} + +func statusLevel(status int) slog.Level { + switch { + case status < http.StatusContinue: + return slog.LevelWarn + case status >= http.StatusBadRequest && status < http.StatusInternalServerError: + return slog.LevelWarn + case status >= http.StatusInternalServerError: + return slog.LevelError + default: // for statuses 100 <= 400 + return slog.LevelInfo + } +} + +func statusLabel(status int) string { + switch { + case status >= http.StatusContinue && status < http.StatusMultipleChoices: + return "OK" + case status >= http.StatusMultipleChoices && status < http.StatusBadRequest: + return "Redirect" + case status >= http.StatusBadRequest && status < http.StatusInternalServerError: + return "Client Error" + case status >= http.StatusInternalServerError: + return "Server Error" + default: + return "Unknown" + } +} diff --git a/internal/chislog/chislog_test.go b/internal/chislog/chislog_test.go new file mode 100644 index 0000000..310f8ba --- /dev/null +++ b/internal/chislog/chislog_test.go @@ -0,0 +1,161 @@ +package chislog_test + +import ( + "bytes" + "encoding/json" + "log/slog" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "gitea.dwysokinski.me/twhelp/corev3/internal/chislog" + "github.com/go-chi/chi/v5" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestLogger(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + register func(r chi.Router) + options []chislog.Option + req func(t *testing.T) *http.Request + assertEntry func(t *testing.T, entry map[string]any) + excluded bool + }{ + { + name: "log level should be Info when status code >= 200 and < 400", + register: func(r chi.Router) { + r.Get("/info", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) + }, + req: func(t *testing.T) *http.Request { + t.Helper() + return httptest.NewRequest(http.MethodGet, "/info?test=true", nil) + }, + assertEntry: func(t *testing.T, entry map[string]any) { + t.Helper() + assert.Equal(t, slog.LevelInfo.String(), entry[slog.LevelKey]) + assert.Equal(t, "192.0.2.1", entry["httpRequest.ip"]) // default ip address set by httptest.NewRequest + }, + }, + { + name: "log level should be Warn when status code >= 400 and < 500", + register: func(r chi.Router) { + r.Get("/warn", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + }) + }, + req: func(t *testing.T) *http.Request { + t.Helper() + return httptest.NewRequest(http.MethodGet, "/warn?test=true", nil) + }, + assertEntry: func(t *testing.T, entry map[string]any) { + t.Helper() + assert.Equal(t, slog.LevelWarn.String(), entry[slog.LevelKey]) + }, + }, + { + name: "log level should be Error when status code >= 500", + register: func(r chi.Router) { + r.Get("/error", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + }) + }, + req: func(t *testing.T) *http.Request { + t.Helper() + return httptest.NewRequest(http.MethodGet, "/error?test=true", nil) + }, + assertEntry: func(t *testing.T, entry map[string]any) { + t.Helper() + assert.Equal(t, slog.LevelError.String(), entry[slog.LevelKey]) + }, + }, + { + name: "read IP from header X-Forwarded-For", + options: []chislog.Option{ + chislog.WithIPExtractor(func(r *http.Request) string { + return r.Header.Get("X-Forwarded-For") + }), + }, + register: func(r chi.Router) { + r.Post("/x-forwarded-for", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) + }, + req: func(t *testing.T) *http.Request { + t.Helper() + req := httptest.NewRequest(http.MethodPost, "/x-forwarded-for", nil) + req.Header.Set("X-Forwarded-For", "111.111.111.111") + return req + }, + assertEntry: func(t *testing.T, entry map[string]any) { + t.Helper() + assert.Equal(t, slog.LevelInfo.String(), entry[slog.LevelKey]) + assert.Equal(t, "111.111.111.111", entry["httpRequest.ip"]) + }, + }, + { + name: "log entry should be skipped", + options: []chislog.Option{ + chislog.WithFilter(func(r *http.Request) bool { + return !strings.HasPrefix(r.URL.Path, "/meta") + }), + }, + register: func(r chi.Router) { + r.Get("/meta/test", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) + }, + req: func(t *testing.T) *http.Request { + t.Helper() + return httptest.NewRequest(http.MethodGet, "/meta/test", nil) + }, + excluded: true, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + buf := bytes.NewBuffer(nil) + logger := slog.New(slog.NewJSONHandler(buf, nil)) + + r := chi.NewRouter() + r.Use(chislog.Logger(logger, tt.options...)) + tt.register(r) + + rr := httptest.NewRecorder() + req := tt.req(t) + + r.ServeHTTP(rr, req) + + if tt.excluded { + assert.Zero(t, buf.Bytes()) + return + } + + var entry map[string]any + require.NoError(t, json.Unmarshal(buf.Bytes(), &entry)) + assert.NotEmpty(t, entry["time"]) + assert.Equal(t, req.Method, entry["httpRequest.method"]) + assert.Equal(t, req.RequestURI, entry["httpRequest.uri"]) + assert.Equal(t, req.Referer(), entry["httpRequest.referer"]) + assert.Equal(t, req.UserAgent(), entry["httpRequest.userAgent"]) + assert.Equal(t, req.Proto, entry["httpRequest.proto"]) + assert.Equal(t, float64(rr.Code), entry["httpResponse.status"]) + assert.GreaterOrEqual(t, entry["httpResponse.bytes"], 0.0) + assert.GreaterOrEqual(t, entry["httpResponse.duration"], 0.0) + if tt.assertEntry != nil { + tt.assertEntry(t, entry) + } + }) + } +} diff --git a/internal/chislog/config.go b/internal/chislog/config.go new file mode 100644 index 0000000..89885d4 --- /dev/null +++ b/internal/chislog/config.go @@ -0,0 +1,54 @@ +package chislog + +import ( + "net" + "net/http" +) + +type Filter func(r *http.Request) bool + +type IPExtractor func(r *http.Request) string + +type config struct { + filters []Filter + ipExtractor IPExtractor +} + +type Option func(cfg *config) + +func newConfig(opts ...Option) *config { + cfg := &config{ + ipExtractor: defaultIPExtractor, + } + + for _, opt := range opts { + opt(cfg) + } + + return cfg +} + +// WithFilter adds a filter to the list of filters used by the middleware. +// If any filter indicates to exclude a request then the request will not be logged. +// All filters must allow a request to be logged. +// If no filters are provided, then all requests are logged. +func WithFilter(f Filter) Option { + return func(c *config) { + c.filters = append(c.filters, f) + } +} + +// WithIPExtractor takes a function that will be called on every +// request and the returned ip will be added to the log entry. +// +// http.Request RemoteAddr is logged by default. +func WithIPExtractor(extractor IPExtractor) Option { + return func(c *config) { + c.ipExtractor = extractor + } +} + +func defaultIPExtractor(r *http.Request) string { + ip, _, _ := net.SplitHostPort(r.RemoteAddr) + return ip +} diff --git a/internal/health/checker.go b/internal/health/checker.go new file mode 100644 index 0000000..b8aa28e --- /dev/null +++ b/internal/health/checker.go @@ -0,0 +1,8 @@ +package health + +import "context" + +type Checker interface { + Name() string + Check(ctx context.Context) error +} diff --git a/internal/health/config.go b/internal/health/config.go new file mode 100644 index 0000000..bbbe273 --- /dev/null +++ b/internal/health/config.go @@ -0,0 +1,41 @@ +package health + +type config struct { + liveChecks []Checker + readyChecks []Checker + maxConcurrent int +} + +type Option func(cfg *config) + +const maxConcurrentDefault = 5 + +func newConfig(opts ...Option) *config { + cfg := &config{ + maxConcurrent: maxConcurrentDefault, + } + + for _, opt := range opts { + opt(cfg) + } + + return cfg +} + +func WithMaxConcurrent(max int) Option { + return func(cfg *config) { + cfg.maxConcurrent = max + } +} + +func WithLiveCheck(check Checker) Option { + return func(cfg *config) { + cfg.liveChecks = append(cfg.liveChecks, check) + } +} + +func WithReadyCheck(check Checker) Option { + return func(cfg *config) { + cfg.readyChecks = append(cfg.readyChecks, check) + } +} diff --git a/internal/health/health.go b/internal/health/health.go new file mode 100644 index 0000000..1e6834a --- /dev/null +++ b/internal/health/health.go @@ -0,0 +1,112 @@ +package health + +import ( + "context" + "sync" + "time" +) + +type Health struct { + liveChecks []Checker + readyChecks []Checker + maxConcurrent int +} + +func New(opts ...Option) *Health { + cfg := newConfig(opts...) + return &Health{ + liveChecks: cfg.liveChecks, + readyChecks: cfg.readyChecks, + maxConcurrent: cfg.maxConcurrent, + } +} + +type Status string + +const ( + StatusPass Status = "pass" + StatusFail Status = "fail" +) + +func (s Status) String() string { + return string(s) +} + +type SingleCheckResult struct { + Status Status + Err error + Time time.Time +} + +type Result struct { + Status Status + Checks map[string][]SingleCheckResult +} + +func (h *Health) CheckLive(ctx context.Context) Result { + return h.check(ctx, h.liveChecks) +} + +func (h *Health) CheckReady(ctx context.Context) Result { + return h.check(ctx, h.readyChecks) +} + +type singleCheckResultWithName struct { + Name string + SingleCheckResult +} + +func (h *Health) check(ctx context.Context, checks []Checker) Result { + limiterCh := make(chan struct{}, h.maxConcurrent) + checkCh := make(chan singleCheckResultWithName) + var wg sync.WaitGroup + + for _, ch := range checks { + wg.Add(1) + + go func(ch Checker) { + defer wg.Done() + + limiterCh <- struct{}{} + defer func() { + <-limiterCh + }() + + check := SingleCheckResult{ + Status: StatusPass, + Time: time.Now(), + } + + if err := ch.Check(ctx); err != nil { + check.Status = StatusFail + check.Err = err + } + + checkCh <- singleCheckResultWithName{ + Name: ch.Name(), + SingleCheckResult: check, + } + }(ch) + } + + go func() { + wg.Wait() + close(limiterCh) + close(checkCh) + }() + + res := Result{ + Status: StatusPass, + Checks: make(map[string][]SingleCheckResult, len(checks)), + } + + for check := range checkCh { + if check.Status == StatusFail { + res.Status = StatusFail + } + + res.Checks[check.Name] = append(res.Checks[check.Name], check.SingleCheckResult) + } + + return res +} diff --git a/internal/health/health_test.go b/internal/health/health_test.go new file mode 100644 index 0000000..f7626be --- /dev/null +++ b/internal/health/health_test.go @@ -0,0 +1,206 @@ +package health_test + +import ( + "context" + "errors" + "testing" + "time" + + "gitea.dwysokinski.me/twhelp/corev3/internal/health" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" +) + +var errCheckFailed = errors.New("failed") + +func TestHealth_CheckReady(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + options []health.Option + expectedResult health.Result + }{ + { + name: "0 checks", + expectedResult: health.Result{ + Status: health.StatusPass, + Checks: make(map[string][]health.SingleCheckResult), + }, + }, + { + name: "3 checks passed", + options: []health.Option{ + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test2", err: nil}), + health.WithMaxConcurrent(2), + }, + expectedResult: health.Result{ + Status: health.StatusPass, + Checks: map[string][]health.SingleCheckResult{ + "test": { + { + Status: health.StatusPass, + }, + { + Status: health.StatusPass, + }, + }, + "test2": { + { + Status: health.StatusPass, + }, + }, + }, + }, + }, + { + name: "2 checks passed, 1 check failed", + options: []health.Option{ + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test2", err: errCheckFailed}), + }, + expectedResult: health.Result{ + Status: health.StatusFail, + Checks: map[string][]health.SingleCheckResult{ + "test": { + { + Status: health.StatusPass, + }, + { + Status: health.StatusPass, + }, + }, + "test2": { + { + Status: health.StatusFail, + Err: errCheckFailed, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result := health.New(tt.options...).CheckReady(context.Background()) + + assert.Empty(t, cmp.Diff( + tt.expectedResult, + result, + cmpopts.IgnoreTypes(time.Time{}), + cmpopts.EquateErrors(), + )) + }) + } +} + +func TestHealth_CheckLive(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + options []health.Option + expectedResult health.Result + }{ + { + name: "0 checks", + expectedResult: health.Result{ + Status: health.StatusPass, + Checks: make(map[string][]health.SingleCheckResult), + }, + }, + { + name: "3 checks passed", + options: []health.Option{ + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test2", err: nil}), + health.WithMaxConcurrent(2), + }, + expectedResult: health.Result{ + Status: health.StatusPass, + Checks: map[string][]health.SingleCheckResult{ + "test": { + { + Status: health.StatusPass, + }, + { + Status: health.StatusPass, + }, + }, + "test2": { + { + Status: health.StatusPass, + }, + }, + }, + }, + }, + { + name: "2 checks passed, 1 check failed", + options: []health.Option{ + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test2", err: errCheckFailed}), + }, + expectedResult: health.Result{ + Status: health.StatusFail, + Checks: map[string][]health.SingleCheckResult{ + "test": { + { + Status: health.StatusPass, + }, + { + Status: health.StatusPass, + }, + }, + "test2": { + { + Status: health.StatusFail, + Err: errCheckFailed, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result := health.New(tt.options...).CheckLive(context.Background()) + + assert.Empty(t, cmp.Diff( + tt.expectedResult, + result, + cmpopts.IgnoreTypes(time.Time{}), + cmpopts.EquateErrors(), + )) + }) + } +} + +type checker struct { + name string + err error +} + +func (c checker) Name() string { + return c.name +} + +func (c checker) Check(_ context.Context) error { + return c.err +} diff --git a/internal/health/healthhttp/export.go b/internal/health/healthhttp/export.go new file mode 100644 index 0000000..c44a268 --- /dev/null +++ b/internal/health/healthhttp/export.go @@ -0,0 +1,5 @@ +package healthhttp + +type Response = response + +type SingleCheckResult = singleCheckResult diff --git a/internal/health/healthhttp/handler.go b/internal/health/healthhttp/handler.go new file mode 100644 index 0000000..ba1ce91 --- /dev/null +++ b/internal/health/healthhttp/handler.go @@ -0,0 +1,79 @@ +package healthhttp + +import ( + "context" + "encoding/json" + "net/http" + "time" + + "gitea.dwysokinski.me/twhelp/corev3/internal/health" +) + +type handler struct { + check func(ctx context.Context) health.Result +} + +var _ http.Handler = (*handler)(nil) + +func LiveHandler(h *health.Health) http.Handler { + return &handler{ + check: h.CheckLive, + } +} + +func ReadyHandler(h *health.Health) http.Handler { + return &handler{ + check: h.CheckReady, + } +} + +type singleCheckResult struct { + Status string `json:"status"` + FailureReason string `json:"err,omitempty"` + Time time.Time `json:"time"` +} + +type response struct { + Status string `json:"status"` + Checks map[string][]singleCheckResult `json:"checks"` +} + +func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + result := h.check(r.Context()) + + respChecks := make(map[string][]singleCheckResult, len(result.Checks)) + for name, checks := range result.Checks { + respChecks[name] = make([]singleCheckResult, 0, len(checks)) + + for _, ch := range checks { + failureReason := "" + if ch.Err != nil { + failureReason = ch.Err.Error() + } + + respChecks[name] = append(respChecks[name], singleCheckResult{ + Status: ch.Status.String(), + FailureReason: failureReason, + Time: ch.Time, + }) + } + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(healthStatusToHTTPStatus(result.Status)) + _ = json.NewEncoder(w).Encode(response{ + Status: result.Status.String(), + Checks: respChecks, + }) +} + +func healthStatusToHTTPStatus(status health.Status) int { + switch status { + case health.StatusPass: + return http.StatusOK + case health.StatusFail: + return http.StatusServiceUnavailable + default: + return http.StatusInternalServerError + } +} diff --git a/internal/health/healthhttp/handler_test.go b/internal/health/healthhttp/handler_test.go new file mode 100644 index 0000000..61626fa --- /dev/null +++ b/internal/health/healthhttp/handler_test.go @@ -0,0 +1,209 @@ +package healthhttp_test + +import ( + "context" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + "time" + + "gitea.dwysokinski.me/twhelp/corev3/internal/health" + "gitea.dwysokinski.me/twhelp/corev3/internal/health/healthhttp" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestReadyHandler(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + options []health.Option + expectedStatus int + expectedResponse healthhttp.Response + }{ + { + name: "pass", + options: []health.Option{ + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test2", err: nil}), + }, + expectedStatus: http.StatusOK, + expectedResponse: healthhttp.Response{ + Status: health.StatusPass.String(), + Checks: map[string][]healthhttp.SingleCheckResult{ + "test": { + { + Status: health.StatusPass.String(), + }, + { + Status: health.StatusPass.String(), + }, + }, + "test2": { + { + Status: health.StatusPass.String(), + }, + }, + }, + }, + }, + { + name: "2 checks passed, 1 check failed", + options: []health.Option{ + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test", err: nil}), + health.WithReadyCheck(checker{name: "test2", err: errors.New("failed")}), + }, + expectedStatus: http.StatusServiceUnavailable, + expectedResponse: healthhttp.Response{ + Status: health.StatusFail.String(), + Checks: map[string][]healthhttp.SingleCheckResult{ + "test": { + { + Status: health.StatusPass.String(), + }, + { + Status: health.StatusPass.String(), + }, + }, + "test2": { + { + Status: health.StatusFail.String(), + FailureReason: "failed", + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + rr := httptest.NewRecorder() + + healthhttp.ReadyHandler(health.New(tt.options...)).ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/readyz", nil)) + + assert.Equal(t, tt.expectedStatus, rr.Code) + assert.Equal(t, "application/json", rr.Header().Get("Content-Type")) + var body healthhttp.Response + require.NoError(t, json.NewDecoder(rr.Body).Decode(&body)) + assert.Empty(t, cmp.Diff( + tt.expectedResponse, + body, + cmpopts.IgnoreTypes(time.Time{}), + )) + }) + } +} + +func TestLiveHandler(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + options []health.Option + expectedStatus int + expectedResponse healthhttp.Response + }{ + { + name: "pass", + options: []health.Option{ + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test2", err: nil}), + }, + expectedStatus: http.StatusOK, + expectedResponse: healthhttp.Response{ + Status: health.StatusPass.String(), + Checks: map[string][]healthhttp.SingleCheckResult{ + "test": { + { + Status: health.StatusPass.String(), + }, + { + Status: health.StatusPass.String(), + }, + }, + "test2": { + { + Status: health.StatusPass.String(), + }, + }, + }, + }, + }, + { + name: "2 checks passed, 1 check failed", + options: []health.Option{ + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test", err: nil}), + health.WithLiveCheck(checker{name: "test2", err: errors.New("failed")}), + }, + expectedStatus: http.StatusServiceUnavailable, + expectedResponse: healthhttp.Response{ + Status: health.StatusFail.String(), + Checks: map[string][]healthhttp.SingleCheckResult{ + "test": { + { + Status: health.StatusPass.String(), + }, + { + Status: health.StatusPass.String(), + }, + }, + "test2": { + { + Status: health.StatusFail.String(), + FailureReason: "failed", + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + rr := httptest.NewRecorder() + + healthhttp.LiveHandler(health.New(tt.options...)).ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/livez", nil)) + + assert.Equal(t, tt.expectedStatus, rr.Code) + assert.Equal(t, "application/json", rr.Header().Get("Content-Type")) + var body healthhttp.Response + require.NoError(t, json.NewDecoder(rr.Body).Decode(&body)) + assert.Empty(t, cmp.Diff( + tt.expectedResponse, + body, + cmpopts.IgnoreTypes(time.Time{}), + )) + }) + } +} + +type checker struct { + name string + err error +} + +func (c checker) Name() string { + return c.name +} + +func (c checker) Check(_ context.Context) error { + return c.err +} diff --git a/internal/migrations/20231216063603_create_versions_table.down.sql b/internal/migrations/20231216063603_create_versions_table.down.sql new file mode 100644 index 0000000..c31dbbc --- /dev/null +++ b/internal/migrations/20231216063603_create_versions_table.down.sql @@ -0,0 +1 @@ +drop table if exists versions CASCADE; diff --git a/internal/migrations/20231216063603_create_versions_table.up.sql b/internal/migrations/20231216063603_create_versions_table.up.sql new file mode 100644 index 0000000..a26a1b4 --- /dev/null +++ b/internal/migrations/20231216063603_create_versions_table.up.sql @@ -0,0 +1,31 @@ +create table if not exists versions +( + code varchar(6) not null + primary key, + name varchar(150) not null, + host varchar(150) not null + unique, + timezone varchar(150) not null +); + +insert into versions (code, name, host, timezone) +values ('pl', 'Poland', 'www.plemiona.pl', 'Europe/Warsaw'), + ('uk', 'United Kingdom', 'www.tribalwars.co.uk', 'Europe/London'), + ('hu', 'Hungary', 'www.klanhaboru.hu', 'Europe/Budapest'), + ('it', 'Italy', 'www.tribals.it', 'Europe/Rome'), + ('fr', 'France', 'www.guerretribale.fr', 'Europe/Paris'), + ('us', 'United States', 'www.tribalwars.us', 'America/New_York'), + ('nl', 'The Netherlands', 'www.tribalwars.nl', 'Europe/Amsterdam'), + ('es', 'Spain', 'www.guerrastribales.es', 'Europe/Madrid'), + ('ro', 'Romania', 'www.triburile.ro', 'Europe/Bucharest'), + ('gr', 'Greece', 'www.fyletikesmaxes.gr', 'Europe/Athens'), + ('br', 'Brazil', 'www.tribalwars.com.br', 'America/Sao_Paulo'), + ('tr', 'Turkey', 'www.klanlar.org', 'Europe/Istanbul'), + ('cs', 'Czech Republic', 'www.divokekmeny.cz', 'Europe/Prague'), + ('ch', 'Switzerland', 'www.staemme.ch', 'Europe/Zurich'), + ('pt', 'Portugal', 'www.tribalwars.com.pt', 'Europe/Lisbon'), + ('en', 'International', 'www.tribalwars.net', 'Europe/London'), + ('de', 'Germany', 'www.die-staemme.de', 'Europe/Berlin'), + ('sk', 'Slovakia', 'www.divoke-kmene.sk', 'Europe/Bratislava'), + ('ru', 'Russia', 'www.voynaplemyon.com', 'Europe/Moscow') +ON CONFLICT DO NOTHING; diff --git a/internal/migrations/20231216063731_create_servers_table.down.sql b/internal/migrations/20231216063731_create_servers_table.down.sql new file mode 100644 index 0000000..ae6f784 --- /dev/null +++ b/internal/migrations/20231216063731_create_servers_table.down.sql @@ -0,0 +1 @@ +drop table if exists servers cascade; diff --git a/internal/migrations/20231216063731_create_servers_table.up.sql b/internal/migrations/20231216063731_create_servers_table.up.sql new file mode 100644 index 0000000..fc4cef0 --- /dev/null +++ b/internal/migrations/20231216063731_create_servers_table.up.sql @@ -0,0 +1,49 @@ +create table if not exists servers +( + key varchar(100) not null + primary key, + url varchar(255) not null, + open boolean default false, + special boolean default false, + num_players bigint default 0, + num_tribes bigint default 0, + num_villages bigint default 0, + config jsonb, + building_info jsonb, + unit_info jsonb, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null, + player_data_updated_at timestamp with time zone, + tribe_data_updated_at timestamp with time zone, + village_data_updated_at timestamp with time zone, + version_code varchar(6) not null + references versions, + player_snapshots_created_at timestamp with time zone, + tribe_snapshots_created_at timestamp with time zone, + ennoblement_data_updated_at timestamp with time zone, + num_player_villages bigint default 0, + num_barbarian_villages bigint default 0, + num_bonus_villages bigint default 0 +); + +insert into servers (key, url, open, special, num_players, num_tribes, num_villages, config, building_info, unit_info, created_at, player_data_updated_at, tribe_data_updated_at, village_data_updated_at, version_code, player_snapshots_created_at, tribe_snapshots_created_at, ennoblement_data_updated_at, num_player_villages, num_barbarian_villages, num_bonus_villages) +values ('pls1', 'https://pls1.plemiona.pl', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'pl', null, null, null, 0, 0, 0), + ('uks1', 'https://uks1.tribalwars.co.uk', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'uk', null, null, null, 0, 0, 0), + ('hus1', 'https://hus1.klanhaboru.hu', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'hu', null, null, null, 0, 0, 0), + ('its1', 'https://its1.tribals.it', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'it', null, null, null, 0, 0, 0), + ('frs1', 'https://frs1.guerretribale.fr', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'fr', null, null, null, 0, 0, 0), + ('uss1', 'https://uss1.tribalwars.us', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'us', null, null, null, 0, 0, 0), + ('nls1', 'https://nls1.tribalwars.nl', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'nl', null, null, null, 0, 0, 0), + ('ess1', 'https://ess1.guerrastribales.es', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'es', null, null, null, 0, 0, 0), + ('ros1', 'https://ros1.triburile.ro', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'ro', null, null, null, 0, 0, 0), + ('grs1', 'https://grs1.fyletikesmaxes.gr', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'gr', null, null, null, 0, 0, 0), + ('brs1', 'https://brs1.tribalwars.com.br', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'br', null, null, null, 0, 0, 0), + ('trs1', 'https://trs1.klanlar.org', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'tr', null, null, null, 0, 0, 0), + ('css1', 'https://css1.divokekmeny.cz', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'cs', null, null, null, 0, 0, 0), + ('chs1', 'https://chs1.staemme.ch', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'ch', null, null, null, 0, 0, 0), + ('pts1', 'https://pts1.tribalwars.com.pt', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'pt', null, null, null, 0, 0, 0), + ('ens1', 'https://ens1.tribalwars.net', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'en', null, null, null, 0, 0, 0), + ('des1', 'https://des1.die-staemme.de', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'de', null, null, null, 0, 0, 0), + ('sks1', 'https://sks1.divoke-kmene.sk', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'sk', null, null, null, 0, 0, 0), + ('master', 'https://www.tribalwars.co.uk', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'uk', null, null, null, 0, 0, 0), + ('rus1', 'https://rus1.voynaplemyon.com', false, true, 0, 0, 0, '{"Win": {"Check": 0}, "Ally": {"Limit": 0, "Levels": 0, "NoHarm": 0, "NoJoin": 0, "NoLeave": 0, "FixedAllies": 0, "NoOtherSupport": 0, "XpRequirements": "", "AllytimeSupport": 0, "PointsMemberCount": 0, "NoOtherSupportType": 0, "WarsAutoacceptDays": 0, "WarsMemberRequirement": 0, "WarsPointsRequirement": 0}, "Game": {"Tech": 0, "Event": 0, "Hauls": 0, "Archer": 0, "Church": 0, "Knight": 0, "HaulsMax": 0, "FakeLimit": 0, "FarmLimit": 0, "HaulsBase": 0, "Stronghold": 0, "Watchtower": 0, "BarbarianRise": 0, "BaseProduction": 0, "KnightNewItems": 0, "SuppressEvents": 0, "BarbarianShrink": 0, "BuildtimeFormula": 0, "BarbarianMaxPoints": 0}, "Misc": {"Tutorial": 0, "KillRanking": 0, "TradeCancelTime": 0}, "Snob": {"Gold": 0, "Rise": 0, "Factor": 0, "MaxDist": 0, "CoinIron": 0, "CoinWood": 0, "CoinStone": 0, "CheapRebuild": 0, "NoBarbConquer": 0}, "Build": {"Destroy": 0}, "Coord": {"Func": 0, "Inner": 0, "MapSize": 0, "BonusNew": 0, "SelectStart": 0, "NobleRestart": 0, "BonusVillages": 0, "EmptyVillages": 0, "StartVillages": 0, "VillageMoveWait": 0}, "Moral": 0, "Night": {"Active": 0, "EndHour": 0, "Duration": 0, "DefFactor": 0, "StartHour": 0}, "Sleep": {"Max": 0, "Min": 0, "Delay": 0, "Active": 0, "MaxAwake": 0, "MinAwake": 0, "WarnTime": 0}, "Speed": 0, "Newbie": {"Days": 0, "Ratio": 0, "RatioDays": 0, "RemoveNewbieVillages": 0}, "Sitter": {"Allow": 0}, "Commands": {"MillisArrival": 0, "CommandCancelTime": 0}, "Buildings": {"CustomFarm": 0, "CustomHide": 0, "CustomIron": 0, "CustomMain": 0, "CustomSnob": 0, "CustomWall": 0, "CustomWood": 0, "CustomPlace": 0, "CustomSmith": 0, "CustomStone": 0, "CustomChurch": 0, "CustomGarage": 0, "CustomMarket": 0, "CustomStable": 0, "CustomStatue": 0, "CustomStorage": 0, "CustomBarracks": 0, "CustomWatchtower": 0}, "UnitSpeed": 0}', '{"Farm": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Hide": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Iron": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Main": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Snob": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wall": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Wood": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Place": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Smith": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stone": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Garage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Market": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Stable": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Statue": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Storage": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Barracks": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}, "Watchtower": {"Pop": 0, "Iron": 0, "Wood": 0, "Stone": 0, "MaxLevel": 0, "MinLevel": 0, "BuildTime": 0, "PopFactor": 0, "IronFactor": 0, "WoodFactor": 0, "StoneFactor": 0, "BuildTimeFactor": 0}}', '{"Axe": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Ram": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Snob": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Heavy": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Light": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Spear": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Sword": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Archer": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Knight": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Marcher": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Militia": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}, "Catapult": {"Pop": 0, "Carry": 0, "Speed": 0, "Attack": 0, "Defense": 0, "BuildTime": 0, "DefenseArcher": 0, "DefenseCavalry": 0}}', CURRENT_TIMESTAMP, null, null, null, 'ru', null, null, null, 0, 0, 0) +ON CONFLICT DO NOTHING; diff --git a/internal/migrations/20231216063825_create_tribes_table.down.sql b/internal/migrations/20231216063825_create_tribes_table.down.sql new file mode 100644 index 0000000..5141f04 --- /dev/null +++ b/internal/migrations/20231216063825_create_tribes_table.down.sql @@ -0,0 +1 @@ +drop table if exists tribes cascade; diff --git a/internal/migrations/20231216063825_create_tribes_table.up.sql b/internal/migrations/20231216063825_create_tribes_table.up.sql new file mode 100644 index 0000000..2118bc0 --- /dev/null +++ b/internal/migrations/20231216063825_create_tribes_table.up.sql @@ -0,0 +1,35 @@ +create table if not exists tribes +( + id bigint not null, + server_key varchar(100) not null + references servers, + name varchar(255) not null, + tag varchar(10) not null, + num_members bigint default 0, + num_villages bigint default 0, + points bigint default 0, + all_points bigint default 0, + rank bigint default 0, + dominance double precision default 0, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null, + deleted_at timestamp with time zone, + rank_att bigint default 0, + score_att bigint default 0, + rank_def bigint default 0, + score_def bigint default 0, + rank_sup bigint default 0, + score_sup bigint default 0, + rank_total bigint default 0, + score_total bigint default 0, + profile_url varchar(150), + best_rank bigint default 999999, + best_rank_at timestamp with time zone default CURRENT_TIMESTAMP not null, + most_points bigint default 0, + most_points_at timestamp with time zone default CURRENT_TIMESTAMP not null, + most_villages bigint default 0, + most_villages_at timestamp with time zone default CURRENT_TIMESTAMP not null, + primary key (id, server_key) +); + +create index if not exists tribes_server_key_idx + on tribes (server_key); diff --git a/internal/migrations/20231216064247_create_players_table.down.sql b/internal/migrations/20231216064247_create_players_table.down.sql new file mode 100644 index 0000000..676aefd --- /dev/null +++ b/internal/migrations/20231216064247_create_players_table.down.sql @@ -0,0 +1 @@ +drop table if exists players cascade; diff --git a/internal/migrations/20231216064247_create_players_table.up.sql b/internal/migrations/20231216064247_create_players_table.up.sql new file mode 100644 index 0000000..abe0a9b --- /dev/null +++ b/internal/migrations/20231216064247_create_players_table.up.sql @@ -0,0 +1,33 @@ +create table if not exists players +( + id bigint not null, + server_key varchar(100) not null + references servers, + name varchar(150) not null, + num_villages bigint default 0, + points bigint default 0, + rank bigint default 0, + tribe_id bigint, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null, + deleted_at timestamp with time zone, + rank_att bigint default 0, + score_att bigint default 0, + rank_def bigint default 0, + score_def bigint default 0, + rank_sup bigint default 0, + score_sup bigint default 0, + rank_total bigint default 0, + score_total bigint default 0, + profile_url varchar(150), + best_rank bigint default 999999, + best_rank_at timestamp with time zone default CURRENT_TIMESTAMP not null, + most_points bigint default 0, + most_points_at timestamp with time zone default CURRENT_TIMESTAMP not null, + most_villages bigint default 0, + most_villages_at timestamp with time zone default CURRENT_TIMESTAMP not null, + last_activity_at timestamp with time zone default CURRENT_TIMESTAMP not null, + primary key (id, server_key) +); + +create index if not exists players_server_key_idx + on players (server_key); diff --git a/internal/migrations/20231216064325_create_ennoblements_table.down.sql b/internal/migrations/20231216064325_create_ennoblements_table.down.sql new file mode 100644 index 0000000..e5908d8 --- /dev/null +++ b/internal/migrations/20231216064325_create_ennoblements_table.down.sql @@ -0,0 +1 @@ +drop table if exists ennoblements cascade; diff --git a/internal/migrations/20231216064325_create_ennoblements_table.up.sql b/internal/migrations/20231216064325_create_ennoblements_table.up.sql new file mode 100644 index 0000000..31170f7 --- /dev/null +++ b/internal/migrations/20231216064325_create_ennoblements_table.up.sql @@ -0,0 +1,37 @@ +create table if not exists ennoblements +( + id bigint generated by default as identity + primary key, + server_key varchar(100) not null + references servers, + village_id bigint not null, + new_owner_id bigint, + new_tribe_id bigint, + old_owner_id bigint, + old_tribe_id bigint, + points bigint default 0, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null +); + +create unique index if not exists ennoblements_hash_key + on ennoblements (hash_record_extended( + ROW (server_key, village_id, new_owner_id, new_tribe_id, old_owner_id, old_tribe_id, points, created_at), + 0::bigint)); + +create index if not exists ennoblements_server_key_created_at_idx + on ennoblements (server_key, created_at); + +create index if not exists ennoblements_server_key_village_id_idx + on ennoblements (server_key, village_id); + +create index if not exists ennoblements_server_key_new_owner_id_idx + on ennoblements (server_key, new_owner_id); + +create index if not exists ennoblements_server_key_old_owner_id_idx + on ennoblements (server_key, old_owner_id); + +create index if not exists ennoblements_server_key_new_tribe_id_idx + on ennoblements (server_key, new_tribe_id); + +create index if not exists ennoblements_server_key_old_tribe_id_idx + on ennoblements (server_key, old_tribe_id); diff --git a/internal/migrations/20231216064433_create_player_snapshots_table.down.sql b/internal/migrations/20231216064433_create_player_snapshots_table.down.sql new file mode 100644 index 0000000..ad97025 --- /dev/null +++ b/internal/migrations/20231216064433_create_player_snapshots_table.down.sql @@ -0,0 +1 @@ +drop table if exists player_snapshots cascade; diff --git a/internal/migrations/20231216064433_create_player_snapshots_table.up.sql b/internal/migrations/20231216064433_create_player_snapshots_table.up.sql new file mode 100644 index 0000000..32694a7 --- /dev/null +++ b/internal/migrations/20231216064433_create_player_snapshots_table.up.sql @@ -0,0 +1,24 @@ +create table if not exists player_snapshots +( + id bigint generated by default as identity + primary key, + player_id bigint not null, + num_villages bigint default 0, + points bigint default 0, + rank bigint default 0, + tribe_id bigint, + server_key varchar(100) not null + references servers, + date date not null, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null, + rank_att bigint default 0, + score_att bigint default 0, + rank_def bigint default 0, + score_def bigint default 0, + rank_sup bigint default 0, + score_sup bigint default 0, + rank_total bigint default 0, + score_total bigint default 0, + unique (player_id, server_key, date), + foreign key (player_id, server_key) references players +); diff --git a/internal/migrations/20231216064559_create_tribe_snapshots_table.down.sql b/internal/migrations/20231216064559_create_tribe_snapshots_table.down.sql new file mode 100644 index 0000000..7161901 --- /dev/null +++ b/internal/migrations/20231216064559_create_tribe_snapshots_table.down.sql @@ -0,0 +1 @@ +drop table if exists tribe_snapshots cascade; diff --git a/internal/migrations/20231216064559_create_tribe_snapshots_table.up.sql b/internal/migrations/20231216064559_create_tribe_snapshots_table.up.sql new file mode 100644 index 0000000..50b0b37 --- /dev/null +++ b/internal/migrations/20231216064559_create_tribe_snapshots_table.up.sql @@ -0,0 +1,26 @@ +create table if not exists tribe_snapshots +( + id bigint generated by default as identity + primary key, + tribe_id bigint not null, + server_key varchar(100) not null + references servers, + num_members bigint default 0, + num_villages bigint default 0, + points bigint default 0, + all_points bigint default 0, + rank bigint default 0, + dominance double precision default 0, + date date not null, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null, + rank_att bigint default 0, + score_att bigint default 0, + rank_def bigint default 0, + score_def bigint default 0, + rank_sup bigint default 0, + score_sup bigint default 0, + rank_total bigint default 0, + score_total bigint default 0, + unique (tribe_id, server_key, date), + foreign key (tribe_id, server_key) references tribes +); diff --git a/internal/migrations/20231216064617_create_tribe_changes_table.down.sql b/internal/migrations/20231216064617_create_tribe_changes_table.down.sql new file mode 100644 index 0000000..09d00bd --- /dev/null +++ b/internal/migrations/20231216064617_create_tribe_changes_table.down.sql @@ -0,0 +1 @@ +drop table if exists tribe_changes cascade; diff --git a/internal/migrations/20231216064617_create_tribe_changes_table.up.sql b/internal/migrations/20231216064617_create_tribe_changes_table.up.sql new file mode 100644 index 0000000..9689880 --- /dev/null +++ b/internal/migrations/20231216064617_create_tribe_changes_table.up.sql @@ -0,0 +1,26 @@ +create table if not exists tribe_changes +( + id bigint generated by default as identity + primary key, + player_id bigint not null, + new_tribe_id bigint, + old_tribe_id bigint, + server_key varchar(100) not null + references servers, + created_at timestamp with time zone default CURRENT_TIMESTAMP not null, + foreign key (player_id, server_key) references players +); + +create index if not exists tribe_changes_server_key_player_id_idx + on tribe_changes (server_key, player_id); + +create unique index if not exists tribe_changes_hash_key + on tribe_changes (hash_record_extended( + ROW (player_id, new_tribe_id, old_tribe_id, server_key, date_trunc('hours'::text, (created_at AT TIME ZONE 'UTC'::text))), + 0::bigint)); + +create index if not exists tribe_changes_server_key_new_tribe_id_idx + on tribe_changes (server_key, new_tribe_id); + +create index if not exists tribe_changes_server_key_old_tribe_id_idx + on tribe_changes (server_key, old_tribe_id); diff --git a/internal/migrations/migrations.go b/internal/migrations/migrations.go new file mode 100644 index 0000000..ce19676 --- /dev/null +++ b/internal/migrations/migrations.go @@ -0,0 +1,23 @@ +package migrations + +import ( + "embed" + + "github.com/uptrace/bun" + "github.com/uptrace/bun/migrate" +) + +var migrations = migrate.NewMigrations() + +//go:embed *.sql +var sqlMigrations embed.FS + +func init() { + if err := migrations.Discover(sqlMigrations); err != nil { + panic(err) + } +} + +func NewMigrator(db *bun.DB, opts ...migrate.MigratorOption) *migrate.Migrator { + return migrate.NewMigrator(db, migrations, opts...) +} diff --git a/k8s/base/jobs.yml b/k8s/base/jobs.yml new file mode 100644 index 0000000..03f1178 --- /dev/null +++ b/k8s/base/jobs.yml @@ -0,0 +1,34 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: twhelp-migrations-job +spec: + template: + spec: + containers: + - name: twhelp-migrations + image: twhelp + args: [db, migrate] + env: + - name: APP_MODE + value: development + - name: DB_CONNECTION_STRING + valueFrom: + secretKeyRef: + name: twhelp-secret + key: db-connection-string + - name: DB_MAX_OPEN_CONNS + value: "1" + - name: DB_MAX_IDLE_CONNS + value: "1" + - name: DB_READ_TIMEOUT + value: 60s + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + restartPolicy: Never diff --git a/k8s/base/kustomization.yml b/k8s/base/kustomization.yml new file mode 100644 index 0000000..f43cae7 --- /dev/null +++ b/k8s/base/kustomization.yml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - jobs.yml +images: + - name: twhelp + newName: twhelp + newTag: latest diff --git a/k8s/overlays/dev/kustomization.yml b/k8s/overlays/dev/kustomization.yml new file mode 100644 index 0000000..d0601d7 --- /dev/null +++ b/k8s/overlays/dev/kustomization.yml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +nameSuffix: -dev +resources: + - secret.yml + - ../../base diff --git a/k8s/overlays/dev/secret.yml b/k8s/overlays/dev/secret.yml new file mode 100644 index 0000000..650ea0d --- /dev/null +++ b/k8s/overlays/dev/secret.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: twhelp-secret +type: Opaque +data: + # postgres://twhelp:twhelp@twhelpdb-postgresql:5432/twhelp?sslmode=disable + db-connection-string: cG9zdGdyZXM6Ly90d2hlbHA6dHdoZWxwQHR3aGVscGRiLXBvc3RncmVzcWw6NTQzMi90d2hlbHA/c3NsbW9kZT1kaXNhYmxl + # amqp://twhelp:twhelp@twhelprmq-rabbitmq:5672/ + rabbit-connection-string: YW1xcDovL3R3aGVscDp0d2hlbHBAdHdoZWxwcm1xLXJhYmJpdG1xOjU2NzIv