Browse Source

feat: add send to group

pull/3/head
Aldino kemal 4 years ago
parent
commit
67305e2e2c
  1. 21
      controllers/send_controller.go
  2. 4
      go.mod
  3. 3
      go.sum
  4. 3
      readme.md
  5. 6
      services/send_service_impl.go
  6. 12
      structs/send_struct.go
  7. 19
      validations/send_validation.go
  8. 61
      validations/send_validation_test.go
  9. 74
      views/index.html

21
controllers/send_controller.go

@ -30,7 +30,12 @@ func (controller *SendController) SendText(c *fiber.Ctx) error {
// add validation send message
validations.ValidateSendMessage(request)
request.Phone = request.Phone + "@s.whatsapp.net"
if request.Type == structs.TypeGroup {
request.Phone = request.Phone + "@g.us"
} else {
request.Phone = request.Phone + "@s.whatsapp.net"
}
response, err := controller.Service.SendText(c, request)
utils.PanicIfNeeded(err)
@ -54,7 +59,12 @@ func (controller *SendController) SendImage(c *fiber.Ctx) error {
//add validation send image
validations.ValidateSendImage(request)
request.Phone = request.Phone + "@s.whatsapp.net"
if request.Type == structs.TypeGroup {
request.Phone = request.Phone + "@g.us"
} else {
request.Phone = request.Phone + "@s.whatsapp.net"
}
response, err := controller.Service.SendImage(c, request)
utils.PanicIfNeeded(err)
@ -78,7 +88,12 @@ func (controller *SendController) SendFile(c *fiber.Ctx) error {
//add validation send image
validations.ValidateSendFile(request)
request.Phone = request.Phone + "@s.whatsapp.net"
if request.Type == structs.TypeGroup {
request.Phone = request.Phone + "@g.us"
} else {
request.Phone = request.Phone + "@s.whatsapp.net"
}
response, err := controller.Service.SendFile(c, request)
utils.PanicIfNeeded(err)

4
go.mod

@ -9,6 +9,7 @@ require (
github.com/h2non/bimg v1.1.6
github.com/mattn/go-sqlite3 v1.14.11
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.7.0
go.mau.fi/whatsmeow v0.0.0-20220210171358-894bfaa70e7b
google.golang.org/protobuf v1.27.1
)
@ -17,12 +18,15 @@ require (
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/klauspost/compress v1.14.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.33.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910 // indirect
golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 // indirect
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

3
go.sum

@ -272,6 +272,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@ -305,6 +306,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@ -805,6 +807,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=

3
readme.md

@ -10,8 +10,7 @@
- `sudo apt install libvips-dev`
- Windows (not recomended, prefer using [WSL](https://docs.microsoft.com/en-us/windows/wsl/install)):
- install vips library, or you can check here https://www.libvips.org/install.html
- `choco install nip2`
- `choco install pkgconfiglite`
- add to [environment variable](https://www.google.com/search?q=windows+add+to+environment+path)
### How to use

6
services/send_service_impl.go

@ -39,7 +39,7 @@ func (service SendServiceImpl) SendText(_ *fiber.Ctx, request structs.SendMessag
if err != nil {
return response, err
} else {
response.Status = fmt.Sprintf("Message sent (server timestamp: %s)", ts)
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
}
return response, nil
}
@ -108,7 +108,7 @@ func (service SendServiceImpl) SendImage(c *fiber.Ctx, request structs.SendImage
if err != nil {
return response, err
} else {
response.Status = fmt.Sprintf("Image message sent (server timestamp: %s)", ts)
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
}
}
@ -165,7 +165,7 @@ func (service SendServiceImpl) SendFile(c *fiber.Ctx, request structs.SendFileRe
if err != nil {
return response, err
} else {
response.Status = fmt.Sprintf("File message sent (server timestamp: %s)", ts)
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
}
}

12
structs/send_struct.go

@ -56,9 +56,15 @@ type UserMyListGroupsResponse struct {
// ============================== SEND ==============================
type SendType string
const TypeUser SendType = "user"
const TypeGroup SendType = "group"
type SendMessageRequest struct {
Phone string `json:"phone" form:"phone"`
Message string `json:"message" form:"message"`
Phone string `json:"phone" form:"phone"`
Message string `json:"message" form:"message"`
Type SendType `json:"type" form:"type"`
}
type SendMessageResponse struct {
@ -70,6 +76,7 @@ type SendImageRequest struct {
Caption string `json:"caption" form:"caption"`
Image *multipart.FileHeader `json:"image" form:"image"`
ViewOnce bool `json:"view_once" form:"view_once"`
Type SendType `json:"type" form:"message"`
}
type SendImageResponse struct {
@ -79,6 +86,7 @@ type SendImageResponse struct {
type SendFileRequest struct {
Phone string `json:"phone" form:"phone"`
File *multipart.FileHeader `json:"file" form:"file"`
Type SendType `json:"type" form:"message"`
}
type SendFileResponse struct {

19
validations/send_validation.go

@ -5,12 +5,11 @@ import (
"github.com/aldinokemal/go-whatsapp-web-multidevice/utils"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
"strings"
)
func ValidateSendMessage(request structs.SendMessageRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.E164, validation.Length(10, 15)),
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.Message, validation.Required, validation.Length(1, 50)),
)
@ -18,16 +17,12 @@ func ValidateSendMessage(request structs.SendMessageRequest) {
panic(utils.ValidationError{
Message: err.Error(),
})
} else if !strings.HasPrefix(request.Phone, "62") {
panic(utils.ValidationError{
Message: "phone number only work for indonesia country (start with 62)",
})
}
}
func ValidateSendImage(request structs.SendImageRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.E164, validation.Length(10, 15)),
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.Caption, validation.When(true, validation.Length(1, 200))),
validation.Field(&request.Image, validation.Required),
)
@ -36,10 +31,6 @@ func ValidateSendImage(request structs.SendImageRequest) {
panic(utils.ValidationError{
Message: err.Error(),
})
} else if !strings.HasPrefix(request.Phone, "62") {
panic(utils.ValidationError{
Message: "phone number only work for indonesia country (start with 62)",
})
}
availableMimes := map[string]bool{
@ -58,7 +49,7 @@ func ValidateSendImage(request structs.SendImageRequest) {
func ValidateSendFile(request structs.SendFileRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.E164, validation.Length(10, 15)),
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.File, validation.Required),
)
@ -66,10 +57,6 @@ func ValidateSendFile(request structs.SendFileRequest) {
panic(utils.ValidationError{
Message: err.Error(),
})
} else if !strings.HasPrefix(request.Phone, "62") {
panic(utils.ValidationError{
Message: "phone number only work for indonesia country (start with 62)",
})
}
if request.File.Size > 10240000 { // 10MB

61
validations/send_validation_test.go

@ -0,0 +1,61 @@
package validations
import (
"github.com/aldinokemal/go-whatsapp-web-multidevice/structs"
"github.com/aldinokemal/go-whatsapp-web-multidevice/utils"
"github.com/stretchr/testify/assert"
"testing"
)
func TestValidateSendMessage(t *testing.T) {
type args struct {
request structs.SendMessageRequest
}
tests := []struct {
name string
args args
err interface{}
}{
{
name: "success phone & message normal",
args: args{request: structs.SendMessageRequest{
Phone: "6289685024091",
Message: "Hello this is testing",
}},
err: nil,
},
{
name: "error invalid phone",
args: args{request: structs.SendMessageRequest{
Phone: "some-random-phone",
Message: "Hello this is testing",
}},
err: utils.ValidationError{
Message: "phone: must contain digits only.",
},
},
{
name: "error invalid phone contains dash (-)",
args: args{request: structs.SendMessageRequest{
Phone: "6289-748-291",
Message: "Hello this is testing",
}},
err: utils.ValidationError{
Message: "phone: must contain digits only.",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.err == nil {
ValidateSendMessage(tt.args.request)
} else {
assert.PanicsWithValue(t, tt.err, func() {
ValidateSendMessage(tt.args.request)
})
}
})
}
}

74
views/index.html

@ -59,9 +59,9 @@
</div>
<div class="ui three cards">
<div class="green card" @click="sendMessageModal" style="cursor: pointer">
<div class="green card" @click="sendMessageModal('user')" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (Text)</div>
<div class="header">Send Message (Text) | Private Message</div>
<div class="meta">App</div>
<div class="description">
Send any message to any
@ -70,9 +70,9 @@
</div>
</div>
</div>
<div class="green card" @click="sendImageModal" style="cursor:pointer;">
<div class="green card" @click="sendImageModal('user')" style="cursor:pointer;">
<div class="content">
<div class="header">Send Message (Image)</div>
<div class="header">Send Message (Image) | Private Message</div>
<div class="meta">App</div>
<div class="description">
Send image with
@ -81,9 +81,44 @@
</div>
</div>
</div>
<div class="green card" @click="sendFileModal" style="cursor: pointer">
<div class="green card" @click="sendFileModal('user')" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (File)</div>
<div class="header">Send Message (File) | Private Message</div>
<div class="meta">App</div>
<div class="description">
Send any file up to
<div class="ui blue horizontal label">10MB</div>
</div>
</div>
</div>
</div>
<div class="ui three cards">
<div class="green card" @click="sendMessageModal('group')" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (Text) | Group</div>
<div class="meta">App</div>
<div class="description">
Send any message to any
<div class="ui blue horizontal label">indonesian</div>
whatsapp number
</div>
</div>
</div>
<div class="green card" @click="sendImageModal('group')" style="cursor:pointer;">
<div class="content">
<div class="header">Send Message (Image) | Group</div>
<div class="meta">App</div>
<div class="description">
Send image with
<div class="ui blue horizontal label">jpg/jpeg/png</div>
type
</div>
</div>
</div>
<div class="green card" @click="sendFileModal('group')" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (File) | Group</div>
<div class="meta">App</div>
<div class="description">
Send any file up to
@ -141,7 +176,7 @@
</div>
<div class="image content">
<div class="ui medium image">
<img :src="login_link">
<img :src="login_link" alt="qrCodeLogin">
</div>
<div class="description">
<div class="ui header">Please scan to connect</div>
@ -165,7 +200,7 @@
<div class="content">
<form class="ui form">
<div class="field">
<label>Phone</label>
<label>Phone / Group ID</label>
<input v-model="message_phone" type="text" placeholder="6289..."
aria-label="phone">
</div>
@ -193,7 +228,7 @@
<div class="content">
<form class="ui form">
<div class="field">
<label>Phone</label>
<label>Phone / Group ID</label>
<input v-model="image_phone" type="text" placeholder="6289..."
aria-label="phone">
</div>
@ -230,7 +265,7 @@
<div class="content">
<form class="ui form">
<div class="field">
<label>Phone</label>
<label>Phone / Group ID</label>
<input v-model="file_phone" type="text" placeholder="6289..."
aria-label="phone">
</div>
@ -473,12 +508,14 @@
const sendMessage = {
data() {
return {
message_type: 'user',
message_phone: '',
message_text: '',
}
},
methods: {
sendMessageModal() {
sendMessageModal(type) {
this.message_type = type
$('#modalSendMessage').modal('show');
},
async sendMessageProcess() {
@ -495,6 +532,7 @@
let payload = new FormData();
payload.append("phone", this.message_phone)
payload.append("message", this.message_text)
payload.append("type", this.message_type)
let response = await axios.post(`${this.app_host}/send/message`, payload)
this.sendMessageReset();
resolve(response.data.message)
@ -510,6 +548,7 @@
sendMessageReset() {
this.message_phone = '';
this.message_text = '';
this.message_type = 'user';
},
}
}
@ -519,10 +558,12 @@
return {
image_phone: '',
image_caption: '',
image_type: 'user',
}
},
methods: {
sendImageModal() {
sendImageModal(type) {
this.image_type = type
$('#modalSendImage').modal('show');
},
async sendImageProcess() {
@ -540,6 +581,7 @@
payload.append("phone", this.image_phone)
payload.append("caption", this.image_caption)
payload.append("image", $("#image_file")[0].files[0])
payload.append("type", this.image_type)
let response = await axios.post(`${this.app_host}/send/image`, payload)
this.sendImageReset();
resolve(response.data.message)
@ -555,6 +597,7 @@
sendImageReset() {
this.image_phone = '';
this.image_caption = '';
this.image_type = 'user';
$("#image_file").val('');
},
}
@ -563,11 +606,13 @@
const sendFile = {
data() {
return {
file_type: 'user',
file_phone: '',
}
},
methods: {
sendFileModal() {
sendFileModal(type) {
this.file_type = type
$('#modalSendFile').modal('show');
},
async sendFileProcess() {
@ -584,6 +629,7 @@
let payload = new FormData();
payload.append("phone", this.file_phone)
payload.append("file", $("#file_file")[0].files[0])
payload.append("type", this.file_type)
let response = await axios.post(`${this.app_host}/send/file`, payload)
this.sendFileReset();
resolve(response.data.message)
@ -598,7 +644,7 @@
},
sendFileReset() {
this.file_phone = '';
this.file_caption = '';
this.file_type = 'user';
$("#file_file").val('');
},
}

Loading…
Cancel
Save