commit
49678e36c2
27 changed files with 1073 additions and 0 deletions
-
5.dockerignore
-
1.env.example
-
5.gitignore
-
33.goreleaser.yml
-
3.vscode/settings.json
-
28Dockerfile
-
93Makefile
-
77README.md
-
99cmd/main/main.go
-
11go.mod
-
66go.sum
-
14internal/index/auth/jwt.go
-
57internal/index/index.go
-
5internal/index/model/request.go
-
5internal/index/model/response.go
-
35internal/route.go
-
20internal/whatsapp/model/request.go
-
45internal/whatsapp/whatsapp.go
-
35pkg/auth/auth.go
-
59pkg/auth/basic.go
-
88pkg/env/env.go
-
29pkg/log/log.go
-
20pkg/router/handler.go
-
27pkg/router/middleware.go
-
180pkg/router/response.go
-
32pkg/router/router.go
-
1pkg/whatsapp/whatsapp.go
@ -0,0 +1,5 @@ |
|||
dist |
|||
vendor |
|||
.env |
|||
**/.DS_Store |
|||
**/.gitkeep |
|||
@ -0,0 +1 @@ |
|||
API_BASE_URL=/api/v1/whatsapp |
|||
@ -0,0 +1,5 @@ |
|||
dist |
|||
vendor |
|||
.env |
|||
*.DS_Store |
|||
!*.gitkeep |
|||
@ -0,0 +1,33 @@ |
|||
before: |
|||
hooks: |
|||
- make vendor |
|||
builds: |
|||
- main: ./cmd/main/main.go |
|||
env: |
|||
- CGO_ENABLED=0 |
|||
ldflags: |
|||
- -s -w |
|||
goos: |
|||
- darwin |
|||
- linux |
|||
- windows |
|||
goarch: |
|||
- 386 |
|||
- amd64 |
|||
archives: |
|||
- replacements: |
|||
darwin: macos |
|||
linux: linux |
|||
windows: windows |
|||
386: 32-bit |
|||
amd64: 64-bit |
|||
format: zip |
|||
checksum: |
|||
name_template: 'checksums.txt' |
|||
snapshot: |
|||
name_template: "{{ .Version }}_{{ .ShortCommit }}" |
|||
changelog: |
|||
filters: |
|||
exclude: |
|||
- '^docs:' |
|||
- '^test:' |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"go.inferGopath": false |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
# Builder Image |
|||
# --------------------------------------------------- |
|||
FROM dimaskiddo/alpine:go-1.15 AS go-builder |
|||
|
|||
WORKDIR /usr/src/app |
|||
|
|||
COPY . ./ |
|||
|
|||
RUN go mod download \ |
|||
&& CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -a -o main cmd/main/main.go |
|||
|
|||
|
|||
# Final Image |
|||
# --------------------------------------------------- |
|||
FROM dimaskiddo/alpine:base |
|||
MAINTAINER Dimas Restu Hidayanto <dimas.restu@student.upi.edu> |
|||
|
|||
ARG SERVICE_NAME="go-whatsapp-multidevice-rest" |
|||
|
|||
ENV PATH $PATH:/usr/app/${SERVICE_NAME} |
|||
|
|||
WORKDIR /usr/app/${SERVICE_NAME} |
|||
|
|||
COPY --from=go-builder /usr/src/app/main ./main |
|||
|
|||
EXPOSE 3000 |
|||
|
|||
CMD ["main"] |
|||
@ -0,0 +1,93 @@ |
|||
BUILD_CGO_ENABLED := 0 |
|||
SERVICE_NAME := go-whatsapp-multidevice-rest |
|||
SERVICE_PORT := 3000 |
|||
IMAGE_NAME := go-whatsapp-multidevice-rest |
|||
IMAGE_TAG := latest |
|||
REBASE_URL := "github.com/dimaskiddo/go-whatsapp-multidevice-rest" |
|||
COMMIT_MSG := "update improvement" |
|||
|
|||
.PHONY: |
|||
|
|||
.SILENT: |
|||
|
|||
init: |
|||
make clean |
|||
GO111MODULE=on go mod init |
|||
|
|||
init-dist: |
|||
mkdir -p dist |
|||
|
|||
vendor: |
|||
make clean |
|||
GO111MODULE=on go mod vendor |
|||
|
|||
release: |
|||
make vendor |
|||
make clean-dist |
|||
goreleaser --snapshot --skip-publish --rm-dist |
|||
echo "Release '$(SERVICE_NAME)' complete, please check dist directory." |
|||
|
|||
publish: |
|||
make vendor |
|||
make clean-dist |
|||
GITHUB_TOKEN=$(GITHUB_TOKEN) goreleaser --rm-dist |
|||
echo "Publish '$(SERVICE_NAME)' complete, please check your repository releases." |
|||
|
|||
build: |
|||
make vendor |
|||
CGO_ENABLED=$(BUILD_CGO_ENABLED) go build -ldflags="-s -w" -a -o $(SERVICE_NAME) cmd/main/main.go |
|||
echo "Build '$(SERVICE_NAME)' complete." |
|||
|
|||
run: |
|||
go run cmd/main/*.go |
|||
|
|||
clean-dist: |
|||
rm -rf dist |
|||
|
|||
clean-build: |
|||
rm -f $(SERVICE_NAME) |
|||
|
|||
clean: |
|||
make clean-dist |
|||
make clean-build |
|||
rm -rf vendor |
|||
|
|||
commit: |
|||
make vendor |
|||
make clean |
|||
git add . |
|||
git commit -am $(COMMIT_MSG) |
|||
|
|||
rebase: |
|||
rm -rf .git |
|||
find . -type f -iname "*.go*" -exec sed -i '' -e "s%github.com/dimaskiddo/go-whatsapp-multidevice-rest%$(REBASE_URL)%g" {} \; |
|||
git init |
|||
git remote add origin https://$(REBASE_URL).git |
|||
|
|||
push: |
|||
git push origin master |
|||
|
|||
pull: |
|||
git pull origin master |
|||
|
|||
c-build: |
|||
docker build -t $(IMAGE_NAME):$(IMAGE_TAG) --build-arg SERVICE_NAME=$(SERVICE_NAME) . |
|||
|
|||
c-run: |
|||
docker run -d -p $(SERVICE_PORT):$(SERVICE_PORT) --name $(SERVICE_NAME) --rm $(IMAGE_NAME):$(IMAGE_TAG) |
|||
make c-logs |
|||
|
|||
c-shell: |
|||
docker exec -it $(SERVICE_NAME) bash |
|||
|
|||
c-stop: |
|||
docker stop $(SERVICE_NAME) |
|||
|
|||
c-logs: |
|||
docker logs $(SERVICE_NAME) |
|||
|
|||
c-push: |
|||
docker push $(IMAGE_NAME):$(IMAGE_TAG) |
|||
|
|||
c-clean: |
|||
docker rmi -f $(IMAGE_NAME):$(IMAGE_TAG) |
|||
@ -0,0 +1,77 @@ |
|||
# Go WhatsApp Multi-Device Implementation in REST API |
|||
|
|||
This repository contains example of implementation [go.mau.fi/whatsmeow](https://go.mau.fi/whatsmeow/) package. This example is using a [labstack/echo](https://github.com/labstack/echo) version 4.x. |
|||
|
|||
## Getting Started |
|||
|
|||
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. |
|||
See deployment for notes on how to deploy the project on a live system. |
|||
|
|||
### Prerequisites |
|||
|
|||
Prequisites package: |
|||
* Go (Go Programming Language) |
|||
* Make (Automated Execution using Makefile) |
|||
|
|||
Optional package: |
|||
* GoReleaser (Go Automated Binaries Build) |
|||
* Docker (Application Containerization) |
|||
|
|||
### Installing |
|||
|
|||
Below is the instructions to make this codebase running: |
|||
* Create a Go Workspace directory and export it as the extended GOPATH directory |
|||
``` |
|||
cd <your_go_workspace_directory> |
|||
export GOPATH=$GOPATH:"`pwd`" |
|||
``` |
|||
* Under the Go Workspace directory create a source directory |
|||
``` |
|||
mkdir -p src/github.com/dimaskiddo/go-whatsapp-multidevice-rest |
|||
``` |
|||
* Move to the created directory and pull codebase |
|||
``` |
|||
cd src/github.com/dimaskiddo/go-whatsapp-multidevice-rest |
|||
git clone -b master https://github.com/dimaskiddo/go-whatsapp-multidevice-rest.git . |
|||
``` |
|||
* Run following command to pull dependecies package |
|||
``` |
|||
make vendor |
|||
``` |
|||
* Until this step you already can run this code by using this command |
|||
``` |
|||
make run |
|||
``` |
|||
|
|||
## Running The Tests |
|||
|
|||
Currently the test is not ready yet :) |
|||
|
|||
## Deployment |
|||
|
|||
To build this code to binaries for distribution purposes you can run following command: |
|||
``` |
|||
make release |
|||
``` |
|||
The build result will shown in build directory |
|||
|
|||
## API Access |
|||
|
|||
You can access any endpoint under **API_BASE_URL** environment variable which by default located at */*. |
|||
|
|||
## Built With |
|||
|
|||
* [Go](https://golang.org/) - Go Programming Languange |
|||
* [GoReleaser](https://github.com/goreleaser/goreleaser) - Go Automated Binaries Build |
|||
* [Make](https://www.gnu.org/software/make/) - GNU Make Automated Execution |
|||
* [Docker](https://www.docker.com/) - Application Containerization |
|||
|
|||
## Authors |
|||
|
|||
* **Dimas Restu Hidayanto** - *Initial Work* - [DimasKiddo](https://github.com/dimaskiddo) |
|||
|
|||
See also the list of [contributors](https://github.com/dimaskiddo/go-whatsapp-multidevice-rest/contributors) who participated in this project |
|||
|
|||
## Annotation |
|||
|
|||
You can seek more information for the make command parameters in the [Makefile](https://github.com/dimaskiddo/go-whatsapp-multidevice-rest/-/raw/master/Makefile) |
|||
@ -0,0 +1,99 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"context" |
|||
"net/http" |
|||
"os" |
|||
"os/signal" |
|||
"syscall" |
|||
"time" |
|||
|
|||
"github.com/labstack/echo/v4" |
|||
"github.com/labstack/echo/v4/middleware" |
|||
|
|||
"github.com/go-playground/validator/v10" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/log" |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/router" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal" |
|||
) |
|||
|
|||
type EchoValidator struct { |
|||
Validator *validator.Validate |
|||
} |
|||
|
|||
func (ev *EchoValidator) Validate(i interface{}) error { |
|||
return ev.Validator.Struct(i) |
|||
} |
|||
|
|||
func main() { |
|||
// Initialize Echo
|
|||
e := echo.New() |
|||
|
|||
// Router Recovery
|
|||
e.Use(middleware.Recover()) |
|||
|
|||
// Router Compression
|
|||
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{ |
|||
Level: router.GZipLevel, |
|||
})) |
|||
|
|||
// Router CORS
|
|||
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ |
|||
AllowOrigins: []string{router.CORSOrigin}, |
|||
AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAuthorization, echo.HeaderXRequestedWith}, |
|||
AllowMethods: []string{echo.GET, echo.POST, echo.PUT, echo.PATCH, echo.DELETE, echo.OPTIONS}, |
|||
})) |
|||
|
|||
// Router Security
|
|||
e.Use(middleware.SecureWithConfig(middleware.SecureConfig{ |
|||
ContentTypeNosniff: "nosniff", |
|||
XSSProtection: "1; mode=block", |
|||
XFrameOptions: "SAMEORIGIN", |
|||
})) |
|||
|
|||
// Router Body Size Limit
|
|||
e.Use(middleware.BodyLimitWithConfig(middleware.BodyLimitConfig{ |
|||
Limit: router.BodyLimit, |
|||
})) |
|||
|
|||
// Router RealIP
|
|||
e.Use(router.HttpRealIP()) |
|||
|
|||
// Router Validator
|
|||
e.Validator = &EchoValidator{ |
|||
Validator: validator.New(), |
|||
} |
|||
|
|||
// Router Default Handler
|
|||
e.HTTPErrorHandler = router.HttpErrorHandler |
|||
e.GET("/favicon.ico", router.ResponseNoContent) |
|||
|
|||
// Router Load Routes
|
|||
internal.Routes(e) |
|||
|
|||
// Start Server
|
|||
go func() { |
|||
err := e.Start(":3000") |
|||
if err != nil && err != http.ErrServerClosed { |
|||
log.Print(nil).Fatal(err.Error()) |
|||
} |
|||
}() |
|||
|
|||
// Watch for Shutdown Signal
|
|||
sigShutdown := make(chan os.Signal, 1) |
|||
signal.Notify(sigShutdown, os.Interrupt) |
|||
signal.Notify(sigShutdown, syscall.SIGTERM) |
|||
<-sigShutdown |
|||
|
|||
// Wait 5 Seconds for Graceful Shutdown
|
|||
ctx, cancelShutdown := context.WithTimeout(context.Background(), 5*time.Second) |
|||
defer cancelShutdown() |
|||
|
|||
// Try To Shutdown Server
|
|||
err := e.Shutdown(ctx) |
|||
if err != nil { |
|||
log.Print(nil).Fatal(err.Error()) |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
module github.com/dimaskiddo/go-whatsapp-multidevice-rest |
|||
|
|||
go 1.15 |
|||
|
|||
require ( |
|||
github.com/go-playground/validator/v10 v10.6.1 |
|||
github.com/golang-jwt/jwt v3.2.2+incompatible |
|||
github.com/joho/godotenv v1.3.0 |
|||
github.com/labstack/echo/v4 v4.7.2 |
|||
github.com/sirupsen/logrus v1.8.1 |
|||
) |
|||
@ -0,0 +1,66 @@ |
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= |
|||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= |
|||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= |
|||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= |
|||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= |
|||
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I= |
|||
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk= |
|||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= |
|||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= |
|||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= |
|||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= |
|||
github.com/labstack/echo/v4 v4.7.2 h1:Kv2/p8OaQ+M6Ex4eGimg9b9e6icoxA42JSlOR3msKtI= |
|||
github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= |
|||
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= |
|||
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= |
|||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= |
|||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= |
|||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= |
|||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= |
|||
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
|||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= |
|||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= |
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= |
|||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= |
|||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
|||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= |
|||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= |
|||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= |
|||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= |
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= |
|||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= |
|||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= |
|||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= |
|||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= |
|||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= |
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= |
|||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= |
|||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= |
|||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= |
|||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= |
|||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= |
|||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
|||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
|||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
|||
@ -0,0 +1,14 @@ |
|||
package model |
|||
|
|||
import ( |
|||
"github.com/golang-jwt/jwt" |
|||
) |
|||
|
|||
type AuthJWTClaims struct { |
|||
Data AuthJWTClaimsPayload `json:"dat"` |
|||
jwt.StandardClaims |
|||
} |
|||
|
|||
type AuthJWTClaimsPayload struct { |
|||
MSISDN string `json:"msisdn"` |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
package index |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"time" |
|||
|
|||
"github.com/golang-jwt/jwt" |
|||
"github.com/labstack/echo/v4" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/auth" |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/router" |
|||
|
|||
indexAuth "github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal/index/auth" |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal/index/model" |
|||
) |
|||
|
|||
// Index
|
|||
func Index(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "Go WhatsApp Multi-Device REST is running") |
|||
} |
|||
|
|||
// Auth
|
|||
func Auth(c echo.Context) error { |
|||
var reqAuthBasicInfo model.ReqAuthBasicInfo |
|||
var resAuthJWTData model.ResAuthJWTData |
|||
|
|||
// Parse Basic Auth Information from Rewrited Body Request
|
|||
// By Basic Auth Middleware
|
|||
_ = json.NewDecoder(c.Request().Body).Decode(&reqAuthBasicInfo) |
|||
|
|||
// Create JWT Claims
|
|||
jwtClaims := &indexAuth.AuthJWTClaims{ |
|||
indexAuth.AuthJWTClaimsPayload{ |
|||
MSISDN: reqAuthBasicInfo.Username, |
|||
}, |
|||
jwt.StandardClaims{ |
|||
Issuer: "go-whatsapp-multidevice-rest", |
|||
IssuedAt: time.Now().Unix(), |
|||
ExpiresAt: time.Now().Add(time.Hour * time.Duration(auth.AuthJWTExpiredHour)).Unix(), |
|||
}, |
|||
} |
|||
|
|||
// Create JWT Token
|
|||
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims) |
|||
|
|||
// Generate Encoded JWT Token
|
|||
jwtTokenEncoded, err := jwtToken.SignedString([]byte(auth.AuthJWTSecret)) |
|||
if err != nil { |
|||
return router.ResponseInternalError(c, "") |
|||
} |
|||
|
|||
// Set Encoded JWT Token as Response Data
|
|||
resAuthJWTData.Token = jwtTokenEncoded |
|||
|
|||
// Return JWT Token in JSON Response
|
|||
return router.ResponseSuccessWithData(c, "", resAuthJWTData) |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
package model |
|||
|
|||
type ReqAuthBasicInfo struct { |
|||
Username string |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
package model |
|||
|
|||
type ResAuthJWTData struct { |
|||
Token string `json:"token"` |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
package internal |
|||
|
|||
import ( |
|||
"github.com/labstack/echo/v4" |
|||
"github.com/labstack/echo/v4/middleware" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/auth" |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/router" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal/index" |
|||
indexAuth "github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal/index/auth" |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal/whatsapp" |
|||
) |
|||
|
|||
func Routes(e *echo.Echo) { |
|||
// Route for Index
|
|||
// ---------------------------------------------
|
|||
e.GET(router.BaseURL, index.Index) |
|||
e.GET(router.BaseURL+"/auth", index.Auth, auth.BasicAuth()) |
|||
|
|||
// Route for WhatsApp
|
|||
// ---------------------------------------------
|
|||
authJWTConfig := middleware.JWTConfig{ |
|||
Claims: &indexAuth.AuthJWTClaims{}, |
|||
SigningKey: []byte(auth.AuthJWTSecret), |
|||
} |
|||
|
|||
e.POST(router.BaseURL+"/login", whatsapp.Login, middleware.JWTWithConfig(authJWTConfig)) |
|||
e.POST(router.BaseURL+"/send/text", whatsapp.SendText, middleware.JWTWithConfig(authJWTConfig)) |
|||
e.POST(router.BaseURL+"/send/location", whatsapp.SendLocation, middleware.JWTWithConfig(authJWTConfig)) |
|||
e.POST(router.BaseURL+"/send/document", whatsapp.SendDocument, middleware.JWTWithConfig(authJWTConfig)) |
|||
e.POST(router.BaseURL+"/send/audio", whatsapp.SendAudio, middleware.JWTWithConfig(authJWTConfig)) |
|||
e.POST(router.BaseURL+"/send/image", whatsapp.SendImage, middleware.JWTWithConfig(authJWTConfig)) |
|||
e.POST(router.BaseURL+"/send/video", whatsapp.SendVideo, middleware.JWTWithConfig(authJWTConfig)) |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
package model |
|||
|
|||
type ReqLogin struct { |
|||
Output string |
|||
} |
|||
|
|||
type ReqSendMessage struct { |
|||
MSISDN string |
|||
Message string |
|||
QuotedID string |
|||
QuotedMessage string |
|||
} |
|||
|
|||
type ReqSendLocation struct { |
|||
MSISDN string |
|||
Latitude float64 |
|||
Longitude float64 |
|||
QuotedID string |
|||
QuotedMessage string |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
package whatsapp |
|||
|
|||
import ( |
|||
"github.com/golang-jwt/jwt" |
|||
"github.com/labstack/echo/v4" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/router" |
|||
|
|||
indexAuth "github.com/dimaskiddo/go-whatsapp-multidevice-rest/internal/index/auth" |
|||
) |
|||
|
|||
func getJWTPayload(c echo.Context) indexAuth.AuthJWTClaimsPayload { |
|||
jwtToken := c.Get("user").(*jwt.Token) |
|||
jwtClaims := jwtToken.Claims.(*indexAuth.AuthJWTClaims) |
|||
|
|||
return jwtClaims.Data |
|||
} |
|||
|
|||
func Login(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
|
|||
func SendText(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
|
|||
func SendLocation(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
|
|||
func SendDocument(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
|
|||
func SendImage(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
|
|||
func SendAudio(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
|
|||
func SendVideo(c echo.Context) error { |
|||
return router.ResponseSuccess(c, "") |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
package auth |
|||
|
|||
import ( |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/env" |
|||
) |
|||
|
|||
var AuthBasicUsername string |
|||
var AuthBasicPassword string |
|||
|
|||
var AuthJWTSecret string |
|||
var AuthJWTExpiredHour int |
|||
|
|||
func init() { |
|||
var err error |
|||
|
|||
AuthBasicUsername, err = env.GetEnvString("AUTH_BASIC_USERNAME") |
|||
if err != nil { |
|||
AuthBasicUsername = "administrator" |
|||
} |
|||
|
|||
AuthBasicPassword, err = env.GetEnvString("AUTH_BASIC_PASSWORD") |
|||
if err != nil { |
|||
AuthBasicPassword = "83e4060e-78e1-4fe5-9977-aeeccd46a2b8" |
|||
} |
|||
|
|||
AuthJWTSecret, err = env.GetEnvString("AUTH_JWT_SECRET") |
|||
if err != nil { |
|||
AuthJWTSecret = "9e4eb4cf-be25-4a29-bba3-fefb5a30f6ab" |
|||
} |
|||
|
|||
AuthJWTExpiredHour, err = env.GetEnvInt("AUTH_JWT_EXPIRED_HOUR") |
|||
if err != nil { |
|||
AuthJWTExpiredHour = 24 |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
package auth |
|||
|
|||
import ( |
|||
"encoding/base64" |
|||
"io/ioutil" |
|||
"strings" |
|||
|
|||
"github.com/labstack/echo/v4" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/router" |
|||
) |
|||
|
|||
// BasicAuth Function as Midleware for Basic Authorization
|
|||
func BasicAuth() echo.MiddlewareFunc { |
|||
return func(next echo.HandlerFunc) echo.HandlerFunc { |
|||
return func(c echo.Context) error { |
|||
// Parse HTTP Header Authorization
|
|||
authHeader := strings.SplitN(c.Request().Header.Get("Authorization"), " ", 2) |
|||
|
|||
// Check HTTP Header Authorization Section
|
|||
// Authorization Section Length Should Be 2
|
|||
// The First Authorization Section Should Be "Basic"
|
|||
if len(authHeader) != 2 || authHeader[0] != "Basic" { |
|||
return router.ResponseAuthenticate(c) |
|||
} |
|||
|
|||
// The Second Authorization Section Should Be The Credentials Payload
|
|||
// But We Should Decode it First From Base64 Encoding
|
|||
authPayload, err := base64.StdEncoding.DecodeString(authHeader[1]) |
|||
if err != nil { |
|||
return router.ResponseInternalError(c, "") |
|||
} |
|||
|
|||
// Split Decoded Authorization Payload Into Username and Password Credentials
|
|||
authCredentials := strings.SplitN(string(authPayload), ":", 2) |
|||
|
|||
// Check Credentials Section
|
|||
// It Should Have 2 Section, Username and Password
|
|||
if len(authCredentials) != 2 { |
|||
return router.ResponseBadRequest(c, "") |
|||
} |
|||
|
|||
// Validate Authentication Password
|
|||
if authCredentials[1] != AuthBasicPassword { |
|||
return router.ResponseBadRequest(c, "Invalid Authentication") |
|||
} |
|||
|
|||
// Make Credentials to JSON Format
|
|||
authInformation := `{"username": "` + authCredentials[0] + `"}` |
|||
|
|||
// Rewrite Body Content With Credentials in JSON Format
|
|||
c.Request().Header.Set("Content-Type", "application/json") |
|||
c.Request().Body = ioutil.NopCloser(strings.NewReader(authInformation)) |
|||
|
|||
// Call Next Handler Function With Current Request
|
|||
return next(c) |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
package env |
|||
|
|||
import ( |
|||
"errors" |
|||
"os" |
|||
"strconv" |
|||
"strings" |
|||
|
|||
_ "github.com/joho/godotenv/autoload" |
|||
) |
|||
|
|||
func SanitizeEnv(envName string) (string, error) { |
|||
if len(envName) == 0 { |
|||
return "", errors.New("Environment Variable Name Should Not Empty") |
|||
} |
|||
|
|||
retValue := strings.TrimSpace(os.Getenv(envName)) |
|||
if len(retValue) == 0 { |
|||
return "", errors.New("Environment Variable '" + envName + "' Has an Empty Value") |
|||
} |
|||
|
|||
return retValue, nil |
|||
} |
|||
|
|||
func GetEnvString(envName string) (string, error) { |
|||
envValue, err := SanitizeEnv(envName) |
|||
if err != nil { |
|||
return "", err |
|||
} |
|||
|
|||
return envValue, nil |
|||
} |
|||
|
|||
func GetEnvBool(envName string) (bool, error) { |
|||
envValue, err := SanitizeEnv(envName) |
|||
if err != nil { |
|||
return false, err |
|||
} |
|||
|
|||
retValue, err := strconv.ParseBool(envValue) |
|||
if err != nil { |
|||
return false, err |
|||
} |
|||
|
|||
return retValue, nil |
|||
} |
|||
|
|||
func GetEnvInt(envName string) (int, error) { |
|||
envValue, err := SanitizeEnv(envName) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
|
|||
retValue, err := strconv.ParseInt(envValue, 0, 0) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
|
|||
return int(retValue), nil |
|||
} |
|||
|
|||
func GetEnvFloat32(envName string) (float32, error) { |
|||
envValue, err := SanitizeEnv(envName) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
|
|||
retValue, err := strconv.ParseFloat(envValue, 32) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
|
|||
return float32(retValue), nil |
|||
} |
|||
|
|||
func GetEnvFloat64(envName string) (float64, error) { |
|||
envValue, err := SanitizeEnv(envName) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
|
|||
retValue, err := strconv.ParseFloat(envValue, 64) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
|
|||
return float64(retValue), nil |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
package log |
|||
|
|||
import ( |
|||
"time" |
|||
|
|||
"github.com/labstack/echo/v4" |
|||
"github.com/sirupsen/logrus" |
|||
) |
|||
|
|||
var logger = logrus.New() |
|||
|
|||
func Print(c echo.Context) *logrus.Entry { |
|||
logger.Formatter = &logrus.TextFormatter{ |
|||
TimestampFormat: time.RFC3339, |
|||
FullTimestamp: true, |
|||
DisableColors: false, |
|||
ForceColors: true, |
|||
} |
|||
|
|||
if c == nil { |
|||
return logger.WithFields(logrus.Fields{}) |
|||
} |
|||
|
|||
return logger.WithFields(logrus.Fields{ |
|||
"remote_ip": c.Request().RemoteAddr, |
|||
"method": c.Request().Method, |
|||
"uri": c.Request().URL.String(), |
|||
}) |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
package router |
|||
|
|||
import ( |
|||
"fmt" |
|||
|
|||
"github.com/labstack/echo/v4" |
|||
) |
|||
|
|||
func HttpErrorHandler(err error, c echo.Context) { |
|||
report, _ := err.(*echo.HTTPError) |
|||
|
|||
response := &ResError{ |
|||
Status: false, |
|||
Code: report.Code, |
|||
Error: fmt.Sprintf("%v", report.Message), |
|||
} |
|||
|
|||
logError(c, response.Code, response.Error) |
|||
c.JSON(response.Code, response) |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package router |
|||
|
|||
import ( |
|||
"net/http" |
|||
"strings" |
|||
|
|||
"github.com/labstack/echo/v4" |
|||
) |
|||
|
|||
func HttpRealIP() echo.MiddlewareFunc { |
|||
return func(next echo.HandlerFunc) echo.HandlerFunc { |
|||
return func(c echo.Context) error { |
|||
if XForwardedFor := c.Request().Header.Get(http.CanonicalHeaderKey("X-Forwarded-For")); XForwardedFor != "" { |
|||
dataIndex := strings.Index(XForwardedFor, ", ") |
|||
if dataIndex == -1 { |
|||
dataIndex = len(XForwardedFor) |
|||
} |
|||
|
|||
c.Request().RemoteAddr = XForwardedFor[:dataIndex] |
|||
} else if XRealIP := c.Request().Header.Get(http.CanonicalHeaderKey("X-Real-IP")); XRealIP != "" { |
|||
c.Request().RemoteAddr = XRealIP |
|||
} |
|||
|
|||
return next(c) |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,180 @@ |
|||
package router |
|||
|
|||
import ( |
|||
"fmt" |
|||
"net/http" |
|||
"strings" |
|||
|
|||
"github.com/labstack/echo/v4" |
|||
|
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/log" |
|||
) |
|||
|
|||
type ResSuccess struct { |
|||
Status bool `json:"status"` |
|||
Code int `json:"code"` |
|||
Message string `json:"message"` |
|||
} |
|||
|
|||
type ResSuccessWithData struct { |
|||
Status bool `json:"status"` |
|||
Code int `json:"code"` |
|||
Message string `json:"message"` |
|||
Data interface{} `json:"data"` |
|||
} |
|||
|
|||
type ResError struct { |
|||
Status bool `json:"status"` |
|||
Code int `json:"code"` |
|||
Error string `json:"error"` |
|||
} |
|||
|
|||
func logSuccess(c echo.Context, code int, message string) { |
|||
statusMessage := http.StatusText(code) |
|||
|
|||
if statusMessage == message || c.Request().RequestURI == BaseURL { |
|||
log.Print(c).Info(fmt.Sprintf("%d %v", code, statusMessage)) |
|||
} else { |
|||
log.Print(c).Info(fmt.Sprintf("%d %v", code, message)) |
|||
} |
|||
} |
|||
|
|||
func logError(c echo.Context, code int, message string) { |
|||
statusMessage := http.StatusText(code) |
|||
|
|||
if statusMessage == message { |
|||
log.Print(c).Error(fmt.Sprintf("%d %v", code, statusMessage)) |
|||
} else { |
|||
log.Print(c).Error(fmt.Sprintf("%d %v", code, message)) |
|||
} |
|||
} |
|||
|
|||
func ResponseSuccess(c echo.Context, message string) error { |
|||
var response ResSuccess |
|||
|
|||
response.Status = true |
|||
response.Code = http.StatusOK |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Message = message |
|||
|
|||
logSuccess(c, response.Code, response.Message) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseSuccessWithData(c echo.Context, message string, data interface{}) error { |
|||
var response ResSuccessWithData |
|||
|
|||
response.Status = true |
|||
response.Code = http.StatusOK |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Message = message |
|||
response.Data = data |
|||
|
|||
logSuccess(c, response.Code, response.Message) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseCreated(c echo.Context, message string) error { |
|||
var response ResSuccess |
|||
|
|||
response.Status = true |
|||
response.Code = http.StatusCreated |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Message = message |
|||
|
|||
logSuccess(c, response.Code, response.Message) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseNoContent(c echo.Context) error { |
|||
return c.NoContent(http.StatusNoContent) |
|||
} |
|||
|
|||
func ResponseNotFound(c echo.Context, message string) error { |
|||
var response ResError |
|||
|
|||
response.Status = false |
|||
response.Code = http.StatusNotFound |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Error = message |
|||
|
|||
logError(c, response.Code, response.Error) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseAuthenticate(c echo.Context) error { |
|||
c.Response().Header().Set("WWW-Authenticate", `Basic realm="Authentication Required"`) |
|||
return ResponseUnauthorized(c, "") |
|||
} |
|||
|
|||
func ResponseUnauthorized(c echo.Context, message string) error { |
|||
var response ResError |
|||
|
|||
response.Status = false |
|||
response.Code = http.StatusUnauthorized |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Error = message |
|||
|
|||
logError(c, response.Code, response.Error) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseBadRequest(c echo.Context, message string) error { |
|||
var response ResError |
|||
|
|||
response.Status = false |
|||
response.Code = http.StatusBadRequest |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Error = message |
|||
|
|||
logError(c, response.Code, response.Error) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseInternalError(c echo.Context, message string) error { |
|||
var response ResError |
|||
|
|||
response.Status = false |
|||
response.Code = http.StatusInternalServerError |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Error = message |
|||
|
|||
logError(c, response.Code, response.Error) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
|
|||
func ResponseBadGateway(c echo.Context, message string) error { |
|||
var response ResError |
|||
|
|||
response.Status = false |
|||
response.Code = http.StatusBadGateway |
|||
|
|||
if strings.TrimSpace(message) == "" { |
|||
message = http.StatusText(response.Code) |
|||
} |
|||
response.Error = message |
|||
|
|||
logError(c, response.Code, response.Error) |
|||
return c.JSON(response.Code, response) |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
package router |
|||
|
|||
import ( |
|||
"github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/env" |
|||
) |
|||
|
|||
var BaseURL, CORSOrigin, BodyLimit string |
|||
var GZipLevel int |
|||
|
|||
func init() { |
|||
var err error |
|||
|
|||
BaseURL, err = env.GetEnvString("API_BASE_URL") |
|||
if err != nil { |
|||
BaseURL = "/" |
|||
} |
|||
|
|||
CORSOrigin, err = env.GetEnvString("HTTP_CORS_ORIGIN") |
|||
if err != nil { |
|||
CORSOrigin = "*" |
|||
} |
|||
|
|||
BodyLimit, err = env.GetEnvString("HTTP_BODY_LIMIT_SIZE") |
|||
if err != nil { |
|||
BodyLimit = "8M" |
|||
} |
|||
|
|||
GZipLevel, err = env.GetEnvInt("HTTP_GZIP_LEVEL") |
|||
if err != nil { |
|||
GZipLevel = 3 |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
package whatsapp |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue