diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..60b6702 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,33 @@ +name: Go Test + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + env: + GO111MODULE: on + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.21.0 + + - name: Install dependencies + run: go mod download + + - name: Run tests + run: go test -v ./... + + - name: Check code style + run: gofmt -l -s $(find . -type f -name '*.go' -not -path "./vendor/*") diff --git a/2do.md b/2do.md index 13d69e9..d221b54 100644 --- a/2do.md +++ b/2do.md @@ -32,7 +32,21 @@ - [ ] Add Slack - [ ] Add discord +- [ ] Add github actions security check with gosec (should not exit with status 1 in case of non-critical issues) + ```yaml + - name: Gosec Security Scanner + run: | + export PATH=$PATH:$(go env GOPATH)/bin + go install github.com/securego/gosec/v2/cmd/gosec@latest + echo "[gosec]\n severity = \"medium\"\n" > .gosec.toml + gosec ./... + ``` + - [ ] Load yaml config - [ ] Implement web hook and let the user decide for it. - [ ] Make it ready to be installed using go install, apt install, etc. - [ ] Should we replace docker by contract and use it directly as we will never replace it? Not actually, as we may want to plug a mock instead or wrap its functions +- [ ] `dockeroller/docker/docker.go:29` We should get Docker ENVs from user in case of not default +- [ ] Add linter (golangci-linter to actions) +- [ ] Pass ID to session like the way dongi works, or maybe better! + diff --git a/Makefile b/Makefile index e41e2dd..cbd1771 100644 --- a/Makefile +++ b/Makefile @@ -13,3 +13,7 @@ build-docker: # Build the docker image sample-docker: # Run docker with sample start command docker run --rm ${name}:${version} start --token="something" + +gen: + go generate ./... + \ No newline at end of file diff --git a/cmd/start.go b/cmd/start.go index 8279098..8f89281 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -61,7 +61,7 @@ func startTelegram(docker docker.Docker, token string, whitelistedIDs []int64) { log.Gl.Error(err.Error()) } session := session.New() - handlers.Register(bot, docker, session) + handlers.NewHandler(bot, docker, session) // Middlewares bot.Use(middleware.Whitelist(whitelistedIDs...)) // TODO: Disabled logger middleware for now. diff --git a/entities/queue_test.go b/entities/queue_test.go new file mode 100644 index 0000000..2d43efe --- /dev/null +++ b/entities/queue_test.go @@ -0,0 +1,50 @@ +package entities_test + +import ( + "testing" + + "github.com/arshamalh/dockeroller/entities" + "github.com/stretchr/testify/assert" +) + +func TestNewQueue(t *testing.T) { + assert := assert.New(t) + t.Run("pop priorities", func(t *testing.T) { + // Arrange + queue := entities.NewQueue() + firstInput := "cont1" + secondInput := "cont2" + queue.Push(firstInput).Push(secondInput) + + // Act + firstOutput, err1 := queue.Pop() + secondOutput, err2 := queue.Pop() + + // Assert + assert.Nil(err1) + assert.Nil(err2) + + assert.Equal(firstInput, firstOutput) + assert.Equal(secondInput, secondOutput) + }) + + t.Run("empty queue", func(t *testing.T) { + // Arrange + queue := entities.NewQueue() + + // Act + poppedItem, err := queue.Pop() + + // Assert + assert.NotNil(err) + assert.Equal("", poppedItem) + }) + + t.Run("queue representation", func(t *testing.T) { + queue := entities.NewQueue() + queue.Push("cont1").Push("cont2") + printableString := queue.String() + + assert.Equal("cont1\ncont2\n", printableString) + }) +} diff --git a/go.mod b/go.mod index 69a724a..798468f 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,28 @@ module github.com/arshamalh/dockeroller -go 1.19 +go 1.21.0 require ( github.com/docker/docker v20.10.17+incompatible github.com/joho/godotenv v1.4.0 + go.uber.org/mock v0.3.0 gopkg.in/telebot.v3 v3.0.0 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/k0kubun/pp v3.0.1+incompatible // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.10.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect ) @@ -23,6 +31,7 @@ require ( github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect + github.com/go-faker/faker/v4 v4.4.1 github.com/gogo/protobuf v1.3.2 // indirect github.com/moby/moby v20.10.18+incompatible github.com/opencontainers/go-digest v1.0.0 // indirect @@ -30,8 +39,8 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/cobra v1.7.0 - github.com/stretchr/testify v1.8.4 // indirect + github.com/stretchr/testify v1.8.4 go.uber.org/zap v1.26.0 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect - golang.org/x/sys v0.1.0 // indirect + golang.org/x/sys v0.5.0 // indirect ) diff --git a/go.sum b/go.sum index 82c1034..b3b7db7 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -15,6 +16,10 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/go-faker/faker/v4 v4.2.0 h1:dGebOupKwssrODV51E0zbMrv5e2gO9VWSLNC1WDCpWg= +github.com/go-faker/faker/v4 v4.2.0/go.mod h1:F/bBy8GH9NxOxMInug5Gx4WYeG6fHJZ8Ol/dhcpRub4= +github.com/go-faker/faker/v4 v4.4.1 h1:LY1jDgjVkBZWIhATCt+gkl0x9i/7wC61gZx73GTFb+Q= +github.com/go-faker/faker/v4 v4.4.1/go.mod h1:HRLrjis+tYsbFtIHufEPTAIzcZiRu0rS9EYl2Ccwme4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= @@ -23,17 +28,22 @@ github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3K github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40= +github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/moby/moby v20.10.18+incompatible h1:aAQ5lDb+SDrhVDnoMbR3kSzswd+41X34pex8VRJXvHg= github.com/moby/moby v20.10.18+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= @@ -67,6 +77,9 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -99,10 +112,16 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -113,6 +132,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/telebot.v3 v3.0.0 h1:UgHIiE/RdjoDi6nf4xACM7PU3TqiPVV9vvTydCEnrTo= gopkg.in/telebot.v3 v3.0.0/go.mod h1:7rExV8/0mDDNu9epSrDm/8j22KLaActH1Tbee6YjzWg= diff --git a/session/session_test.go b/session/session_test.go new file mode 100644 index 0000000..0d46dab --- /dev/null +++ b/session/session_test.go @@ -0,0 +1,49 @@ +package session_test + +import ( + "testing" + + "github.com/arshamalh/dockeroller/entities" + "github.com/arshamalh/dockeroller/session" + "github.com/stretchr/testify/assert" +) + +func TestNewSession(t *testing.T) { + assert := assert.New(t) + t.Run("new session", func(t *testing.T) { + s := session.New() + + var userID int64 = 2 + userData := s.Get(userID) + + assert.NotNil(userData) + }) + + t.Run("scene", func(t *testing.T) { + s := session.New() + given := entities.SceneRenameContainer + + var userID int64 = 2 + userData := s.Get(userID) + assert.NotNil(userData) + + userData.SetScene(given) + got := userData.GetScene() + + assert.Equal(given, got) + }) + + t.Run("question", func(t *testing.T) { + s := session.New() + + var userID int64 = 2 + userData := s.Get(userID) + assert.NotNil(userData) + + userData.SetContainerRemoveForm(true, true) + got := userData.GetContainerRemoveForm() + + assert.Equal(true, got.Force) + assert.Equal(true, got.RemoveVolumes) + }) +} diff --git a/session/userdata_test.go b/session/userdata_test.go new file mode 100644 index 0000000..8b01817 --- /dev/null +++ b/session/userdata_test.go @@ -0,0 +1,109 @@ +package session_test + +import ( + "github.com/arshamalh/dockeroller/entities" + "github.com/arshamalh/dockeroller/session" + "github.com/go-faker/faker/v4" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestUserData(t *testing.T) { + assert := assert.New(t) + t.Run("set and get containers", func(t *testing.T) { + s := session.New() + userData := s.Get(2) + fakeContainers := newFakeContainers() + + userData.SetContainers(fakeContainers) + userContainers := userData.GetContainers() + + assert.NotNil(userContainers) + for _, userContainer := range userContainers { + assert.NotNil(userContainer) + } + }) + + t.Run("set and get current container", func(t *testing.T) { + s := session.New() + userData := s.Get(2) + fakeContainers := newFakeContainers() + + userData.SetCurrentContainer(fakeContainers[1]) + userCurrentContainer := userData.GetCurrentContainer() + + assert.NotNil(userCurrentContainer) + }) + + t.Run("set and get images", func(t *testing.T) { + s := session.New() + userData := s.Get(2) + fakeImages := newFakeImages() + + userData.SetImages(fakeImages) + userImages := userData.GetImages() + + assert.NotNil(userImages) + for _, userImage := range userImages { + assert.NotNil(userImage) + } + }) + + t.Run("set and get current image", func(t *testing.T) { + s := session.New() + userData := s.Get(2) + fakeImages := newFakeImages() + + userData.SetCurrentImage(fakeImages[1]) + userCurrentImage := userData.GetCurrentImage() + + assert.NotNil(userCurrentImage) + }) + + t.Run("set and get scene", func(t *testing.T) { + s := session.New() + userData := s.Get(2) + + userData.SetScene(entities.SceneRenameImage) + scene := userData.GetScene() + + assert.NotNil(scene) + assert.Equal(userData.CurrentQuestion, entities.QNewImageName) + + userData.SetScene(entities.SceneRenameContainer) + scene = userData.GetScene() + + assert.NotNil(scene) + assert.Equal(userData.CurrentQuestion, entities.QNewContainerName) + }) +} + +func newFakeContainers() []*entities.Container { + var containers []*entities.Container + for i := 0; i < 3; i++ { + containers = append(containers, &entities.Container{ + ID: faker.UUIDDigit(), + Name: faker.Word(), + State: entities.ContainerStateRunning, + Image: faker.Word(), + Status: faker.Word(), + }) + } + + return containers +} + +func newFakeImages() []*entities.Image { + var images []*entities.Image + for i := 0; i < 3; i++ { + images = append(images, &entities.Image{ + ID: faker.UUIDDigit(), + Size: 12, + Tags: []string{faker.Word(), faker.WORD}, + Status: entities.ImageStatusInUse, + CreatedAt: faker.TIMESTAMP, + }) + } + + return images +} diff --git a/telegram/handlers/container_remove.go b/telegram/handlers/container_remove.go index f97a703..87ec4c0 100644 --- a/telegram/handlers/container_remove.go +++ b/telegram/handlers/container_remove.go @@ -14,7 +14,7 @@ import ( // This handler doesn't remove the container, // it's just a form for setting the options of removing a container in the later "Done" step. func (h *handler) ContainerRemoveForm(ctx telebot.Context) error { - ctx.Respond(&telebot.CallbackResponse{Text: "Please fill the form and press done"}) + ctx.Respond(msgs.FillTheFormAndPressDone) userID := ctx.Chat().ID index, err := strconv.Atoi(ctx.Data()) session := h.session.Get(userID) @@ -47,14 +47,15 @@ func (h *handler) ContainerRemoveDone(ctx telebot.Context) error { if err := h.docker.ContainerRemove(current.ID, cRemoveForm); err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{Text: "Unable to remove container"}) + return ctx.Respond(msgs.UnableToRemoveContainer) } - ctx.Respond(&telebot.CallbackResponse{Text: "Container removed successfully"}) + ctx.Respond(msgs.ContainerRemovedSuccessfully) containers := h.docker.ContainersList(context.TODO(), filters.Args{}) session.SetContainers(containers) if len(containers) == 0 { + // TODO: if container removed and there is no container, get back to the start menu, no extra action needed return ctx.Send("there is no container") } current = containers[0] @@ -72,9 +73,7 @@ func (h *handler) ContainerRemoveForce(ctx telebot.Context) error { session := h.session.Get(userID) if err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{ - Text: "Invalid button 🤔️️️️️️", - }) + return ctx.Respond(msgs.InvalidButton) } current := session.GetContainer(index) @@ -95,9 +94,7 @@ func (h *handler) ContainerRemoveVolumes(ctx telebot.Context) error { index, err := strconv.Atoi(ctx.Data()) if err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{ - Text: "Invalid button 🤔️️️️️️", - }) + return ctx.Respond(msgs.InvalidButton) } current := session.GetContainer(index) diff --git a/telegram/handlers/containers.go b/telegram/handlers/containers.go index 6c12609..be5fc5e 100644 --- a/telegram/handlers/containers.go +++ b/telegram/handlers/containers.go @@ -13,13 +13,12 @@ import ( ) func (h *handler) ContainersList(ctx telebot.Context) error { - ctx.Respond() userID := ctx.Chat().ID session := h.session.Get(userID) containers := h.docker.ContainersList(context.TODO(), filters.Args{}) session.SetContainers(containers) if len(containers) == 0 { - return ctx.Send("there is no container") + return ctx.Respond(msgs.NoContainer) } current := containers[0] return ctx.Send( @@ -40,11 +39,7 @@ func (h *handler) ContainersNavBtn(ctx telebot.Context) error { containers := h.docker.ContainersList(context.TODO(), filters.Args{}) session.SetContainers(containers) if len(containers) == 0 { - return ctx.Respond( - &telebot.CallbackResponse{ - Text: "There is either no containers or you should run /containers again!", - }, - ) + return ctx.Respond(msgs.NoContainer) } index = tools.Indexer(index, len(containers)) current := containers[index] @@ -89,20 +84,12 @@ func (h *handler) ContainerStart(ctx telebot.Context) error { current := session.GetContainer(index) if err := h.docker.ContainerStart(current.ID); err != nil { log.Gl.Error(err.Error()) - return ctx.Respond( - &telebot.CallbackResponse{ - Text: "We cannot start the container!", - }, - ) + return ctx.Respond(msgs.CannotStartTheContainer) } current, err = h.docker.GetContainer(current.ID) if err != nil { - return ctx.Respond( - &telebot.CallbackResponse{ - Text: "Container started, but we're not able to show current state.", - }, - ) + return ctx.Respond(msgs.StartedButUnavailableCurrentState) } return ctx.Edit( msgs.FmtContainer(current), @@ -121,20 +108,12 @@ func (h *handler) ContainerStop(ctx telebot.Context) error { current := session.GetContainer(index) if err := h.docker.ContainerStop(current.ID); err != nil { log.Gl.Error(err.Error()) - return ctx.Respond( - &telebot.CallbackResponse{ - Text: "We cannot stop the container!", - }, - ) + return ctx.Respond(msgs.CannotStopTheContainer) } current, err = h.docker.GetContainer(current.ID) if err != nil { - return ctx.Respond( - &telebot.CallbackResponse{ - Text: "Container stopped, but we're not able to show current state.", - }, - ) + return ctx.Respond(msgs.StoppedButUnavailableCurrentState) } return ctx.Edit( diff --git a/telegram/handlers/containers_test.go b/telegram/handlers/containers_test.go new file mode 100644 index 0000000..0cb79d2 --- /dev/null +++ b/telegram/handlers/containers_test.go @@ -0,0 +1,76 @@ +package handlers_test + +import ( + "context" + "testing" + + "github.com/arshamalh/dockeroller/entities" + "github.com/arshamalh/dockeroller/session" + "github.com/arshamalh/dockeroller/telegram/handlers" + "github.com/arshamalh/dockeroller/telegram/msgs" + "github.com/docker/docker/api/types/filters" + "github.com/go-faker/faker/v4" + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" + "gopkg.in/telebot.v3" +) + +//go:generate mockgen -destination mock_telebot_context_test.go -package handlers_test gopkg.in/telebot.v3 Context +//go:generate mockgen -destination mock_docker_test.go -package handlers_test github.com/arshamalh/dockeroller/docker Docker +// TODO: restructure the session and make its mocks here + +func TestContainersList(t *testing.T) { + assert := assert.New(t) + ctrl := gomock.NewController(t) + + docker := NewMockDocker(ctrl) + ctx := NewMockContext(ctrl) + ssn := session.New() + + containersList := fakeContainers(t, 3) + // pp.Print(containersList) + + offBot, err := telebot.NewBot(telebot.Settings{Offline: true}) + assert.Nil(err, "can't make offline bot") + + handler := handlers.NewHandler(offBot, docker, ssn) + + t.Run("no containers", func(t *testing.T) { + ctx.EXPECT().Respond(msgs.NoContainer).Return(nil) + ctx.EXPECT().Chat().Return(&telebot.Chat{ID: 467}) + docker.EXPECT().ContainersList(context.TODO(), filters.Args{}).Return([]*entities.Container{}) + + err := handler.ContainersList(ctx) + + assert.Nil(err) + }) + + t.Run("picking first container and formatting", func(t *testing.T) { + docker.EXPECT().ContainersList(context.TODO(), filters.Args{}).Return(containersList) + ctx.EXPECT().Chat().Return(&telebot.Chat{ID: 467}) + + ctx.EXPECT().Send(gomock.Any(), gomock.Any()).DoAndReturn(func(receivedContainer interface{}, opts ...interface{}) error { + formattedContainer := msgs.FmtContainer(containersList[0]) + assert.Equal(formattedContainer, receivedContainer) + return nil + }) + + err := handler.ContainersList(ctx) + + assert.Nil(err) + }) + + t.Run("filling the session", func(t *testing.T) {}) +} + +func fakeContainers(t *testing.T, howMany int) []*entities.Container { + containersList := make([]*entities.Container, howMany) + for i, _ := range containersList { + container := new(entities.Container) + if err := faker.FakeData(container); err != nil { + t.Error("can't make stubs", err) + } + containersList[i] = container + } + return containersList +} diff --git a/telegram/handlers/handlers.go b/telegram/handlers/handlers.go index ee55562..af59d51 100644 --- a/telegram/handlers/handlers.go +++ b/telegram/handlers/handlers.go @@ -14,7 +14,7 @@ type handler struct { // log } -func Register(bot *telebot.Bot, docker docker.Docker, session sessionPkg.Session) { +func NewHandler(bot *telebot.Bot, docker docker.Docker, session sessionPkg.Session) *handler { h := &handler{ docker: docker, bot: bot, @@ -55,4 +55,6 @@ func Register(bot *telebot.Bot, docker docker.Docker, session sessionPkg.Session h.bot.Handle(btns.ImgRmPruneCh.Key(), h.ImageRemovePruneChildren) h.bot.Handle(btns.ImgRmDone.Key(), h.ImageRemoveDone) h.bot.Handle(btns.ImgTag.Key(), h.ImageTag) + + return h } diff --git a/telegram/handlers/image_remove.go b/telegram/handlers/image_remove.go index b217d06..4df0037 100644 --- a/telegram/handlers/image_remove.go +++ b/telegram/handlers/image_remove.go @@ -18,10 +18,9 @@ func (h *handler) ImageRemoveForm(ctx telebot.Context) error { index, err := strconv.Atoi(ctx.Data()) if err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{Text: "wrong button clicked!"}) + return ctx.Respond(msgs.InvalidButton) } - // Informational Response - ctx.Respond(&telebot.CallbackResponse{Text: "Please fill the form and press done"}) + ctx.Respond(msgs.FillTheFormAndPressDone) current := session.GetImages()[index] imgRmForm := session.GetImageRemoveForm() @@ -49,10 +48,10 @@ func (h *handler) ImageRemoveDone(ctx telebot.Context) error { if err := h.docker.ImageRemove(context.TODO(), current.ID, imgRmForm.Force, imgRmForm.PruneChildren); err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{Text: "Unable to remove image"}) + return ctx.Respond() } - ctx.Respond(&telebot.CallbackResponse{Text: "Image removed successfully"}) + ctx.Respond(msgs.ImageRemovedSuccessfully) images := h.updateImagesList(userID) if len(images) == 0 { @@ -73,9 +72,7 @@ func (h *handler) ImageRemoveForce(ctx telebot.Context) error { session := h.session.Get(userID) if err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{ - Text: "Invalid button 🤔️️️️️️", - }) + return ctx.Respond(msgs.InvalidButton) } current := session.GetImages()[index] @@ -96,9 +93,7 @@ func (h *handler) ImageRemovePruneChildren(ctx telebot.Context) error { session := h.session.Get(userID) if err != nil { log.Gl.Error(err.Error()) - return ctx.Respond(&telebot.CallbackResponse{ - Text: "Invalid button 🤔️️️️️️", - }) + return ctx.Respond(msgs.InvalidButton) } current := session.GetImages()[index] diff --git a/telegram/handlers/mock_docker_test.go b/telegram/handlers/mock_docker_test.go new file mode 100644 index 0000000..44b6ea4 --- /dev/null +++ b/telegram/handlers/mock_docker_test.go @@ -0,0 +1,199 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/arshamalh/dockeroller/docker (interfaces: Docker) +// +// Generated by this command: +// +// mockgen -destination mock_docker_test.go -package handlers_test github.com/arshamalh/dockeroller/docker Docker +// +// Package handlers_test is a generated GoMock package. +package handlers_test + +import ( + context "context" + io "io" + reflect "reflect" + + entities "github.com/arshamalh/dockeroller/entities" + filters "github.com/docker/docker/api/types/filters" + gomock "go.uber.org/mock/gomock" +) + +// MockDocker is a mock of Docker interface. +type MockDocker struct { + ctrl *gomock.Controller + recorder *MockDockerMockRecorder +} + +// MockDockerMockRecorder is the mock recorder for MockDocker. +type MockDockerMockRecorder struct { + mock *MockDocker +} + +// NewMockDocker creates a new mock instance. +func NewMockDocker(ctrl *gomock.Controller) *MockDocker { + mock := &MockDocker{ctrl: ctrl} + mock.recorder = &MockDockerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDocker) EXPECT() *MockDockerMockRecorder { + return m.recorder +} + +// ContainerLogs mocks base method. +func (m *MockDocker) ContainerLogs(arg0 string) (io.ReadCloser, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainerLogs", arg0) + ret0, _ := ret[0].(io.ReadCloser) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ContainerLogs indicates an expected call of ContainerLogs. +func (mr *MockDockerMockRecorder) ContainerLogs(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerLogs", reflect.TypeOf((*MockDocker)(nil).ContainerLogs), arg0) +} + +// ContainerRemove mocks base method. +func (m *MockDocker) ContainerRemove(arg0 string, arg1 *entities.ContainerRemoveForm) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainerRemove", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// ContainerRemove indicates an expected call of ContainerRemove. +func (mr *MockDockerMockRecorder) ContainerRemove(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerRemove", reflect.TypeOf((*MockDocker)(nil).ContainerRemove), arg0, arg1) +} + +// ContainerRename mocks base method. +func (m *MockDocker) ContainerRename(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainerRename", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// ContainerRename indicates an expected call of ContainerRename. +func (mr *MockDockerMockRecorder) ContainerRename(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerRename", reflect.TypeOf((*MockDocker)(nil).ContainerRename), arg0, arg1) +} + +// ContainerStart mocks base method. +func (m *MockDocker) ContainerStart(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainerStart", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// ContainerStart indicates an expected call of ContainerStart. +func (mr *MockDockerMockRecorder) ContainerStart(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerStart", reflect.TypeOf((*MockDocker)(nil).ContainerStart), arg0) +} + +// ContainerStats mocks base method. +func (m *MockDocker) ContainerStats(arg0 string) (io.ReadCloser, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainerStats", arg0) + ret0, _ := ret[0].(io.ReadCloser) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ContainerStats indicates an expected call of ContainerStats. +func (mr *MockDockerMockRecorder) ContainerStats(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerStats", reflect.TypeOf((*MockDocker)(nil).ContainerStats), arg0) +} + +// ContainerStop mocks base method. +func (m *MockDocker) ContainerStop(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainerStop", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// ContainerStop indicates an expected call of ContainerStop. +func (mr *MockDockerMockRecorder) ContainerStop(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerStop", reflect.TypeOf((*MockDocker)(nil).ContainerStop), arg0) +} + +// ContainersList mocks base method. +func (m *MockDocker) ContainersList(arg0 context.Context, arg1 filters.Args) []*entities.Container { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainersList", arg0, arg1) + ret0, _ := ret[0].([]*entities.Container) + return ret0 +} + +// ContainersList indicates an expected call of ContainersList. +func (mr *MockDockerMockRecorder) ContainersList(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainersList", reflect.TypeOf((*MockDocker)(nil).ContainersList), arg0, arg1) +} + +// GetContainer mocks base method. +func (m *MockDocker) GetContainer(arg0 string) (*entities.Container, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetContainer", arg0) + ret0, _ := ret[0].(*entities.Container) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetContainer indicates an expected call of GetContainer. +func (mr *MockDockerMockRecorder) GetContainer(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContainer", reflect.TypeOf((*MockDocker)(nil).GetContainer), arg0) +} + +// ImageRemove mocks base method. +func (m *MockDocker) ImageRemove(arg0 context.Context, arg1 string, arg2, arg3 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ImageRemove", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// ImageRemove indicates an expected call of ImageRemove. +func (mr *MockDockerMockRecorder) ImageRemove(arg0, arg1, arg2, arg3 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageRemove", reflect.TypeOf((*MockDocker)(nil).ImageRemove), arg0, arg1, arg2, arg3) +} + +// ImageTag mocks base method. +func (m *MockDocker) ImageTag(arg0 context.Context, arg1, arg2 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ImageTag", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ImageTag indicates an expected call of ImageTag. +func (mr *MockDockerMockRecorder) ImageTag(arg0, arg1, arg2 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageTag", reflect.TypeOf((*MockDocker)(nil).ImageTag), arg0, arg1, arg2) +} + +// ImagesList mocks base method. +func (m *MockDocker) ImagesList() []*entities.Image { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ImagesList") + ret0, _ := ret[0].([]*entities.Image) + return ret0 +} + +// ImagesList indicates an expected call of ImagesList. +func (mr *MockDockerMockRecorder) ImagesList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImagesList", reflect.TypeOf((*MockDocker)(nil).ImagesList)) +} diff --git a/telegram/handlers/mock_telebot_context_test.go b/telegram/handlers/mock_telebot_context_test.go new file mode 100644 index 0000000..0df3746 --- /dev/null +++ b/telegram/handlers/mock_telebot_context_test.go @@ -0,0 +1,614 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: gopkg.in/telebot.v3 (interfaces: Context) +// +// Generated by this command: +// +// mockgen -destination mock_telebot_context_test.go -package handlers_test gopkg.in/telebot.v3 Context +// +// Package handlers_test is a generated GoMock package. +package handlers_test + +import ( + reflect "reflect" + time "time" + + gomock "go.uber.org/mock/gomock" + telebot "gopkg.in/telebot.v3" +) + +// MockContext is a mock of Context interface. +type MockContext struct { + ctrl *gomock.Controller + recorder *MockContextMockRecorder +} + +// MockContextMockRecorder is the mock recorder for MockContext. +type MockContextMockRecorder struct { + mock *MockContext +} + +// NewMockContext creates a new mock instance. +func NewMockContext(ctrl *gomock.Controller) *MockContext { + mock := &MockContext{ctrl: ctrl} + mock.recorder = &MockContextMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockContext) EXPECT() *MockContextMockRecorder { + return m.recorder +} + +// Accept mocks base method. +func (m *MockContext) Accept(arg0 ...string) error { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range arg0 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Accept", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Accept indicates an expected call of Accept. +func (mr *MockContextMockRecorder) Accept(arg0 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accept", reflect.TypeOf((*MockContext)(nil).Accept), arg0...) +} + +// Answer mocks base method. +func (m *MockContext) Answer(arg0 *telebot.QueryResponse) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Answer", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Answer indicates an expected call of Answer. +func (mr *MockContextMockRecorder) Answer(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Answer", reflect.TypeOf((*MockContext)(nil).Answer), arg0) +} + +// Args mocks base method. +func (m *MockContext) Args() []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Args") + ret0, _ := ret[0].([]string) + return ret0 +} + +// Args indicates an expected call of Args. +func (mr *MockContextMockRecorder) Args() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Args", reflect.TypeOf((*MockContext)(nil).Args)) +} + +// Bot mocks base method. +func (m *MockContext) Bot() *telebot.Bot { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Bot") + ret0, _ := ret[0].(*telebot.Bot) + return ret0 +} + +// Bot indicates an expected call of Bot. +func (mr *MockContextMockRecorder) Bot() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bot", reflect.TypeOf((*MockContext)(nil).Bot)) +} + +// Callback mocks base method. +func (m *MockContext) Callback() *telebot.Callback { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Callback") + ret0, _ := ret[0].(*telebot.Callback) + return ret0 +} + +// Callback indicates an expected call of Callback. +func (mr *MockContextMockRecorder) Callback() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Callback", reflect.TypeOf((*MockContext)(nil).Callback)) +} + +// Chat mocks base method. +func (m *MockContext) Chat() *telebot.Chat { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Chat") + ret0, _ := ret[0].(*telebot.Chat) + return ret0 +} + +// Chat indicates an expected call of Chat. +func (mr *MockContextMockRecorder) Chat() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Chat", reflect.TypeOf((*MockContext)(nil).Chat)) +} + +// ChatJoinRequest mocks base method. +func (m *MockContext) ChatJoinRequest() *telebot.ChatJoinRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChatJoinRequest") + ret0, _ := ret[0].(*telebot.ChatJoinRequest) + return ret0 +} + +// ChatJoinRequest indicates an expected call of ChatJoinRequest. +func (mr *MockContextMockRecorder) ChatJoinRequest() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChatJoinRequest", reflect.TypeOf((*MockContext)(nil).ChatJoinRequest)) +} + +// ChatMember mocks base method. +func (m *MockContext) ChatMember() *telebot.ChatMemberUpdate { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChatMember") + ret0, _ := ret[0].(*telebot.ChatMemberUpdate) + return ret0 +} + +// ChatMember indicates an expected call of ChatMember. +func (mr *MockContextMockRecorder) ChatMember() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChatMember", reflect.TypeOf((*MockContext)(nil).ChatMember)) +} + +// Data mocks base method. +func (m *MockContext) Data() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Data") + ret0, _ := ret[0].(string) + return ret0 +} + +// Data indicates an expected call of Data. +func (mr *MockContextMockRecorder) Data() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Data", reflect.TypeOf((*MockContext)(nil).Data)) +} + +// Delete mocks base method. +func (m *MockContext) Delete() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete") + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockContextMockRecorder) Delete() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockContext)(nil).Delete)) +} + +// DeleteAfter mocks base method. +func (m *MockContext) DeleteAfter(arg0 time.Duration) *time.Timer { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteAfter", arg0) + ret0, _ := ret[0].(*time.Timer) + return ret0 +} + +// DeleteAfter indicates an expected call of DeleteAfter. +func (mr *MockContextMockRecorder) DeleteAfter(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAfter", reflect.TypeOf((*MockContext)(nil).DeleteAfter), arg0) +} + +// Edit mocks base method. +func (m *MockContext) Edit(arg0 any, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Edit", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Edit indicates an expected call of Edit. +func (mr *MockContextMockRecorder) Edit(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Edit", reflect.TypeOf((*MockContext)(nil).Edit), varargs...) +} + +// EditCaption mocks base method. +func (m *MockContext) EditCaption(arg0 string, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "EditCaption", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// EditCaption indicates an expected call of EditCaption. +func (mr *MockContextMockRecorder) EditCaption(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditCaption", reflect.TypeOf((*MockContext)(nil).EditCaption), varargs...) +} + +// EditOrReply mocks base method. +func (m *MockContext) EditOrReply(arg0 any, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "EditOrReply", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// EditOrReply indicates an expected call of EditOrReply. +func (mr *MockContextMockRecorder) EditOrReply(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditOrReply", reflect.TypeOf((*MockContext)(nil).EditOrReply), varargs...) +} + +// EditOrSend mocks base method. +func (m *MockContext) EditOrSend(arg0 any, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "EditOrSend", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// EditOrSend indicates an expected call of EditOrSend. +func (mr *MockContextMockRecorder) EditOrSend(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditOrSend", reflect.TypeOf((*MockContext)(nil).EditOrSend), varargs...) +} + +// Forward mocks base method. +func (m *MockContext) Forward(arg0 telebot.Editable, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Forward", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Forward indicates an expected call of Forward. +func (mr *MockContextMockRecorder) Forward(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Forward", reflect.TypeOf((*MockContext)(nil).Forward), varargs...) +} + +// ForwardTo mocks base method. +func (m *MockContext) ForwardTo(arg0 telebot.Recipient, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ForwardTo", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// ForwardTo indicates an expected call of ForwardTo. +func (mr *MockContextMockRecorder) ForwardTo(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForwardTo", reflect.TypeOf((*MockContext)(nil).ForwardTo), varargs...) +} + +// Get mocks base method. +func (m *MockContext) Get(arg0 string) any { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(any) + return ret0 +} + +// Get indicates an expected call of Get. +func (mr *MockContextMockRecorder) Get(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockContext)(nil).Get), arg0) +} + +// InlineResult mocks base method. +func (m *MockContext) InlineResult() *telebot.InlineResult { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InlineResult") + ret0, _ := ret[0].(*telebot.InlineResult) + return ret0 +} + +// InlineResult indicates an expected call of InlineResult. +func (mr *MockContextMockRecorder) InlineResult() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InlineResult", reflect.TypeOf((*MockContext)(nil).InlineResult)) +} + +// Message mocks base method. +func (m *MockContext) Message() *telebot.Message { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Message") + ret0, _ := ret[0].(*telebot.Message) + return ret0 +} + +// Message indicates an expected call of Message. +func (mr *MockContextMockRecorder) Message() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Message", reflect.TypeOf((*MockContext)(nil).Message)) +} + +// Migration mocks base method. +func (m *MockContext) Migration() (int64, int64) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Migration") + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(int64) + return ret0, ret1 +} + +// Migration indicates an expected call of Migration. +func (mr *MockContextMockRecorder) Migration() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Migration", reflect.TypeOf((*MockContext)(nil).Migration)) +} + +// Notify mocks base method. +func (m *MockContext) Notify(arg0 telebot.ChatAction) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Notify", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Notify indicates an expected call of Notify. +func (mr *MockContextMockRecorder) Notify(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notify", reflect.TypeOf((*MockContext)(nil).Notify), arg0) +} + +// Poll mocks base method. +func (m *MockContext) Poll() *telebot.Poll { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Poll") + ret0, _ := ret[0].(*telebot.Poll) + return ret0 +} + +// Poll indicates an expected call of Poll. +func (mr *MockContextMockRecorder) Poll() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Poll", reflect.TypeOf((*MockContext)(nil).Poll)) +} + +// PollAnswer mocks base method. +func (m *MockContext) PollAnswer() *telebot.PollAnswer { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PollAnswer") + ret0, _ := ret[0].(*telebot.PollAnswer) + return ret0 +} + +// PollAnswer indicates an expected call of PollAnswer. +func (mr *MockContextMockRecorder) PollAnswer() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PollAnswer", reflect.TypeOf((*MockContext)(nil).PollAnswer)) +} + +// PreCheckoutQuery mocks base method. +func (m *MockContext) PreCheckoutQuery() *telebot.PreCheckoutQuery { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PreCheckoutQuery") + ret0, _ := ret[0].(*telebot.PreCheckoutQuery) + return ret0 +} + +// PreCheckoutQuery indicates an expected call of PreCheckoutQuery. +func (mr *MockContextMockRecorder) PreCheckoutQuery() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PreCheckoutQuery", reflect.TypeOf((*MockContext)(nil).PreCheckoutQuery)) +} + +// Query mocks base method. +func (m *MockContext) Query() *telebot.Query { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Query") + ret0, _ := ret[0].(*telebot.Query) + return ret0 +} + +// Query indicates an expected call of Query. +func (mr *MockContextMockRecorder) Query() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockContext)(nil).Query)) +} + +// Recipient mocks base method. +func (m *MockContext) Recipient() telebot.Recipient { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Recipient") + ret0, _ := ret[0].(telebot.Recipient) + return ret0 +} + +// Recipient indicates an expected call of Recipient. +func (mr *MockContextMockRecorder) Recipient() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recipient", reflect.TypeOf((*MockContext)(nil).Recipient)) +} + +// Reply mocks base method. +func (m *MockContext) Reply(arg0 any, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Reply", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Reply indicates an expected call of Reply. +func (mr *MockContextMockRecorder) Reply(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reply", reflect.TypeOf((*MockContext)(nil).Reply), varargs...) +} + +// Respond mocks base method. +func (m *MockContext) Respond(arg0 ...*telebot.CallbackResponse) error { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range arg0 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Respond", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Respond indicates an expected call of Respond. +func (mr *MockContextMockRecorder) Respond(arg0 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Respond", reflect.TypeOf((*MockContext)(nil).Respond), arg0...) +} + +// Send mocks base method. +func (m *MockContext) Send(arg0 any, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Send", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Send indicates an expected call of Send. +func (mr *MockContextMockRecorder) Send(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockContext)(nil).Send), varargs...) +} + +// SendAlbum mocks base method. +func (m *MockContext) SendAlbum(arg0 telebot.Album, arg1 ...any) error { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "SendAlbum", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendAlbum indicates an expected call of SendAlbum. +func (mr *MockContextMockRecorder) SendAlbum(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendAlbum", reflect.TypeOf((*MockContext)(nil).SendAlbum), varargs...) +} + +// Sender mocks base method. +func (m *MockContext) Sender() *telebot.User { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Sender") + ret0, _ := ret[0].(*telebot.User) + return ret0 +} + +// Sender indicates an expected call of Sender. +func (mr *MockContextMockRecorder) Sender() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sender", reflect.TypeOf((*MockContext)(nil).Sender)) +} + +// Set mocks base method. +func (m *MockContext) Set(arg0 string, arg1 any) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Set", arg0, arg1) +} + +// Set indicates an expected call of Set. +func (mr *MockContextMockRecorder) Set(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockContext)(nil).Set), arg0, arg1) +} + +// Ship mocks base method. +func (m *MockContext) Ship(arg0 ...any) error { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range arg0 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Ship", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Ship indicates an expected call of Ship. +func (mr *MockContextMockRecorder) Ship(arg0 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ship", reflect.TypeOf((*MockContext)(nil).Ship), arg0...) +} + +// ShippingQuery mocks base method. +func (m *MockContext) ShippingQuery() *telebot.ShippingQuery { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ShippingQuery") + ret0, _ := ret[0].(*telebot.ShippingQuery) + return ret0 +} + +// ShippingQuery indicates an expected call of ShippingQuery. +func (mr *MockContextMockRecorder) ShippingQuery() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShippingQuery", reflect.TypeOf((*MockContext)(nil).ShippingQuery)) +} + +// Text mocks base method. +func (m *MockContext) Text() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Text") + ret0, _ := ret[0].(string) + return ret0 +} + +// Text indicates an expected call of Text. +func (mr *MockContextMockRecorder) Text() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Text", reflect.TypeOf((*MockContext)(nil).Text)) +} + +// Update mocks base method. +func (m *MockContext) Update() telebot.Update { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update") + ret0, _ := ret[0].(telebot.Update) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockContextMockRecorder) Update() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockContext)(nil).Update)) +} diff --git a/telegram/msgs/callback_responses.go b/telegram/msgs/callback_responses.go new file mode 100644 index 0000000..1379200 --- /dev/null +++ b/telegram/msgs/callback_responses.go @@ -0,0 +1,21 @@ +package msgs + +import "gopkg.in/telebot.v3" + +var ( + CannotStartTheContainer = NewCallbackResponse("We cannot start the container!") + CannotStopTheContainer = NewCallbackResponse("We cannot stop the container!") + FillTheFormAndPressDone = NewCallbackResponse("Please fill the form and press done") + UnableToRemoveContainer = NewCallbackResponse("Unable to remove container") + ContainerRemovedSuccessfully = NewCallbackResponse("Container removed successfully") + InvalidButton = NewCallbackResponse("Invalid button 🤔️️️️️️") + UnableToRemoveImage = NewCallbackResponse("Unable to remove image") + ImageRemovedSuccessfully = NewCallbackResponse("Image removed successfully") + NoContainer = NewCallbackResponse("There is either no containers or you should run /containers again!") + StartedButUnavailableCurrentState = NewCallbackResponse("Container started, but we're not able to show current state.") + StoppedButUnavailableCurrentState = NewCallbackResponse("Container stopped, but we're not able to show current state.") +) + +func NewCallbackResponse(text string) *telebot.CallbackResponse { + return &telebot.CallbackResponse{Text: text} +}