mirror of
https://git.ptzo.gdn/feditools/relay.git
synced 2024-09-21 14:27:11 +00:00
Metrics (#53)
This commit is contained in:
parent
32fb83af2f
commit
30e1682104
17
Jenkinsfile
vendored
17
Jenkinsfile
vendored
@ -1,12 +1,11 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
environment {
|
environment {
|
||||||
|
BUILD_IMAGE = 'gobuild:1.18'
|
||||||
|
BUILD_ARGS = '-e GOCACHE=/gocache -e HOME=${WORKSPACE} -v /var/lib/jenkins/gocache:/gocache -v /var/lib/jenkins/go/pkg:/go/pkg'
|
||||||
PATH = '/go/bin:~/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin'
|
PATH = '/go/bin:~/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin'
|
||||||
composeFile = "deployments/docker-compose-integration.yaml"
|
composeFile = "deployments/docker-compose-integration.yaml"
|
||||||
networkName = "network-${env.BUILD_TAG}"
|
networkName = "network-${env.BUILD_TAG}"
|
||||||
registry = 'tyrm/relay'
|
|
||||||
registryCredential = 'docker-io-feditools'
|
registryCredential = 'docker-io-feditools'
|
||||||
dockerImage = ''
|
|
||||||
gitDescribe = ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
agent any
|
agent any
|
||||||
@ -16,8 +15,8 @@ pipeline {
|
|||||||
stage('Build Static Assets') {
|
stage('Build Static Assets') {
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'gobuild:1.18'
|
image "${BUILD_IMAGE}"
|
||||||
args '-e HOME=${WORKSPACE}'
|
args "${BUILD_ARGS}"
|
||||||
reuseNode true
|
reuseNode true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,8 +52,8 @@ pipeline {
|
|||||||
stage('Test') {
|
stage('Test') {
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'gobuild:1.18'
|
image "${BUILD_IMAGE}"
|
||||||
args '--network ${networkName} -e HOME=${WORKSPACE}'
|
args "--network ${networkName} ${BUILD_ARGS}"
|
||||||
reuseNode true
|
reuseNode true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,8 +78,8 @@ pipeline {
|
|||||||
stage('Build Snapshot') {
|
stage('Build Snapshot') {
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'gobuild:1.18'
|
image "${BUILD_IMAGE}"
|
||||||
args '--network ${networkName} -e HOME=${WORKSPACE}'
|
args "--network ${networkName} ${BUILD_ARGS}"
|
||||||
reuseNode true
|
reuseNode true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
Makefile
8
Makefile
@ -31,13 +31,13 @@ fmt:
|
|||||||
@go fmt $(shell go list ./... | grep -v /vendor/)
|
@go fmt $(shell go list ./... | grep -v /vendor/)
|
||||||
|
|
||||||
i18n-extract:
|
i18n-extract:
|
||||||
goi18n extract -outdir locales
|
goi18n extract -format yaml -outdir web/locales
|
||||||
|
|
||||||
i18n-merge:
|
i18n-merge:
|
||||||
goi18n merge -outdir locales locales/active.*.toml locales/translate.*.toml
|
goi18n merge -format yaml -outdir locales web/locales/active.*.toml web/locales/translate.*.toml
|
||||||
|
|
||||||
i18n-translations:
|
i18n-translations:
|
||||||
goi18n merge -outdir locales locales/active.*.toml
|
goi18n merge -format yaml -outdir locales web/locales/active.*.toml
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@echo linting
|
@echo linting
|
||||||
@ -66,4 +66,4 @@ tidy:
|
|||||||
vendor: tidy
|
vendor: tidy
|
||||||
go mod vendor
|
go mod vendor
|
||||||
|
|
||||||
.PHONY: build-snapshot bun-new-migration clean fmt lint stage-static npm-scss npm-upgrade docker-restart docker-start docker-stop release stage-static test test-ext test-race test-race-ext test-verbose tidy vendor
|
.PHONY: build-snapshot bun-new-migration clean fmt i18n-extract i18n-merge i18n-translations lint stage-static npm-scss npm-upgrade docker-restart docker-start docker-stop release stage-static test test-ext test-race test-race-ext test-verbose tidy vendor
|
||||||
|
@ -3,7 +3,6 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/feditools/go-lib"
|
"github.com/feditools/go-lib"
|
||||||
liblanguage "github.com/feditools/go-lib/language"
|
|
||||||
"github.com/feditools/go-lib/metrics"
|
"github.com/feditools/go-lib/metrics"
|
||||||
"github.com/feditools/relay/internal/config"
|
"github.com/feditools/relay/internal/config"
|
||||||
"github.com/feditools/relay/internal/db"
|
"github.com/feditools/relay/internal/db"
|
||||||
@ -12,6 +11,7 @@ import (
|
|||||||
"github.com/feditools/relay/internal/http/activitypub"
|
"github.com/feditools/relay/internal/http/activitypub"
|
||||||
"github.com/feditools/relay/internal/http/static"
|
"github.com/feditools/relay/internal/http/static"
|
||||||
"github.com/feditools/relay/internal/http/webapp"
|
"github.com/feditools/relay/internal/http/webapp"
|
||||||
|
liblanguage "github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/logic"
|
"github.com/feditools/relay/internal/logic"
|
||||||
"github.com/feditools/relay/internal/runner"
|
"github.com/feditools/relay/internal/runner"
|
||||||
"github.com/feditools/relay/internal/token"
|
"github.com/feditools/relay/internal/token"
|
||||||
|
@ -3,7 +3,6 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
"github.com/feditools/go-lib/metrics/statsd"
|
"github.com/feditools/go-lib/metrics/statsd"
|
||||||
"github.com/feditools/relay/cmd/relay/action"
|
"github.com/feditools/relay/cmd/relay/action"
|
||||||
"github.com/feditools/relay/internal/clock"
|
"github.com/feditools/relay/internal/clock"
|
||||||
@ -12,6 +11,7 @@ import (
|
|||||||
"github.com/feditools/relay/internal/fedi"
|
"github.com/feditools/relay/internal/fedi"
|
||||||
"github.com/feditools/relay/internal/http"
|
"github.com/feditools/relay/internal/http"
|
||||||
"github.com/feditools/relay/internal/kv/redis"
|
"github.com/feditools/relay/internal/kv/redis"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/logic/logic1"
|
"github.com/feditools/relay/internal/logic/logic1"
|
||||||
"github.com/feditools/relay/internal/runner/faktory"
|
"github.com/feditools/relay/internal/runner/faktory"
|
||||||
"github.com/feditools/relay/internal/token"
|
"github.com/feditools/relay/internal/token"
|
||||||
@ -111,7 +111,7 @@ var Start action.Action = func(topCtx context.Context) error {
|
|||||||
|
|
||||||
// create logic module
|
// create logic module
|
||||||
l.Debug("creating logic module")
|
l.Debug("creating logic module")
|
||||||
logicMod, err := logic1.New(ctx, clockMod, dbClient, httpClient, tokz)
|
logicMod, err := logic1.New(ctx, clockMod, dbClient, httpClient, kvClient, tokz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Errorf("logic: %s", err.Error())
|
l.Errorf("logic: %s", err.Error())
|
||||||
cancel()
|
cancel()
|
||||||
|
@ -23,6 +23,8 @@ func Server(cmd *cobra.Command, values config.Values) {
|
|||||||
cmd.PersistentFlags().String(config.Keys.WebappBootstrapCSSIntegrity, values.WebappBootstrapCSSIntegrity, usage.WebappBootstrapCSSIntegrity)
|
cmd.PersistentFlags().String(config.Keys.WebappBootstrapCSSIntegrity, values.WebappBootstrapCSSIntegrity, usage.WebappBootstrapCSSIntegrity)
|
||||||
cmd.PersistentFlags().String(config.Keys.WebappBootstrapJSURI, values.WebappBootstrapJSURI, usage.WebappBootstrapJSURI)
|
cmd.PersistentFlags().String(config.Keys.WebappBootstrapJSURI, values.WebappBootstrapJSURI, usage.WebappBootstrapJSURI)
|
||||||
cmd.PersistentFlags().String(config.Keys.WebappBootstrapJSIntegrity, values.WebappBootstrapJSIntegrity, usage.WebappBootstrapJSIntegrity)
|
cmd.PersistentFlags().String(config.Keys.WebappBootstrapJSIntegrity, values.WebappBootstrapJSIntegrity, usage.WebappBootstrapJSIntegrity)
|
||||||
|
cmd.PersistentFlags().String(config.Keys.WebappChartJSURI, values.WebappChartJSURI, usage.WebappChartJSURI)
|
||||||
|
cmd.PersistentFlags().String(config.Keys.WebappChartJSIntegrity, values.WebappChartJSIntegrity, usage.WebappChartJSIntegrity)
|
||||||
cmd.PersistentFlags().String(config.Keys.WebappFontAwesomeCSSURI, values.WebappFontAwesomeCSSURI, usage.WebappFontAwesomeCSSURI)
|
cmd.PersistentFlags().String(config.Keys.WebappFontAwesomeCSSURI, values.WebappFontAwesomeCSSURI, usage.WebappFontAwesomeCSSURI)
|
||||||
cmd.PersistentFlags().String(config.Keys.WebappFontAwesomeCSSIntegrity, values.WebappFontAwesomeCSSIntegrity, usage.WebappFontAwesomeCSSIntegrity)
|
cmd.PersistentFlags().String(config.Keys.WebappFontAwesomeCSSIntegrity, values.WebappFontAwesomeCSSIntegrity, usage.WebappFontAwesomeCSSIntegrity)
|
||||||
cmd.PersistentFlags().String(config.Keys.WebappLogoSrcDark, values.WebappLogoSrcDark, usage.WebappLogoSrcDark)
|
cmd.PersistentFlags().String(config.Keys.WebappLogoSrcDark, values.WebappLogoSrcDark, usage.WebappLogoSrcDark)
|
||||||
|
8
go.mod
8
go.mod
@ -5,7 +5,7 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
github.com/contribsys/faktory v1.6.1
|
github.com/contribsys/faktory v1.6.1
|
||||||
github.com/contribsys/faktory_worker_go v1.6.0
|
github.com/contribsys/faktory_worker_go v1.6.0
|
||||||
github.com/feditools/go-lib v0.15.2-0.20220810024219-2d57c75a871e
|
github.com/feditools/go-lib v0.16.0
|
||||||
github.com/go-fed/activity v1.0.0
|
github.com/go-fed/activity v1.0.0
|
||||||
github.com/go-fed/httpsig v1.1.0
|
github.com/go-fed/httpsig v1.1.0
|
||||||
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
|
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
|
||||||
@ -19,6 +19,7 @@ require (
|
|||||||
github.com/jackc/pgconn v1.13.0
|
github.com/jackc/pgconn v1.13.0
|
||||||
github.com/jackc/pgx/v4 v4.17.0
|
github.com/jackc/pgx/v4 v4.17.0
|
||||||
github.com/nickname76/telegrambot v1.1.1
|
github.com/nickname76/telegrambot v1.1.1
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.2.0
|
||||||
github.com/rbcervilla/redisstore/v8 v8.1.0
|
github.com/rbcervilla/redisstore/v8 v8.1.0
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/speps/go-hashids/v2 v2.0.1
|
github.com/speps/go-hashids/v2 v2.0.1
|
||||||
@ -33,6 +34,8 @@ require (
|
|||||||
github.com/uptrace/bun/extra/bundebug v1.1.7
|
github.com/uptrace/bun/extra/bundebug v1.1.7
|
||||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
|
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
|
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
|
||||||
|
golang.org/x/text v0.3.7
|
||||||
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
modernc.org/sqlite v1.17.1
|
modernc.org/sqlite v1.17.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -71,7 +74,6 @@ require (
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/nickname76/repeater v1.0.1 // indirect
|
github.com/nickname76/repeater v1.0.1 // indirect
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.2.0 // indirect
|
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||||
@ -88,11 +90,9 @@ require (
|
|||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
|
||||||
golang.org/x/tools v0.1.10 // indirect
|
golang.org/x/tools v0.1.10 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
|
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
|
||||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
lukechampine.com/uint128 v1.2.0 // indirect
|
lukechampine.com/uint128 v1.2.0 // indirect
|
||||||
modernc.org/cc/v3 v3.36.0 // indirect
|
modernc.org/cc/v3 v3.36.0 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
|
||||||
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
@ -90,8 +90,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
|||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/feditools/go-lib v0.15.2-0.20220810024219-2d57c75a871e h1:cvxBlyoDUq1KOnWD0Xb8muGu+X70T8vFe2UYdvpS9Es=
|
github.com/feditools/go-lib v0.16.0 h1:sxAxvRb97Xn/jaDOSljMsWiXTVulbCZZHhr4sMRDrZE=
|
||||||
github.com/feditools/go-lib v0.15.2-0.20220810024219-2d57c75a871e/go.mod h1:LtdLBvApYAhdblS6rTGQ12ZzySI9/6PyTiZlxw5uX10=
|
github.com/feditools/go-lib v0.16.0/go.mod h1:kMw3Dl5vJ2j0dHtD5OHPy9lsm8v+p/szKM01yqX+gMY=
|
||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
|
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
|
||||||
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
@ -45,6 +45,8 @@ type KeyNames struct {
|
|||||||
WebappBootstrapCSSIntegrity string
|
WebappBootstrapCSSIntegrity string
|
||||||
WebappBootstrapJSURI string
|
WebappBootstrapJSURI string
|
||||||
WebappBootstrapJSIntegrity string
|
WebappBootstrapJSIntegrity string
|
||||||
|
WebappChartJSURI string
|
||||||
|
WebappChartJSIntegrity string
|
||||||
WebappFontAwesomeCSSURI string
|
WebappFontAwesomeCSSURI string
|
||||||
WebappFontAwesomeCSSIntegrity string
|
WebappFontAwesomeCSSIntegrity string
|
||||||
WebappLogoSrcDark string
|
WebappLogoSrcDark string
|
||||||
@ -104,6 +106,8 @@ var Keys = KeyNames{
|
|||||||
WebappBootstrapCSSIntegrity: "webapp-bootstrap-css-integrity",
|
WebappBootstrapCSSIntegrity: "webapp-bootstrap-css-integrity",
|
||||||
WebappBootstrapJSURI: "webapp-bootstrap-js-uri",
|
WebappBootstrapJSURI: "webapp-bootstrap-js-uri",
|
||||||
WebappBootstrapJSIntegrity: "webapp-bootstrap-js-integrity",
|
WebappBootstrapJSIntegrity: "webapp-bootstrap-js-integrity",
|
||||||
|
WebappChartJSURI: "webapp-chart-js-uri",
|
||||||
|
WebappChartJSIntegrity: "webapp-chart-js-integrity",
|
||||||
WebappFontAwesomeCSSURI: "webapp-fontawesome-css-uri",
|
WebappFontAwesomeCSSURI: "webapp-fontawesome-css-uri",
|
||||||
WebappFontAwesomeCSSIntegrity: "webapp-fontawesome-css-integrity",
|
WebappFontAwesomeCSSIntegrity: "webapp-fontawesome-css-integrity",
|
||||||
WebappLogoSrcDark: "webapp-logo-src-dark",
|
WebappLogoSrcDark: "webapp-logo-src-dark",
|
||||||
|
@ -45,6 +45,8 @@ type Values struct {
|
|||||||
WebappBootstrapCSSIntegrity string
|
WebappBootstrapCSSIntegrity string
|
||||||
WebappBootstrapJSURI string
|
WebappBootstrapJSURI string
|
||||||
WebappBootstrapJSIntegrity string
|
WebappBootstrapJSIntegrity string
|
||||||
|
WebappChartJSURI string
|
||||||
|
WebappChartJSIntegrity string
|
||||||
WebappFontAwesomeCSSURI string
|
WebappFontAwesomeCSSURI string
|
||||||
WebappFontAwesomeCSSIntegrity string
|
WebappFontAwesomeCSSIntegrity string
|
||||||
WebappLogoSrcDark string
|
WebappLogoSrcDark string
|
||||||
@ -104,6 +106,8 @@ var Defaults = Values{
|
|||||||
WebappBootstrapCSSIntegrity: "sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor",
|
WebappBootstrapCSSIntegrity: "sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor",
|
||||||
WebappBootstrapJSURI: "https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js",
|
WebappBootstrapJSURI: "https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js",
|
||||||
WebappBootstrapJSIntegrity: "sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2",
|
WebappBootstrapJSIntegrity: "sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2",
|
||||||
|
WebappChartJSURI: "https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js",
|
||||||
|
WebappChartJSIntegrity: "sha384-9MhbyIRcBVQiiC7FSd7T38oJNj2Zh+EfxS7/vjhBi4OOT78NlHSnzM31EZRWR1LZ",
|
||||||
WebappFontAwesomeCSSURI: "https://cdn.fedi.tools/vendor/fontawesome-free-6.1.1/css/all.min.css",
|
WebappFontAwesomeCSSURI: "https://cdn.fedi.tools/vendor/fontawesome-free-6.1.1/css/all.min.css",
|
||||||
WebappFontAwesomeCSSIntegrity: "sha384-/frq1SRXYH/bSyou/HUp/hib7RVN1TawQYja658FEOodR/FQBKVqT9Ol+Oz3Olq5",
|
WebappFontAwesomeCSSIntegrity: "sha384-/frq1SRXYH/bSyou/HUp/hib7RVN1TawQYja658FEOodR/FQBKVqT9Ol+Oz3Olq5",
|
||||||
WebappLogoSrcDark: "https://cdn.fedi.tools/img/feditools-logo-dark.svg",
|
WebappLogoSrcDark: "https://cdn.fedi.tools/img/feditools-logo-dark.svg",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package activitypub
|
package activitypub
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/feditools/go-lib/fedihelper"
|
"github.com/feditools/go-lib/fedihelper"
|
||||||
@ -120,5 +121,7 @@ func (m *Module) inboxPostHandler(w nethttp.ResponseWriter, r *nethttp.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go m.logic.MetricsIncReceived(context.Background(), instance.ID)
|
||||||
|
|
||||||
w.WriteHeader(nethttp.StatusAccepted)
|
w.WriteHeader(nethttp.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
16
internal/http/template/admin_instance_view.go
Normal file
16
internal/http/template/admin_instance_view.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/feditools/relay/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminInstanceViewName is the name of the admin block list template.
|
||||||
|
const AdminInstanceViewName = "admin_instance_view"
|
||||||
|
|
||||||
|
// AdminInstanceView contains the variables for the admin block list template.
|
||||||
|
type AdminInstanceView struct {
|
||||||
|
Common
|
||||||
|
|
||||||
|
Instance *models.Instance
|
||||||
|
Breadcrumbs *[]Breadcrumb
|
||||||
|
}
|
6
internal/http/template/breadcrumb.go
Normal file
6
internal/http/template/breadcrumb.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package template
|
||||||
|
|
||||||
|
type Breadcrumb struct {
|
||||||
|
HRef string
|
||||||
|
Text string
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/config"
|
"github.com/feditools/relay/internal/config"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"github.com/feditools/relay/internal/token"
|
"github.com/feditools/relay/internal/token"
|
||||||
@ -41,6 +41,7 @@ func New(tokz *token.Tokenizer) (*template.Template, error) {
|
|||||||
"pathAppAdminBlockExportCSV": path.GenAppAdminBlockExportCSV,
|
"pathAppAdminBlockExportCSV": path.GenAppAdminBlockExportCSV,
|
||||||
"pathAppAdminBlockExportJSON": path.GenAppAdminBlockExportJSON,
|
"pathAppAdminBlockExportJSON": path.GenAppAdminBlockExportJSON,
|
||||||
"pathAppAdminHome": path.GenAppAdminHomePath,
|
"pathAppAdminHome": path.GenAppAdminHomePath,
|
||||||
|
"pathAppAdminInstanceView": path.GenAppAdminInstanceViewPath,
|
||||||
"pathAppHome": path.GenAppHomePath,
|
"pathAppHome": path.GenAppHomePath,
|
||||||
"pathAppLog": path.GenAppLogPath,
|
"pathAppLog": path.GenAppLogPath,
|
||||||
"pathAppLogin": path.GenAppLoginPath,
|
"pathAppLogin": path.GenAppLoginPath,
|
||||||
|
@ -2,9 +2,9 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
libhttp "github.com/feditools/go-lib/http"
|
libhttp "github.com/feditools/go-lib/http"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package webapp
|
package webapp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/util"
|
"github.com/feditools/relay/internal/util"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -93,7 +93,7 @@ func (m *Module) doAddBlock(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
FormAddError: &libtemplate.Alert{
|
FormAddError: &libtemplate.Alert{
|
||||||
Color: libtemplate.ColorDanger,
|
Color: libtemplate.ColorDanger,
|
||||||
Text: localizer.TextBlockExists(domain).String(),
|
Text: localizer.TextBlockExistsDomain(domain).String(),
|
||||||
},
|
},
|
||||||
|
|
||||||
FormAddDomainValue: domain,
|
FormAddDomainValue: domain,
|
||||||
|
@ -2,9 +2,9 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/db"
|
"github.com/feditools/relay/internal/db"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/token"
|
"github.com/feditools/relay/internal/token"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -3,9 +3,9 @@ package webapp
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/db"
|
"github.com/feditools/relay/internal/db"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/token"
|
"github.com/feditools/relay/internal/token"
|
||||||
"github.com/feditools/relay/internal/util"
|
"github.com/feditools/relay/internal/util"
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
libhttp "github.com/feditools/go-lib/http"
|
libhttp "github.com/feditools/go-lib/http"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/util"
|
"github.com/feditools/relay/internal/util"
|
||||||
"io"
|
"io"
|
||||||
|
@ -2,9 +2,9 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -2,9 +2,9 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
libhttp "github.com/feditools/go-lib/http"
|
libhttp "github.com/feditools/go-lib/http"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
113
internal/http/webapp/admin_instance_view.go
Normal file
113
internal/http/webapp/admin_instance_view.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package webapp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
|
"github.com/feditools/relay/internal/db"
|
||||||
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
|
"github.com/feditools/relay/internal/models"
|
||||||
|
"github.com/feditools/relay/internal/path"
|
||||||
|
"github.com/feditools/relay/internal/token"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminInstanceViewGetHandler serves the instance info page.
|
||||||
|
func (m *Module) AdminInstanceViewGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := logger.WithField("func", "AdminInstanceViewGetHandler")
|
||||||
|
|
||||||
|
// lookup instance
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
kind, id, err := m.tokz.DecodeToken(vars[path.VarInstanceID])
|
||||||
|
if err != nil {
|
||||||
|
l.Debugf("decode token: %s", err.Error())
|
||||||
|
m.returnErrorPage(w, r, http.StatusBadRequest, "bad token")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if kind != token.KindInstance {
|
||||||
|
l.Debug("token is wrong kind")
|
||||||
|
m.returnErrorPage(w, r, http.StatusBadRequest, "bad token")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
instance, err := m.db.ReadInstance(r.Context(), id)
|
||||||
|
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||||
|
l.Errorf("db read instance: %s", err.Error())
|
||||||
|
m.returnErrorPage(w, r, http.StatusInternalServerError, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if errors.Is(err, db.ErrNoEntries) {
|
||||||
|
m.returnErrorPage(w, r, http.StatusNotFound, vars[path.VarInstanceID])
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.displayAdminInstanceView(w, r, displayAdminInstanceViewConfig{
|
||||||
|
Instance: instance,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type displayAdminInstanceViewConfig struct {
|
||||||
|
Alerts *[]libtemplate.Alert
|
||||||
|
|
||||||
|
Instance *models.Instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) displayAdminInstanceView(w http.ResponseWriter, r *http.Request, config displayAdminInstanceViewConfig) {
|
||||||
|
l := logger.WithField("func", "displayAdminInstanceView")
|
||||||
|
|
||||||
|
// get localizer
|
||||||
|
localizer := r.Context().Value(ContextKeyLocalizer).(*language.Localizer) //nolint
|
||||||
|
|
||||||
|
// Init template variables
|
||||||
|
tmplVars := &template.AdminInstanceView{
|
||||||
|
Common: template.Common{
|
||||||
|
PageTitle: localizer.TextInstance(1).String() + " " + config.Instance.UnicodeDomain(),
|
||||||
|
},
|
||||||
|
|
||||||
|
Breadcrumbs: &[]template.Breadcrumb{
|
||||||
|
{
|
||||||
|
Text: localizer.TextInstance(2).String(),
|
||||||
|
HRef: path.AppAdminInstance,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Text: config.Instance.UnicodeDomain(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Instance: config.Instance,
|
||||||
|
}
|
||||||
|
|
||||||
|
// alerts
|
||||||
|
tmplVars.Alerts = config.Alerts
|
||||||
|
|
||||||
|
// get metrics
|
||||||
|
deliverErrors, err := m.logic.MetricsGetDeliverErrorWeek(r.Context(), config.Instance.ID)
|
||||||
|
if err != nil {
|
||||||
|
l.Errorf("get metrics deliver error: %s", err.Error())
|
||||||
|
m.returnErrorPage(w, r, http.StatusInternalServerError, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
deliverSuccess, err := m.logic.MetricsGetDeliverSuccessWeek(r.Context(), config.Instance.ID)
|
||||||
|
if err != nil {
|
||||||
|
l.Errorf("get metrics deliver error: %s", err.Error())
|
||||||
|
m.returnErrorPage(w, r, http.StatusInternalServerError, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
received, err := m.logic.MetricsGetReceivedWeek(r.Context(), config.Instance.ID)
|
||||||
|
if err != nil {
|
||||||
|
l.Errorf("get metrics deliver error: %s", err.Error())
|
||||||
|
m.returnErrorPage(w, r, http.StatusInternalServerError, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmplVars.AddFooterExtraScript(JSAdminInstanceView(deliverErrors, deliverSuccess, received))
|
||||||
|
tmplVars.AddFooterScript(m.footerScriptChartJS)
|
||||||
|
|
||||||
|
m.executeTemplate(w, r, template.AdminInstanceViewName, tmplVars)
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package webapp
|
package webapp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package webapp
|
package webapp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -2,7 +2,7 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/feditools/go-lib/language"
|
"github.com/feditools/relay/internal/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
const jsAdminBlock = `
|
const jsAdminBlock = `
|
||||||
|
82
internal/http/webapp/js_chart.go
Normal file
82
internal/http/webapp/js_chart.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package webapp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/feditools/relay/internal/logic"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const jsAdminInstanceView = `
|
||||||
|
new Chart(document.getElementById("deliveryChartContainer"), {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: [%s],
|
||||||
|
datasets: [{
|
||||||
|
data: [%s],
|
||||||
|
label: "Error",
|
||||||
|
borderColor: "#c45850",
|
||||||
|
fill: false,
|
||||||
|
lineTension: 0.2
|
||||||
|
}, {
|
||||||
|
data: [%s],
|
||||||
|
label: "Success",
|
||||||
|
borderColor: "#3cba9f",
|
||||||
|
fill: false,
|
||||||
|
lineTension: 0.2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Chart(document.getElementById("receiveChartContainer"), {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: [%s],
|
||||||
|
datasets: [{
|
||||||
|
data: [%s],
|
||||||
|
label: "Received",
|
||||||
|
borderColor: "#3e95cd",
|
||||||
|
fill: false,
|
||||||
|
lineTension: 0.2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {}
|
||||||
|
});
|
||||||
|
`
|
||||||
|
|
||||||
|
func JSAdminInstanceView(deliverErrors, deliverSuccess, receive *logic.MetricsDataPointsTime) string {
|
||||||
|
labels := make([]string, len(*deliverErrors))
|
||||||
|
for i, dp := range *deliverErrors {
|
||||||
|
labels[i] = dp.X.Format("\"Jan 02 2006\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
deliverErrorsLen := len(*deliverErrors)
|
||||||
|
deliverErrorsData := make([]string, deliverErrorsLen)
|
||||||
|
for i, dp := range *deliverErrors {
|
||||||
|
deliverErrorsData[deliverErrorsLen-1-i] = strconv.FormatInt(int64(dp.Y), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
deliverSuccessLen := len(*deliverSuccess)
|
||||||
|
deliverSuccessData := make([]string, deliverSuccessLen)
|
||||||
|
for i, dp := range *deliverSuccess {
|
||||||
|
deliverSuccessData[deliverSuccessLen-1-i] = strconv.FormatInt(int64(dp.Y), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
receiveLen := len(*receive)
|
||||||
|
receiveData := make([]string, receiveLen)
|
||||||
|
for i, dp := range *receive {
|
||||||
|
receiveData[receiveLen-1-i] = strconv.FormatInt(int64(dp.Y), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
jsAdminInstanceView,
|
||||||
|
strings.Join(labels, ","),
|
||||||
|
strings.Join(deliverErrorsData, ","),
|
||||||
|
strings.Join(deliverSuccessData, ","),
|
||||||
|
strings.Join(labels, ","),
|
||||||
|
strings.Join(receiveData, ","),
|
||||||
|
)
|
||||||
|
}
|
@ -3,10 +3,10 @@ package webapp
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/feditools/go-lib"
|
"github.com/feditools/go-lib"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/db"
|
"github.com/feditools/relay/internal/db"
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
nethttp "net/http"
|
nethttp "net/http"
|
||||||
|
@ -2,9 +2,9 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
libhttp "github.com/feditools/go-lib/http"
|
libhttp "github.com/feditools/go-lib/http"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,7 @@ package webapp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
libhttp "github.com/feditools/go-lib/http"
|
libhttp "github.com/feditools/go-lib/http"
|
||||||
"github.com/feditools/go-lib/language"
|
"github.com/feditools/relay/internal/language"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
package webapp
|
|
@ -39,6 +39,7 @@ func (m *Module) Route(s *http.Server) error {
|
|||||||
admin.HandleFunc(path.AppAdminSubHome, m.AdminHomeGetHandler).Methods(nethttp.MethodGet)
|
admin.HandleFunc(path.AppAdminSubHome, m.AdminHomeGetHandler).Methods(nethttp.MethodGet)
|
||||||
admin.HandleFunc(path.AppAdminSubHome, m.AdminHomePostHandler).Methods(nethttp.MethodPost)
|
admin.HandleFunc(path.AppAdminSubHome, m.AdminHomePostHandler).Methods(nethttp.MethodPost)
|
||||||
admin.HandleFunc(path.AppAdminSubInstance, m.AdminInstanceGetHandler).Methods(nethttp.MethodGet)
|
admin.HandleFunc(path.AppAdminSubInstance, m.AdminInstanceGetHandler).Methods(nethttp.MethodGet)
|
||||||
|
admin.HandleFunc(path.AppAdminSubInstanceView, m.AdminInstanceViewGetHandler).Methods(nethttp.MethodGet)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ package webapp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -2,8 +2,8 @@ package webapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
"github.com/feditools/relay/internal/http/template"
|
"github.com/feditools/relay/internal/http/template"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/models"
|
"github.com/feditools/relay/internal/models"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -97,12 +97,6 @@ func (m *Module) makeNavbar(r *http.Request) (template.Navbar, error) {
|
|||||||
FAIcon: "house",
|
FAIcon: "house",
|
||||||
URL: path.AppHome,
|
URL: path.AppHome,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Text: l.TextActivityLog(1).String(),
|
|
||||||
MatchStr: path.ReAppLog,
|
|
||||||
FAIcon: "newspaper",
|
|
||||||
URL: path.AppLog,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show blocks page if any exist
|
// show blocks page if any exist
|
||||||
|
@ -3,7 +3,6 @@ package webapp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"github.com/feditools/go-lib/language"
|
|
||||||
"github.com/feditools/go-lib/metrics"
|
"github.com/feditools/go-lib/metrics"
|
||||||
libtemplate "github.com/feditools/go-lib/template"
|
libtemplate "github.com/feditools/go-lib/template"
|
||||||
"github.com/feditools/relay/internal/config"
|
"github.com/feditools/relay/internal/config"
|
||||||
@ -12,6 +11,7 @@ import (
|
|||||||
ihttp "github.com/feditools/relay/internal/http"
|
ihttp "github.com/feditools/relay/internal/http"
|
||||||
itemplate "github.com/feditools/relay/internal/http/template"
|
itemplate "github.com/feditools/relay/internal/http/template"
|
||||||
"github.com/feditools/relay/internal/kv"
|
"github.com/feditools/relay/internal/kv"
|
||||||
|
"github.com/feditools/relay/internal/language"
|
||||||
"github.com/feditools/relay/internal/logic"
|
"github.com/feditools/relay/internal/logic"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"github.com/feditools/relay/internal/runner"
|
"github.com/feditools/relay/internal/runner"
|
||||||
@ -49,6 +49,7 @@ type Module struct {
|
|||||||
logoSrcLight string
|
logoSrcLight string
|
||||||
headLinks []libtemplate.HeadLink
|
headLinks []libtemplate.HeadLink
|
||||||
footerScripts []libtemplate.Script
|
footerScripts []libtemplate.Script
|
||||||
|
footerScriptChartJS libtemplate.Script
|
||||||
|
|
||||||
sigCache map[string]string
|
sigCache map[string]string
|
||||||
sigCacheLock sync.RWMutex
|
sigCacheLock sync.RWMutex
|
||||||
@ -143,6 +144,12 @@ func New(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fsCanvasJS := libtemplate.Script{
|
||||||
|
Src: viper.GetString(config.Keys.WebappChartJSURI),
|
||||||
|
CrossOrigin: COAnonymous,
|
||||||
|
Integrity: viper.GetString(config.Keys.WebappChartJSIntegrity),
|
||||||
|
}
|
||||||
|
|
||||||
return &Module{
|
return &Module{
|
||||||
db: d,
|
db: d,
|
||||||
fedi: f,
|
fedi: f,
|
||||||
@ -160,6 +167,7 @@ func New(
|
|||||||
logoSrcLight: viper.GetString(config.Keys.WebappLogoSrcLight),
|
logoSrcLight: viper.GetString(config.Keys.WebappLogoSrcLight),
|
||||||
headLinks: hl,
|
headLinks: hl,
|
||||||
footerScripts: fs,
|
footerScripts: fs,
|
||||||
|
footerScriptChartJS: fsCanvasJS,
|
||||||
|
|
||||||
sigCache: map[string]string{},
|
sigCache: map[string]string{},
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package kv
|
package kv
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
keyBase = "relay:"
|
keyBase = "relay:"
|
||||||
@ -16,6 +19,15 @@ const (
|
|||||||
keyInstance = keyBase + "instance:"
|
keyInstance = keyBase + "instance:"
|
||||||
keyInstanceOAuth = keyInstance + "oauth:"
|
keyInstanceOAuth = keyInstance + "oauth:"
|
||||||
|
|
||||||
|
keyMetrics = keyBase + "metrics:"
|
||||||
|
keyMetricsDeliver = keyMetrics + "deliver:"
|
||||||
|
keyMetricsDeliverError = keyMetricsDeliver + "e:"
|
||||||
|
keyMetricsDeliverErrorTotal = keyMetricsDeliver + "et:"
|
||||||
|
keyMetricsDeliverSuccess = keyMetricsDeliver + "s:"
|
||||||
|
keyMetricsDeliverSuccessTotal = keyMetricsDeliver + "st:"
|
||||||
|
keyMetricsReceived = keyMetrics + "received:"
|
||||||
|
keyMetricsReceivedTotal = keyMetrics + "receivedt:"
|
||||||
|
|
||||||
keySession = keyBase + "session:"
|
keySession = keyBase + "session:"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,5 +46,35 @@ func KeyFediHostMeta(d string) string { return keyFediHostMeta + d }
|
|||||||
// KeyInstanceOAuth returns the kv key which holds an instance's oauth tokens.
|
// KeyInstanceOAuth returns the kv key which holds an instance's oauth tokens.
|
||||||
func KeyInstanceOAuth(i int64) string { return keyInstanceOAuth + strconv.FormatInt(i, 10) }
|
func KeyInstanceOAuth(i int64) string { return keyInstanceOAuth + strconv.FormatInt(i, 10) }
|
||||||
|
|
||||||
|
// KeyMetricsDeliverError returns the kv key which holds the number of delivery errors to an instance.
|
||||||
|
func KeyMetricsDeliverError(t time.Time) string {
|
||||||
|
return keyMetricsDeliverError + t.Format("2006:01:02")
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyMetricsDeliverErrorTotal returns the kv key which holds the number of delivery errors
|
||||||
|
func KeyMetricsDeliverErrorTotal(t time.Time) string {
|
||||||
|
return keyMetricsDeliverErrorTotal + t.Format("2006:01:02")
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyMetricsDeliverSuccess returns the kv key which holds the number of delivery successes to an instance.
|
||||||
|
func KeyMetricsDeliverSuccess(t time.Time) string {
|
||||||
|
return keyMetricsDeliverSuccess + t.Format("2006:01:02")
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyMetricsDeliverSuccessTotal returns the kv key which holds the number of delivery successes to an instance.
|
||||||
|
func KeyMetricsDeliverSuccessTotal(t time.Time) string {
|
||||||
|
return keyMetricsDeliverSuccessTotal + t.Format("2006:01:02")
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyMetricsReceived returns the kv key which holds the number of receives from an instance.
|
||||||
|
func KeyMetricsReceived(t time.Time) string {
|
||||||
|
return keyMetricsReceived + t.Format("2006:01:02")
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyMetricsReceivedTotal returns the kv key which holds the number of receives.
|
||||||
|
func KeyMetricsReceivedTotal(t time.Time) string {
|
||||||
|
return keyMetricsReceivedTotal + t.Format("2006:01:02")
|
||||||
|
}
|
||||||
|
|
||||||
// KeySession returns the base kv key prefix.
|
// KeySession returns the base kv key prefix.
|
||||||
func KeySession() string { return keySession }
|
func KeySession() string { return keySession }
|
||||||
|
@ -1,10 +1,26 @@
|
|||||||
package kv
|
package kv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/feditools/go-lib/fedihelper"
|
"github.com/feditools/go-lib/fedihelper"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KV represents a key value store.
|
// KV represents a key value store.
|
||||||
type KV interface {
|
type KV interface {
|
||||||
fedihelper.KV
|
fedihelper.KV
|
||||||
|
|
||||||
|
GetMetricsDeliverError(ctx context.Context, instanceID int64, timestamp time.Time) (int, Error)
|
||||||
|
GetMetricsDeliverErrorTotal(ctx context.Context, timestamp time.Time) (int, Error)
|
||||||
|
GetMetricsDeliverSuccess(ctx context.Context, instanceID int64, timestamp time.Time) (int, Error)
|
||||||
|
GetMetricsDeliverSuccessTotal(ctx context.Context, timestamp time.Time) (int, Error)
|
||||||
|
GetMetricsReceived(ctx context.Context, instanceID int64, timestamp time.Time) (int, Error)
|
||||||
|
GetMetricsReceivedTotal(ctx context.Context, timestamp time.Time) (int, Error)
|
||||||
|
|
||||||
|
IncMetricsDeliverError(ctx context.Context, instanceID int64, timestamp time.Time) Error
|
||||||
|
IncMetricsDeliverErrorTotal(ctx context.Context, timestamp time.Time) Error
|
||||||
|
IncMetricsDeliverSuccess(ctx context.Context, instanceID int64, timestamp time.Time) Error
|
||||||
|
IncMetricsDeliverSuccessTotal(ctx context.Context, timestamp time.Time) Error
|
||||||
|
IncMetricsReceived(ctx context.Context, instanceID int64, timestamp time.Time) Error
|
||||||
|
IncMetricsReceivedTotal(ctx context.Context, timestamp time.Time) Error
|
||||||
}
|
}
|
||||||
|
116
internal/kv/redis/metrics.go
Normal file
116
internal/kv/redis/metrics.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/feditools/relay/internal/kv"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Client) GetMetricsDeliverError(ctx context.Context, instanceID int64, timestamp time.Time) (int, kv.Error) {
|
||||||
|
count, err := c.redis.HGet(ctx, kv.KeyMetricsDeliverError(timestamp), strconv.FormatInt(instanceID, 10)).Int()
|
||||||
|
if err != nil {
|
||||||
|
return 0, c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetMetricsDeliverErrorTotal(ctx context.Context, timestamp time.Time) (int, kv.Error) {
|
||||||
|
count, err := c.redis.Get(ctx, kv.KeyMetricsDeliverErrorTotal(timestamp)).Int()
|
||||||
|
if err != nil {
|
||||||
|
return 0, c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetMetricsDeliverSuccess(ctx context.Context, instanceID int64, timestamp time.Time) (int, kv.Error) {
|
||||||
|
count, err := c.redis.HGet(ctx, kv.KeyMetricsDeliverSuccess(timestamp), strconv.FormatInt(instanceID, 10)).Int()
|
||||||
|
if err != nil {
|
||||||
|
return 0, c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetMetricsDeliverSuccessTotal(ctx context.Context, timestamp time.Time) (int, kv.Error) {
|
||||||
|
count, err := c.redis.Get(ctx, kv.KeyMetricsDeliverSuccessTotal(timestamp)).Int()
|
||||||
|
if err != nil {
|
||||||
|
return 0, c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetMetricsReceived(ctx context.Context, instanceID int64, timestamp time.Time) (int, kv.Error) {
|
||||||
|
count, err := c.redis.HGet(ctx, kv.KeyMetricsReceived(timestamp), strconv.FormatInt(instanceID, 10)).Int()
|
||||||
|
if err != nil {
|
||||||
|
return 0, c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetMetricsReceivedTotal(ctx context.Context, timestamp time.Time) (int, kv.Error) {
|
||||||
|
count, err := c.redis.Get(ctx, kv.KeyMetricsReceivedTotal(timestamp)).Int()
|
||||||
|
if err != nil {
|
||||||
|
return 0, c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) IncMetricsDeliverError(ctx context.Context, instanceID int64, timestamp time.Time) kv.Error {
|
||||||
|
_, err := c.redis.HIncrBy(ctx, kv.KeyMetricsDeliverError(timestamp), strconv.FormatInt(instanceID, 10), 1).Result()
|
||||||
|
if err != nil {
|
||||||
|
return c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) IncMetricsDeliverErrorTotal(ctx context.Context, timestamp time.Time) kv.Error {
|
||||||
|
_, err := c.redis.IncrBy(ctx, kv.KeyMetricsDeliverErrorTotal(timestamp), 1).Result()
|
||||||
|
if err != nil {
|
||||||
|
return c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) IncMetricsDeliverSuccess(ctx context.Context, instanceID int64, timestamp time.Time) kv.Error {
|
||||||
|
_, err := c.redis.HIncrBy(ctx, kv.KeyMetricsDeliverSuccess(timestamp), strconv.FormatInt(instanceID, 10), 1).Result()
|
||||||
|
if err != nil {
|
||||||
|
return c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) IncMetricsDeliverSuccessTotal(ctx context.Context, timestamp time.Time) kv.Error {
|
||||||
|
_, err := c.redis.IncrBy(ctx, kv.KeyMetricsDeliverSuccessTotal(timestamp), 1).Result()
|
||||||
|
if err != nil {
|
||||||
|
return c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) IncMetricsReceived(ctx context.Context, instanceID int64, timestamp time.Time) kv.Error {
|
||||||
|
_, err := c.redis.HIncrBy(ctx, kv.KeyMetricsReceived(timestamp), strconv.FormatInt(instanceID, 10), 1).Result()
|
||||||
|
if err != nil {
|
||||||
|
return c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) IncMetricsReceivedTotal(ctx context.Context, timestamp time.Time) kv.Error {
|
||||||
|
_, err := c.redis.IncrBy(ctx, kv.KeyMetricsReceivedTotal(timestamp), 1).Result()
|
||||||
|
if err != nil {
|
||||||
|
return c.ProcessError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,19 +1,14 @@
|
|||||||
package language
|
package language
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"github.com/feditools/relay/web"
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Locales contains static files required by the application
|
|
||||||
//go:embed locales/active.*.yaml
|
|
||||||
var Locales embed.FS
|
|
||||||
|
|
||||||
// DefaultLanguage is the default language of the application.
|
// DefaultLanguage is the default language of the application.
|
||||||
var DefaultLanguage = language.English
|
var DefaultLanguage = language.English
|
||||||
|
|
||||||
@ -34,7 +29,7 @@ func New() (*Module, error) {
|
|||||||
|
|
||||||
module.langBundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
|
module.langBundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
|
||||||
|
|
||||||
dir, err := Locales.ReadDir("locales")
|
dir, err := web.Files.ReadDir("locales")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -45,7 +40,7 @@ func New() (*Module, error) {
|
|||||||
l.Debugf("loading language file: %s", d.Name())
|
l.Debugf("loading language file: %s", d.Name())
|
||||||
|
|
||||||
// open it
|
// open it
|
||||||
file, err := Locales.Open("locales/" + d.Name())
|
file, err := web.Files.Open("locales/" + d.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -68,3 +63,16 @@ func New() (*Module, error) {
|
|||||||
|
|
||||||
// Language returns the default language.
|
// Language returns the default language.
|
||||||
func (m Module) Language() language.Tag { return m.lang }
|
func (m Module) Language() language.Tag { return m.lang }
|
||||||
|
|
||||||
|
func isEmptyYaml(b []byte) bool {
|
||||||
|
switch string(b) {
|
||||||
|
case "":
|
||||||
|
return true
|
||||||
|
case "---":
|
||||||
|
return true
|
||||||
|
case "---\n":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
114
internal/language/language_test.go
Normal file
114
internal/language/language_test.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testCantGetLocalizer = "[%d] can't get localizer for %s: %s"
|
||||||
|
testGotInvalidLanguage = "[%d] got invalid language for %s, got: %v, want: %v"
|
||||||
|
testGotInvalidTranslation = "[%d] got invalid translation for %s, got: %v, want: %v"
|
||||||
|
testTranslatedTo = "[%d] Translating to %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
langMod, err := New()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("can't get new language module: %s", err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if langMod == nil {
|
||||||
|
t.Errorf("language module is nil")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if langMod.langBundle == nil {
|
||||||
|
t.Errorf("language module's bundle is nil")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if langMod.Language() != DefaultLanguage {
|
||||||
|
t.Errorf("got invalid language, got: %v, want: %v,", langMod.Language().String(), DefaultLanguage.String())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsEmptyYaml(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []struct {
|
||||||
|
input string
|
||||||
|
output bool
|
||||||
|
}{
|
||||||
|
{"", true},
|
||||||
|
{"---", true},
|
||||||
|
{"---\n", true},
|
||||||
|
{"---\nvalid: yaml", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf("[%d] running isEmptyYaml", i)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
result := isEmptyYaml([]byte(table.input))
|
||||||
|
if result != table.output {
|
||||||
|
t.Errorf("[%d] got invalid response, got: %v, want: %v,", i, result, table.output)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// text testers
|
||||||
|
|
||||||
|
type testTextTable struct {
|
||||||
|
inputLang language.Tag
|
||||||
|
inputCount int
|
||||||
|
inputStrings []string
|
||||||
|
|
||||||
|
outputString string
|
||||||
|
outputLang language.Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func testText(t *testing.T, tid int, translate func() *LocalizedString, table testTextTable) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
result := translate()
|
||||||
|
testTextCheckResults(t, tid, result, table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTextWithCount(t *testing.T, tid int, translate func(int) *LocalizedString, table testTextTable) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
result := translate(table.inputCount)
|
||||||
|
testTextCheckResults(t, tid, result, table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTextWith1String(t *testing.T, tid int, translate func(string) *LocalizedString, table testTextTable) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
result := translate(table.inputStrings[0])
|
||||||
|
testTextCheckResults(t, tid, result, table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTextCheckResults(t *testing.T, tid int, result *LocalizedString, table testTextTable) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if result.String() != table.outputString {
|
||||||
|
t.Errorf(testGotInvalidTranslation, tid, table.inputLang, result.String(), table.outputString)
|
||||||
|
}
|
||||||
|
if result.Language() != table.outputLang {
|
||||||
|
t.Errorf(testGotInvalidLanguage, tid, table.inputLang, result.Language(), table.outputLang)
|
||||||
|
}
|
||||||
|
}
|
26
internal/language/localizer_test.go
Normal file
26
internal/language/localizer_test.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestNewLocalizer(t *testing.T) {
|
||||||
|
langMod, _ := New()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("can't get new language module: %s", err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if localizer == nil {
|
||||||
|
t.Errorf("localizer module is nil")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if localizer.localizer == nil {
|
||||||
|
t.Errorf("localizer module's localizer is nil")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package language
|
package language
|
||||||
|
|
||||||
import (
|
import "github.com/feditools/relay/internal/log"
|
||||||
"github.com/feditools/go-lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
type empty struct{}
|
type empty struct{}
|
||||||
|
|
111
internal/language/text_a.go
Normal file
111
internal/language/text_a.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
|
// TextAccount returns a translated phrase.
|
||||||
|
func (l *Localizer) TextAccount(count int) *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextAccount")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "Account",
|
||||||
|
One: "Account",
|
||||||
|
Other: "Accounts",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextActivityLog returns a translated phrase.
|
||||||
|
func (l *Localizer) TextActivityLog(count int) *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextActivityLog")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "ActivityLog",
|
||||||
|
One: "Activity Log",
|
||||||
|
Other: "Activity Logs",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextActorURI returns a translated phrase.
|
||||||
|
func (l *Localizer) TextActorURI(count int) *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextActorURI")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "ActorURI",
|
||||||
|
One: "Actor URI",
|
||||||
|
Other: "Actor URIs",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextAddBlock returns a translated phrase.
|
||||||
|
func (l *Localizer) TextAddBlock(count int) *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextAddBlock")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "AddBlock",
|
||||||
|
One: "Add Block",
|
||||||
|
Other: "Add Blocks",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextAdmin returns a translated phrase.
|
||||||
|
func (l *Localizer) TextAdmin() *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextAdmin")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "Admin",
|
||||||
|
Other: "Admin",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
196
internal/language/text_a_test.go
Normal file
196
internal/language/text_a_test.go
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextAccount(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Account",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Accounts",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextAccount, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextActivityLog(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Activity Log",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Activity Logs",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextActivityLog, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextActorURI(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Actor URI",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Actor URIs",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextActorURI, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextAddBlock(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Add Block",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Add Blocks",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextAddBlock, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextAdmin(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Admin",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextAdmin, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -24,13 +24,13 @@ func (l *Localizer) TextBlock(count int) *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextBlockExists returns a translated phrase.
|
// TextBlockExistsDomain returns a translated phrase.
|
||||||
func (l *Localizer) TextBlockExists(domain string) *LocalizedString {
|
func (l *Localizer) TextBlockExistsDomain(domain string) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextBlockExists")
|
lg := logger.WithField("func", "TextBlockExistsDomain")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "BlockExists",
|
ID: "BlockExistsDomain",
|
||||||
Other: "Block for domain {{.Domain}} already exists.",
|
Other: "Block for domain {{.Domain}} already exists.",
|
||||||
},
|
},
|
||||||
TemplateData: map[string]interface{}{
|
TemplateData: map[string]interface{}{
|
195
internal/language/text_b_test.go
Normal file
195
internal/language/text_b_test.go
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextBlock(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Block",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Blocks",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextBlock, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextBlockExistsDomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example.com"},
|
||||||
|
outputString: "Block for domain example.com already exists.",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example2.com"},
|
||||||
|
outputString: "Block for domain example2.com already exists.",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWith1String(t, i, localizer.TextBlockExistsDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextBlockSubdomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Block Subdomain",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Block Subdomains",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextBlockSubdomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextBlocked(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Blocked",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextBlocked, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextBlockedDomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Blocked Domain",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Blocked Domains",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextBlockedDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,35 +2,15 @@ package language
|
|||||||
|
|
||||||
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
// TextOauth returns a translated phrase.
|
// TextChatID returns a translated phrase.
|
||||||
func (l *Localizer) TextOauth() *LocalizedString {
|
func (l *Localizer) TextChatID(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextOauth")
|
lg := logger.WithField("func", "TextChatID")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "Oauth",
|
ID: "ChatID",
|
||||||
Other: "OAuth",
|
One: "Chat ID",
|
||||||
},
|
Other: "Chat IDs",
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalizedString{
|
|
||||||
language: tag,
|
|
||||||
string: text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextOauth20Client returns a translated phrase.
|
|
||||||
func (l *Localizer) TextOauth20Client(count int) *LocalizedString {
|
|
||||||
lg := logger.WithField("func", "TextOauth20Client")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
|
||||||
DefaultMessage: &i18n.Message{
|
|
||||||
ID: "Oauth20Client",
|
|
||||||
One: "OAuth 2.0 Client",
|
|
||||||
Other: "OAuth 2.0 Clients",
|
|
||||||
},
|
},
|
||||||
PluralCount: count,
|
PluralCount: count,
|
||||||
})
|
})
|
||||||
@ -44,14 +24,14 @@ func (l *Localizer) TextOauth20Client(count int) *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextOauth20Settings returns a translated phrase.
|
// TextClose returns a translated phrase.
|
||||||
func (l *Localizer) TextOauth20Settings() *LocalizedString {
|
func (l *Localizer) TextClose() *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextOauth20Settings")
|
lg := logger.WithField("func", "TextClose")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "Oauth20Settings",
|
ID: "Close",
|
||||||
Other: "OAuth 2.0 Settings",
|
Other: "Close",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,15 +44,15 @@ func (l *Localizer) TextOauth20Settings() *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextObfuscatedDomain returns a translated phrase.
|
// TextConfig returns a translated phrase.
|
||||||
func (l *Localizer) TextObfuscatedDomain(count int) *LocalizedString {
|
func (l *Localizer) TextConfig(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextObfuscatedDomain")
|
lg := logger.WithField("func", "TextConfig")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "ObfuscatedDomain",
|
ID: "Config",
|
||||||
One: "Obfuscated Domain",
|
One: "Config",
|
||||||
Other: "Obfuscated Domains",
|
Other: "Configs",
|
||||||
},
|
},
|
||||||
PluralCount: count,
|
PluralCount: count,
|
||||||
})
|
})
|
||||||
@ -85,3 +65,23 @@ func (l *Localizer) TextObfuscatedDomain(count int) *LocalizedString {
|
|||||||
string: text,
|
string: text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextCreate returns a translated phrase.
|
||||||
|
func (l *Localizer) TextCreate() *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextCreate")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "Create",
|
||||||
|
Other: "Create",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
150
internal/language/text_c_test.go
Normal file
150
internal/language/text_c_test.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextChatID(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Chat ID",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Chat IDs",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextChatID, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextClose(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Close",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextClose, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextConfig(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Config",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Configs",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextConfig, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextCreate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Create",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextCreate, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,28 +2,6 @@ package language
|
|||||||
|
|
||||||
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
// TextDashboard returns a translated phrase.
|
|
||||||
func (l *Localizer) TextDashboard(count int) *LocalizedString {
|
|
||||||
lg := logger.WithField("func", "TextDashboard")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
|
||||||
DefaultMessage: &i18n.Message{
|
|
||||||
ID: "Dashboard",
|
|
||||||
One: "Dashboard",
|
|
||||||
Other: "Dashboards",
|
|
||||||
},
|
|
||||||
PluralCount: count,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalizedString{
|
|
||||||
language: tag,
|
|
||||||
string: text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextDelete returns a translated phrase.
|
// TextDelete returns a translated phrase.
|
||||||
func (l *Localizer) TextDelete() *LocalizedString {
|
func (l *Localizer) TextDelete() *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextDelete")
|
lg := logger.WithField("func", "TextDelete")
|
||||||
@ -90,18 +68,18 @@ func (l *Localizer) TextDeleteBlockConfirmDomain(domain string) *LocalizedString
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextDemocrablock returns a translated phrase.
|
// TextDeliveryStat returns a translated phrase.
|
||||||
func (l *Localizer) TextDemocrablock() *LocalizedString {
|
func (l *Localizer) TextDeliveryStat(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextDemocrablock")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "Democrablock",
|
ID: "DeliveryStat",
|
||||||
Other: "Democrablock",
|
One: "Delivery Stat",
|
||||||
|
Other: "Delivery Stats",
|
||||||
},
|
},
|
||||||
|
PluralCount: count,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
logger.WithField("func", "TextDeliveryStat").Warningf(missingTranslationWarning, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LocalizedString{
|
return &LocalizedString{
|
235
internal/language/text_d_test.go
Normal file
235
internal/language/text_d_test.go
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextDelete(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Delete",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextDelete, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextDeleteBlockDomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example.com"},
|
||||||
|
outputString: "Delete Block example.com",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example2.com"},
|
||||||
|
outputString: "Delete Block example2.com",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWith1String(t, i, localizer.TextDeleteBlockDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextDeleteBlockConfirmDomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example.com"},
|
||||||
|
outputString: "Are you sure you want to delete the block for example.com?",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example2.com"},
|
||||||
|
outputString: "Are you sure you want to delete the block for example2.com?",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWith1String(t, i, localizer.TextDeleteBlockConfirmDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextDeliveryStat(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Delivery Stat",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Delivery Stats",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextDeliveryStat, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextDescription(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Description",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Descriptions",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextDescription, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextDomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Domain",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Domains",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
110
internal/language/text_e_test.go
Normal file
110
internal/language/text_e_test.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextEditBlock(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example.com"},
|
||||||
|
outputString: "Edit Block example.com",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputStrings: []string{"example2.com"},
|
||||||
|
outputString: "Edit Block example2.com",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWith1String(t, i, localizer.TextEditBlockDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextEnabled(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Enabled",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextEnabled, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextErrorDatabase(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "database error",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextErrorDatabase, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,14 +2,14 @@ package language
|
|||||||
|
|
||||||
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
// TextFediverse returns a translated phrase.
|
// TextFederation returns a translated phrase.
|
||||||
func (l *Localizer) TextFediverse() *LocalizedString {
|
func (l *Localizer) TextFederation() *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextFediverse")
|
lg := logger.WithField("func", "TextFederation")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "Fediverse",
|
ID: "Federation",
|
||||||
Other: "Fediverse",
|
Other: "Federation",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
72
internal/language/text_f_test.go
Normal file
72
internal/language/text_f_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextFederation(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Federation",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextFederation, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextFollowing(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Following",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextFollowing, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
39
internal/language/text_g_test.go
Normal file
39
internal/language/text_g_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextGeneral(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "General",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextGeneral, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
104
internal/language/text_h_test.go
Normal file
104
internal/language/text_h_test.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextHomeWeb(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Home",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextHomeWeb, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextHomePageBody(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Home Page Body",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextHomePageBody, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextHowToJoin(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "How to Join",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextHowToJoin, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,28 @@ func (l *Localizer) TextImportBlockList(count int) *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextInboxURI returns a translated phrase.
|
||||||
|
func (l *Localizer) TextInboxURI(count int) *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextInboxURI")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "InboxURI",
|
||||||
|
One: "Inbox URI",
|
||||||
|
Other: "Inbox URIs",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TextInstance returns a translated phrase.
|
// TextInstance returns a translated phrase.
|
||||||
func (l *Localizer) TextInstance(count int) *LocalizedString {
|
func (l *Localizer) TextInstance(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextInstance")
|
lg := logger.WithField("func", "TextInstance")
|
||||||
@ -65,25 +87,3 @@ func (l *Localizer) TextInstance(count int) *LocalizedString {
|
|||||||
string: text,
|
string: text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextInvalidURI returns a translated phrase.
|
|
||||||
func (l *Localizer) TextInvalidURI(count int) *LocalizedString {
|
|
||||||
lg := logger.WithField("func", "TextInvalidURI")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
|
||||||
DefaultMessage: &i18n.Message{
|
|
||||||
ID: "InvalidURI",
|
|
||||||
One: "Invalid URI",
|
|
||||||
Other: "Invalid URIs",
|
|
||||||
},
|
|
||||||
PluralCount: count,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalizedString{
|
|
||||||
language: tag,
|
|
||||||
string: text,
|
|
||||||
}
|
|
||||||
}
|
|
157
internal/language/text_i_test.go
Normal file
157
internal/language/text_i_test.go
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextImport(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Import",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextImport, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextImportBlockList(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Import Block List",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Import Block Lists",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextImportBlockList, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextInboxURI(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Inbox URI",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Inbox URIs",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextInboxURI, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextInstance(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Instance",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Instances",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextInstance, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,28 +2,6 @@ package language
|
|||||||
|
|
||||||
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
// TextList returns a translated phrase.
|
|
||||||
func (l *Localizer) TextList(count int) *LocalizedString {
|
|
||||||
lg := logger.WithField("func", "TextList")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
|
||||||
DefaultMessage: &i18n.Message{
|
|
||||||
ID: "List",
|
|
||||||
One: "List",
|
|
||||||
Other: "Lists",
|
|
||||||
},
|
|
||||||
PluralCount: count,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalizedString{
|
|
||||||
language: tag,
|
|
||||||
string: text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextLogin returns a translated phrase.
|
// TextLogin returns a translated phrase.
|
||||||
func (l *Localizer) TextLogin() *LocalizedString {
|
func (l *Localizer) TextLogin() *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextLogin")
|
lg := logger.WithField("func", "TextLogin")
|
104
internal/language/text_l_test.go
Normal file
104
internal/language/text_l_test.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextLogin(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Login",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextLogin, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextLogout(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Logout",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextLogout, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextLookGood(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Looks Good!",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextLooksGood, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,15 +2,17 @@ package language
|
|||||||
|
|
||||||
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
// TextModeration returns a translated phrase.
|
// TextMetric returns a translated phrase.
|
||||||
func (l *Localizer) TextModeration() *LocalizedString {
|
func (l *Localizer) TextMetric(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextLogin")
|
lg := logger.WithField("func", "TextMetric")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "Moderation",
|
ID: "Metric",
|
||||||
Other: "Moderation",
|
One: "Metric",
|
||||||
|
Other: "Metrics",
|
||||||
},
|
},
|
||||||
|
PluralCount: count,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
lg.Warningf(missingTranslationWarning, err.Error())
|
85
internal/language/text_m_test.go
Normal file
85
internal/language/text_m_test.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextMetric(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Metric",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Metrics",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextMetric, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextModerator(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Moderator",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Moderators",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextModerator, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
46
internal/language/text_n_test.go
Normal file
46
internal/language/text_n_test.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextNotification(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Notification",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Notifications",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextNotification, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
41
internal/language/text_o.go
Normal file
41
internal/language/text_o.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
|
// TextOAuthConfigured returns a translated phrase.
|
||||||
|
func (l *Localizer) TextOAuthConfigured() *LocalizedString {
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "OAuthConfigured",
|
||||||
|
Other: "OAuth Configured",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.WithField("func", "TextOAuthConfigured").Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextObfuscatedDomain returns a translated phrase.
|
||||||
|
func (l *Localizer) TextObfuscatedDomain(count int) *LocalizedString {
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "ObfuscatedDomain",
|
||||||
|
One: "Obfuscated Domain",
|
||||||
|
Other: "Obfuscated Domains",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.WithField("func", "TextObfuscatedDomain").Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
79
internal/language/text_o_test.go
Normal file
79
internal/language/text_o_test.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextOAuthConfigured(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "OAuth Configured",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextOAuthConfigured, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextObfuscatedDomain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Obfuscated Domain",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Obfuscated Domains",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextObfuscatedDomain, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,26 @@ package language
|
|||||||
|
|
||||||
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
import "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
|
// TextReceivedStat returns a translated phrase.
|
||||||
|
func (l *Localizer) TextReceivedStat(count int) *LocalizedString {
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "ReceivedStat",
|
||||||
|
One: "Received Stat",
|
||||||
|
Other: "Received Stats",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.WithField("func", "TextReceivedStat").Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TextRelay returns a translated phrase.
|
// TextRelay returns a translated phrase.
|
||||||
func (l *Localizer) TextRelay(count int) *LocalizedString {
|
func (l *Localizer) TextRelay(count int) *LocalizedString {
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
@ -22,40 +42,18 @@ func (l *Localizer) TextRelay(count int) *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextRequired returns a translated phrase.
|
// TextRepo returns a translated phrase.
|
||||||
func (l *Localizer) TextRequired() *LocalizedString {
|
func (l *Localizer) TextRepo(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextRequired")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "Required",
|
ID: "Repo",
|
||||||
Other: "Required",
|
One: "Repo",
|
||||||
},
|
Other: "Repos",
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalizedString{
|
|
||||||
language: tag,
|
|
||||||
string: text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextRedirectURI returns a translated phrase.
|
|
||||||
func (l *Localizer) TextRedirectURI(count int) *LocalizedString {
|
|
||||||
lg := logger.WithField("func", "TextRedirectURI")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
|
||||||
DefaultMessage: &i18n.Message{
|
|
||||||
ID: "RedirectURI",
|
|
||||||
One: "Redirect URI",
|
|
||||||
Other: "Redirect URIs",
|
|
||||||
},
|
},
|
||||||
PluralCount: count,
|
PluralCount: count,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
logger.WithField("func", "TextRepo").Warningf(missingTranslationWarning, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LocalizedString{
|
return &LocalizedString{
|
125
internal/language/text_r_test.go
Normal file
125
internal/language/text_r_test.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextReceivedStat(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Received Stat",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Received Stats",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextReceivedStat, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextRelay(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Relay",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Relays",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextRelay, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextRepo(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Repo",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Repos",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextRepo, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,28 @@ func (l *Localizer) TextSave() *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextServerHostname returns a translated phrase.
|
||||||
|
func (l *Localizer) TextServerHostname(count int) *LocalizedString {
|
||||||
|
lg := logger.WithField("func", "TextServerHostname")
|
||||||
|
|
||||||
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
|
DefaultMessage: &i18n.Message{
|
||||||
|
ID: "ServerHostname",
|
||||||
|
One: "Server Hostname",
|
||||||
|
Other: "Server Hostnames",
|
||||||
|
},
|
||||||
|
PluralCount: count,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
lg.Warningf(missingTranslationWarning, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LocalizedString{
|
||||||
|
language: tag,
|
||||||
|
string: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TextSetting returns a translated phrase.
|
// TextSetting returns a translated phrase.
|
||||||
func (l *Localizer) TextSetting(count int) *LocalizedString {
|
func (l *Localizer) TextSetting(count int) *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextSetting")
|
lg := logger.WithField("func", "TextSetting")
|
||||||
@ -44,17 +66,15 @@ func (l *Localizer) TextSetting(count int) *LocalizedString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextSystem returns a translated phrase.
|
// TextSoftware returns a translated phrase.
|
||||||
func (l *Localizer) TextSystem(count int) *LocalizedString {
|
func (l *Localizer) TextSoftware() *LocalizedString {
|
||||||
lg := logger.WithField("func", "TextSystem")
|
lg := logger.WithField("func", "TextSoftware")
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||||
DefaultMessage: &i18n.Message{
|
DefaultMessage: &i18n.Message{
|
||||||
ID: "System",
|
ID: "Software",
|
||||||
One: "System",
|
Other: "Software",
|
||||||
Other: "Systems",
|
|
||||||
},
|
},
|
||||||
PluralCount: count,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
lg.Warningf(missingTranslationWarning, err.Error())
|
150
internal/language/text_s_test.go
Normal file
150
internal/language/text_s_test.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextSave(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Save",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextSave, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextServerHostname(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Server Hostname",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Server Hostnames",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextServerHostname, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextSetting(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Setting",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Settings",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextSetting, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextSoftware(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Software",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextSoftware, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
86
internal/language/text_t_test.go
Normal file
86
internal/language/text_t_test.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextTimestamp(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Timestamp",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Timestamps",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextTimestamp, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextToken(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Token",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Tokens",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextToken, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -43,25 +43,3 @@ func (l *Localizer) TextUpdate(count int) *LocalizedString {
|
|||||||
string: text,
|
string: text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextUsername returns a translated phrase.
|
|
||||||
func (l *Localizer) TextUsername(count int) *LocalizedString {
|
|
||||||
lg := logger.WithField("func", "TextUsername")
|
|
||||||
|
|
||||||
text, tag, err := l.localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
|
||||||
DefaultMessage: &i18n.Message{
|
|
||||||
ID: "Username",
|
|
||||||
One: "Username",
|
|
||||||
Other: "Usernames",
|
|
||||||
},
|
|
||||||
PluralCount: count,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lg.Warningf(missingTranslationWarning, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalizedString{
|
|
||||||
language: tag,
|
|
||||||
string: text,
|
|
||||||
}
|
|
||||||
}
|
|
79
internal/language/text_u_test.go
Normal file
79
internal/language/text_u_test.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package language
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalizer_TextUnauthorized(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
outputString: "Unauthorized",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testText(t, i, localizer.TextUnauthorized, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_TextUpdate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []testTextTable{
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 1,
|
||||||
|
outputString: "Update",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLang: language.English,
|
||||||
|
inputCount: 2,
|
||||||
|
outputString: "Updates",
|
||||||
|
outputLang: language.English,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
langMod, _ := New()
|
||||||
|
for i, table := range tables {
|
||||||
|
i := i
|
||||||
|
table := table
|
||||||
|
|
||||||
|
name := fmt.Sprintf(testTranslatedTo, i, table.inputLang)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
localizer, err := langMod.NewLocalizer(table.inputLang.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(testCantGetLocalizer, i, table.inputLang, err.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTextWithCount(t, i, localizer.TextUpdate, table)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,12 @@ type Logic interface {
|
|||||||
GetLoginURL(ctx context.Context, instance *models.Instance) (*url.URL, error)
|
GetLoginURL(ctx context.Context, instance *models.Instance) (*url.URL, error)
|
||||||
GetPeers(ctx context.Context) (*[]string, error)
|
GetPeers(ctx context.Context) (*[]string, error)
|
||||||
IsDomainBlocked(ctx context.Context, d string) (bool, error)
|
IsDomainBlocked(ctx context.Context, d string) (bool, error)
|
||||||
|
MetricsGetDeliverErrorWeek(ctx context.Context, instanceID int64) (*MetricsDataPointsTime, error)
|
||||||
|
MetricsGetDeliverSuccessWeek(ctx context.Context, instanceID int64) (*MetricsDataPointsTime, error)
|
||||||
|
MetricsGetReceivedWeek(ctx context.Context, instanceID int64) (*MetricsDataPointsTime, error)
|
||||||
|
MetricsIncDeliverError(ctx context.Context, instanceID int64)
|
||||||
|
MetricsIncDeliverSuccess(ctx context.Context, instanceID int64)
|
||||||
|
MetricsIncReceived(ctx context.Context, instanceID int64)
|
||||||
ProcessActivity(ctx context.Context, jid string, instanceID int64, actorIRI *url.URL, activity fedihelper.Activity) error
|
ProcessActivity(ctx context.Context, jid string, instanceID int64, actorIRI *url.URL, activity fedihelper.Activity) error
|
||||||
ProcessBlockAdd(ctx context.Context, blockID int64) error
|
ProcessBlockAdd(ctx context.Context, blockID int64) error
|
||||||
ProcessBlockDelete(ctx context.Context, blockID int64) error
|
ProcessBlockDelete(ctx context.Context, blockID int64) error
|
||||||
|
@ -47,11 +47,16 @@ func (l *Logic) DeliverActivity(ctx context.Context, jid string, instanceID int6
|
|||||||
log.Debugf("sending activity: %s to %s", string(body), inboxIRI.String())
|
log.Debugf("sending activity: %s to %s", string(body), inboxIRI.String())
|
||||||
resp, err := l.transport.InstancePost(ctx, inboxIRI, body, libhttp.MimeAppActivityJSON, libhttp.MimeAppActivityJSON)
|
resp, err := l.transport.InstancePost(ctx, inboxIRI, body, libhttp.MimeAppActivityJSON, libhttp.MimeAppActivityJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
msg := fmt.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
||||||
|
log.Error(msg.Error())
|
||||||
|
|
||||||
return fmt.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
l.MetricsIncDeliverError(ctx, instance.ID)
|
||||||
|
|
||||||
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.MetricsIncDeliverSuccess(ctx, instance.ID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,26 +171,9 @@ func (l *Logic) doFollow(ctx context.Context, jid string, instanceID int64, acti
|
|||||||
|
|
||||||
// send accept
|
// send accept
|
||||||
outgoingActivity := genActivityAccept(l.domain, instance.ActorIRI, id)
|
outgoingActivity := genActivityAccept(l.domain, instance.ActorIRI, id)
|
||||||
body, err := json.Marshal(outgoingActivity)
|
err = l.runner.EnqueueDeliverActivity(ctx, instance.ID, outgoingActivity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("can't marshal response: %s", err.Error())
|
log.Errorf("enqueueing delivery: %s", err.Error())
|
||||||
|
|
||||||
return fmt.Errorf("can't marshal response: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
inboxIRI, err := url.Parse(instance.InboxIRI)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("can't parse actor iri: %s", err.Error())
|
|
||||||
|
|
||||||
return fmt.Errorf("can't parse actor iri: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("sending activity: %s", string(body))
|
|
||||||
resp, err := l.transport.InstancePost(ctx, inboxIRI, body, libhttp.MimeAppActivityJSON, libhttp.MimeAppActivityJSON)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
|
||||||
|
|
||||||
return fmt.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go l.runner.EnqueueSendNotification(
|
go l.runner.EnqueueSendNotification(
|
||||||
@ -391,26 +379,9 @@ func (l *Logic) doUndo(ctx context.Context, jid string, instanceID int64, activi
|
|||||||
|
|
||||||
// send undo
|
// send undo
|
||||||
outgoingActivity := genActivityUndo(l.domain, instance.ActorIRI)
|
outgoingActivity := genActivityUndo(l.domain, instance.ActorIRI)
|
||||||
body, err := json.Marshal(outgoingActivity)
|
err = l.runner.EnqueueDeliverActivity(ctx, instance.ID, outgoingActivity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("can't marshal response: %s", err.Error())
|
log.Errorf("enqueueing delivery: %s", err.Error())
|
||||||
|
|
||||||
return fmt.Errorf("can't marshal response: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
inboxIRI, err := url.Parse(instance.InboxIRI)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("can't parse actor iri: %s", err.Error())
|
|
||||||
|
|
||||||
return fmt.Errorf("can't parse actor iri: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("sending activity: %s", string(body))
|
|
||||||
resp, err := l.transport.InstancePost(ctx, inboxIRI, body, libhttp.MimeAppActivityJSON, libhttp.MimeAppActivityJSON)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
|
||||||
|
|
||||||
return fmt.Errorf("can't post to instance: %s\n%s", err.Error(), resp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go l.runner.EnqueueSendNotification(
|
go l.runner.EnqueueSendNotification(
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/feditools/relay/internal/db"
|
"github.com/feditools/relay/internal/db"
|
||||||
"github.com/feditools/relay/internal/fedi"
|
"github.com/feditools/relay/internal/fedi"
|
||||||
ihttp "github.com/feditools/relay/internal/http"
|
ihttp "github.com/feditools/relay/internal/http"
|
||||||
|
"github.com/feditools/relay/internal/kv"
|
||||||
"github.com/feditools/relay/internal/notification"
|
"github.com/feditools/relay/internal/notification"
|
||||||
"github.com/feditools/relay/internal/path"
|
"github.com/feditools/relay/internal/path"
|
||||||
"github.com/feditools/relay/internal/runner"
|
"github.com/feditools/relay/internal/runner"
|
||||||
@ -25,6 +26,7 @@ import (
|
|||||||
type Logic struct {
|
type Logic struct {
|
||||||
db db.DB
|
db db.DB
|
||||||
fedi *fedi.Module
|
fedi *fedi.Module
|
||||||
|
kv kv.KV
|
||||||
notifier notification.Notifier
|
notifier notification.Notifier
|
||||||
runner runner.Runner
|
runner runner.Runner
|
||||||
tokz *token.Tokenizer
|
tokz *token.Tokenizer
|
||||||
@ -48,7 +50,7 @@ type Logic struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New created a new logic module
|
// New created a new logic module
|
||||||
func New(ctx context.Context, c pub.Clock, d db.DB, h *ihttp.Client, tokz *token.Tokenizer) (*Logic, error) {
|
func New(ctx context.Context, c pub.Clock, d db.DB, h *ihttp.Client, k kv.KV, tokz *token.Tokenizer) (*Logic, error) {
|
||||||
log := logger.WithFields(logrus.Fields{
|
log := logger.WithFields(logrus.Fields{
|
||||||
"func": "New",
|
"func": "New",
|
||||||
})
|
})
|
||||||
@ -56,6 +58,7 @@ func New(ctx context.Context, c pub.Clock, d db.DB, h *ihttp.Client, tokz *token
|
|||||||
// create module
|
// create module
|
||||||
l := Logic{
|
l := Logic{
|
||||||
db: d,
|
db: d,
|
||||||
|
kv: k,
|
||||||
tokz: tokz,
|
tokz: tokz,
|
||||||
|
|
||||||
domain: viper.GetString(config.Keys.ServerExternalHostname),
|
domain: viper.GetString(config.Keys.ServerExternalHostname),
|
||||||
|
81
internal/logic/logic1/metrics_get.go
Normal file
81
internal/logic/logic1/metrics_get.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package logic1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/feditools/relay/internal/kv"
|
||||||
|
"github.com/feditools/relay/internal/logic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *Logic) MetricsGetDeliverErrorWeek(ctx context.Context, instanceID int64) (*logic.MetricsDataPointsTime, error) {
|
||||||
|
now := time.Now().UTC()
|
||||||
|
now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
var days logic.MetricsDataPointsTime = make([]logic.MetricsDataPointTime, 7)
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
day := now.Add(-24 * time.Duration(i) * time.Hour)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
var err error
|
||||||
|
count, err = l.kv.GetMetricsDeliverError(ctx, instanceID, day)
|
||||||
|
if err != nil && !errors.Is(err, kv.ErrNil) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
days[i] = logic.MetricsDataPointTime{
|
||||||
|
X: day,
|
||||||
|
Y: count,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &days, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logic) MetricsGetDeliverSuccessWeek(ctx context.Context, instanceID int64) (*logic.MetricsDataPointsTime, error) {
|
||||||
|
now := time.Now().UTC()
|
||||||
|
now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
var days logic.MetricsDataPointsTime = make([]logic.MetricsDataPointTime, 7)
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
day := now.Add(-24 * time.Duration(i) * time.Hour)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
var err error
|
||||||
|
count, err = l.kv.GetMetricsDeliverSuccess(ctx, instanceID, day)
|
||||||
|
if err != nil && !errors.Is(err, kv.ErrNil) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
days[i] = logic.MetricsDataPointTime{
|
||||||
|
X: day,
|
||||||
|
Y: count,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &days, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logic) MetricsGetReceivedWeek(ctx context.Context, instanceID int64) (*logic.MetricsDataPointsTime, error) {
|
||||||
|
now := time.Now().UTC()
|
||||||
|
now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
var days logic.MetricsDataPointsTime = make([]logic.MetricsDataPointTime, 7)
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
day := now.Add(-24 * time.Duration(i) * time.Hour)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
var err error
|
||||||
|
count, err = l.kv.GetMetricsReceived(ctx, instanceID, day)
|
||||||
|
if err != nil && !errors.Is(err, kv.ErrNil) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
days[i] = logic.MetricsDataPointTime{
|
||||||
|
X: day,
|
||||||
|
Y: count,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &days, nil
|
||||||
|
}
|
54
internal/logic/logic1/metrics_inc.go
Normal file
54
internal/logic/logic1/metrics_inc.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package logic1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *Logic) MetricsIncDeliverError(ctx context.Context, instanceID int64) {
|
||||||
|
log := logger.WithField("func", "MetricsIncDeliverError")
|
||||||
|
|
||||||
|
now := time.Now().UTC()
|
||||||
|
|
||||||
|
err := l.kv.IncMetricsDeliverError(ctx, instanceID, now)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("instance: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.kv.IncMetricsDeliverErrorTotal(ctx, now)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("total: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logic) MetricsIncDeliverSuccess(ctx context.Context, instanceID int64) {
|
||||||
|
log := logger.WithField("func", "MetricsIncDeliverSuccess")
|
||||||
|
|
||||||
|
now := time.Now().UTC()
|
||||||
|
|
||||||
|
err := l.kv.IncMetricsDeliverSuccess(ctx, instanceID, now)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("instance: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.kv.IncMetricsDeliverSuccessTotal(ctx, now)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("total: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logic) MetricsIncReceived(ctx context.Context, instanceID int64) {
|
||||||
|
log := logger.WithField("func", "MetricsIncReceived")
|
||||||
|
|
||||||
|
now := time.Now().UTC()
|
||||||
|
|
||||||
|
err := l.kv.IncMetricsReceived(ctx, instanceID, now)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("instance: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.kv.IncMetricsReceivedTotal(ctx, now)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("total: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
10
internal/logic/metrics.go
Normal file
10
internal/logic/metrics.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type MetricsDataPointsTime []MetricsDataPointTime
|
||||||
|
|
||||||
|
type MetricsDataPointTime struct {
|
||||||
|
X time.Time
|
||||||
|
Y int
|
||||||
|
}
|
@ -27,6 +27,11 @@ func GenAppAdminHomePath() string {
|
|||||||
return AppAdminHome
|
return AppAdminHome
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenAppAdminInstanceViewPath returns a path for the admin instance view page.
|
||||||
|
func GenAppAdminInstanceViewPath(t string) string {
|
||||||
|
return AppAdminPreInstanceView + t
|
||||||
|
}
|
||||||
|
|
||||||
// GenAppHomePath returns a path for the home page.
|
// GenAppHomePath returns a path for the home page.
|
||||||
func GenAppHomePath() string {
|
func GenAppHomePath() string {
|
||||||
return AppHome
|
return AppHome
|
||||||
|
@ -69,4 +69,8 @@ const (
|
|||||||
AppAdminInstance = AppAdmin + AppAdminSubInstance
|
AppAdminInstance = AppAdmin + AppAdminSubInstance
|
||||||
// AppAdminSubInstance is the sub path for the admin instances page.
|
// AppAdminSubInstance is the sub path for the admin instances page.
|
||||||
AppAdminSubInstance = "/" + PartInstance
|
AppAdminSubInstance = "/" + PartInstance
|
||||||
|
// AppAdminPreInstanceView is the prefix path for the admin instance view page.
|
||||||
|
AppAdminPreInstanceView = AppAdmin + AppAdminSubInstance + "/"
|
||||||
|
// AppAdminSubInstanceView is the sub path for the admin instance view page.
|
||||||
|
AppAdminSubInstanceView = AppAdminSubInstance + "/" + VarInstance
|
||||||
)
|
)
|
||||||
|
38
test/fake_metrics.sh
Executable file
38
test/fake_metrics.sh
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash -x
|
||||||
|
|
||||||
|
METRIC_MAX=500
|
||||||
|
|
||||||
|
KEY_DELIVERY_S="relay:metrics:deliver:s:"
|
||||||
|
KEY_DELIVERY_S_TOTAL="relay:metrics:deliver:st:"
|
||||||
|
KEY_DELIVERY_E="relay:metrics:deliver:e:"
|
||||||
|
KEY_DELIVERY_E_TOTAL="relay:metrics:deliver:et:"
|
||||||
|
KEY_RECEIVED="relay:metrics:received:"
|
||||||
|
KEY_RECEIVED_TOTAL="relay:metrics:receivedt:"
|
||||||
|
|
||||||
|
for day in {0..30}; do
|
||||||
|
#echo $day
|
||||||
|
|
||||||
|
DATE1=$(date -v -${day}d +"%Y:%m:%d")
|
||||||
|
|
||||||
|
DELIVERY_S_TOTAL=0
|
||||||
|
DELIVERY_E_TOTAL=0
|
||||||
|
RECEIVED_TOTAL=0
|
||||||
|
|
||||||
|
for instance in {2..3}; do
|
||||||
|
DELIVERY_S=$((1 + $RANDOM % ${METRIC_MAX}))
|
||||||
|
DELIVERY_E=$((1 + $RANDOM % ${METRIC_MAX}))
|
||||||
|
RECEIVED=$((1 + $RANDOM % ${METRIC_MAX}))
|
||||||
|
|
||||||
|
DELIVERY_S_TOTAL=$(expr ${DELIVERY_S_TOTAL} + ${DELIVERY_S})
|
||||||
|
DELIVERY_E_TOTAL=$(expr ${DELIVERY_E_TOTAL} + ${DELIVERY_E})
|
||||||
|
RECEIVED_TOTAL=$(expr ${RECEIVED_TOTAL} + ${RECEIVED})
|
||||||
|
|
||||||
|
docker exec -it relay_redis_1 redis-cli --pass test HSET ${KEY_DELIVERY_S}${DATE1} ${instance} ${DELIVERY_S}
|
||||||
|
docker exec -it relay_redis_1 redis-cli --pass test HSET ${KEY_DELIVERY_E}${DATE1} ${instance} ${DELIVERY_E}
|
||||||
|
docker exec -it relay_redis_1 redis-cli --pass test HSET ${KEY_RECEIVED}${DATE1} ${instance} ${RECEIVED}
|
||||||
|
done
|
||||||
|
|
||||||
|
docker exec -it relay_redis_1 redis-cli --pass test SET ${KEY_DELIVERY_S_TOTAL}${DATE1} ${DELIVERY_S_TOTAL}
|
||||||
|
docker exec -it relay_redis_1 redis-cli --pass test SET ${KEY_DELIVERY_E_TOTAL}${DATE1} ${DELIVERY_E_TOTAL}
|
||||||
|
docker exec -it relay_redis_1 redis-cli --pass test SET ${KEY_RECEIVED_TOTAL}${DATE1} ${RECEIVED_TOTAL}
|
||||||
|
done
|
2
vendor/github.com/feditools/go-lib/Jenkinsfile
generated
vendored
2
vendor/github.com/feditools/go-lib/Jenkinsfile
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
environment {
|
environment {
|
||||||
BUILD_IMAGE = 'gobuild:1.17'
|
BUILD_IMAGE = 'gobuild:1.18'
|
||||||
BUILD_ARGS = '-e GOCACHE=/gocache -e HOME=${WORKSPACE} -v /var/lib/jenkins/gocache:/gocache -v /var/lib/jenkins/go/pkg:/go/pkg'
|
BUILD_ARGS = '-e GOCACHE=/gocache -e HOME=${WORKSPACE} -v /var/lib/jenkins/gocache:/gocache -v /var/lib/jenkins/go/pkg:/go/pkg'
|
||||||
PATH = '/go/bin:~/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin'
|
PATH = '/go/bin:~/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin'
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/feditools/go-lib/language/locales/active.af.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.af.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.ar.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.ar.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.ca.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.ca.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.cs.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.cs.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.da.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.da.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.de.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.de.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.el.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.el.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
39
vendor/github.com/feditools/go-lib/language/locales/active.es.yaml
generated
vendored
39
vendor/github.com/feditools/go-lib/language/locales/active.es.yaml
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
Account:
|
|
||||||
one: Cuenta
|
|
||||||
other: Cuentas
|
|
||||||
AddOauth20Client:
|
|
||||||
one: Añadir Cliente OAuth 2.0
|
|
||||||
other: Añadir Clientes de OAuth 2.0
|
|
||||||
Client:
|
|
||||||
one: Cliente
|
|
||||||
other: Clientes
|
|
||||||
ClientID:
|
|
||||||
one: ID de Cliente
|
|
||||||
other: IDs de Cliente
|
|
||||||
ClientSecret:
|
|
||||||
one: Secreto de Cliente
|
|
||||||
other: Secretos del Cliente
|
|
||||||
Create: Crear
|
|
||||||
Dashboard:
|
|
||||||
one: Tablero
|
|
||||||
other: Tableros
|
|
||||||
Description:
|
|
||||||
one: Descripción
|
|
||||||
other: Descripciones
|
|
||||||
HomeWeb: Inicio
|
|
||||||
InvalidURI:
|
|
||||||
one: URI Inválidas
|
|
||||||
other: URIs Inválidas
|
|
||||||
Login: Ingresar
|
|
||||||
LooksGood: '¡Se ve bien!'
|
|
||||||
Oauth: OAuth
|
|
||||||
Oauth20Client:
|
|
||||||
one: Cliente OAuth 2.0
|
|
||||||
other: Clientes de OAuth 2.0
|
|
||||||
Oauth20Settings: Configuración de OAuth 2.0
|
|
||||||
RedirectURI:
|
|
||||||
one: Redirigir URI
|
|
||||||
other: Redirigir URIs
|
|
||||||
Required: Requerido
|
|
||||||
Unauthorized: No Autorizado
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.fi.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.fi.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.fr.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.fr.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.he.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.he.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.hu.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.hu.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
1
vendor/github.com/feditools/go-lib/language/locales/active.it.yaml
generated
vendored
1
vendor/github.com/feditools/go-lib/language/locales/active.it.yaml
generated
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user