Browse Source

feat: fix validation and update dashboard page

pull/15/head
Aldino Kemal 4 years ago
parent
commit
2b0c860335
  1. 8
      src/cmd/root.go
  2. 5
      src/config/settings.go
  3. 2
      src/services/send_service_impl.go
  4. 6
      src/structs/send_struct.go
  5. 9
      src/validations/send_validation.go
  6. 21
      src/validations/send_validation_test.go
  7. 199
      src/views/index.html

8
src/cmd/root.go

@ -7,6 +7,7 @@ import (
"github.com/aldinokemal/go-whatsapp-web-multidevice/middleware"
"github.com/aldinokemal/go-whatsapp-web-multidevice/services"
"github.com/aldinokemal/go-whatsapp-web-multidevice/utils"
"github.com/dustin/go-humanize"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
@ -79,7 +80,12 @@ func runRest(cmd *cobra.Command, args []string) {
userController.Route(app)
app.Get("/", func(ctx *fiber.Ctx) error {
return ctx.Render("index", fiber.Map{"AppHost": fmt.Sprintf("%s://%s", ctx.Protocol(), ctx.Hostname())})
return ctx.Render("index", fiber.Map{
"AppHost": fmt.Sprintf("%s://%s", ctx.Protocol(), ctx.Hostname()),
"AppVersion": config.AppVersion,
"MaxFileSize": humanize.Bytes(uint64(config.WhatsappSettingMaxFileSize)),
"MaxVideoSize": humanize.Bytes(uint64(config.WhatsappSettingMaxVideoSize)),
})
})
err = app.Listen(":" + config.AppPort)

5
src/config/settings.go

@ -3,8 +3,9 @@ package config
type Browser string
var (
AppPort string = "3000"
AppDebug bool = false
AppVersion string = "3.3.0"
AppPort string = "3000"
AppDebug bool = false
PathQrCode string = "statics/qrcode"
PathSendItems string = "statics/senditems"

2
src/services/send_service_impl.go

@ -185,7 +185,7 @@ func (service SendServiceImpl) SendVideo(c *fiber.Ctx, request structs.SendVideo
// Resize Thumbnail
openImageBuffer, err := bimg.Read(thumbnailVideoPath)
resize, err := bimg.NewImage(openImageBuffer).Thumbnail(100)
resize, err := bimg.NewImage(openImageBuffer).Process(bimg.Options{Quality: 90, Width: 600, Embed: true})
if err != nil {
return response, err
}

6
src/structs/send_struct.go

@ -24,7 +24,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 SendType `json:"type" form:"type"`
}
type SendImageResponse struct {
@ -34,7 +34,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 SendType `json:"type" form:"type"`
}
type SendFileResponse struct {
@ -45,7 +45,7 @@ type SendVideoRequest struct {
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption" form:"caption"`
Video *multipart.FileHeader `json:"video" form:"video"`
Type SendType `json:"type" form:"message"`
Type SendType `json:"type" form:"type"`
ViewOnce bool `json:"view_once" form:"view_once"`
Compress bool `json:"compress"`
}

9
src/validations/send_validation.go

@ -7,12 +7,11 @@ import (
"github.com/aldinokemal/go-whatsapp-web-multidevice/utils"
"github.com/dustin/go-humanize"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
)
func ValidateSendMessage(request structs.SendMessageRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.Phone, validation.Required, validation.Length(10, 25)),
validation.Field(&request.Message, validation.Required, validation.Length(1, 50)),
)
@ -25,7 +24,7 @@ func ValidateSendMessage(request structs.SendMessageRequest) {
func ValidateSendImage(request structs.SendImageRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.Phone, validation.Required, validation.Length(10, 25)),
validation.Field(&request.Caption, validation.When(true, validation.Length(1, 200))),
validation.Field(&request.Image, validation.Required),
)
@ -51,7 +50,7 @@ func ValidateSendImage(request structs.SendImageRequest) {
func ValidateSendFile(request structs.SendFileRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.Phone, validation.Required, validation.Length(10, 25)),
validation.Field(&request.File, validation.Required),
)
@ -71,7 +70,7 @@ func ValidateSendFile(request structs.SendFileRequest) {
func ValidateSendVideo(request structs.SendVideoRequest) {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, is.Digit, validation.Length(10, 25)),
validation.Field(&request.Phone, validation.Required, validation.Length(10, 25)),
validation.Field(&request.Video, validation.Required),
)

21
src/validations/send_validation_test.go

@ -2,7 +2,6 @@ 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"
)
@ -24,26 +23,6 @@ func TestValidateSendMessage(t *testing.T) {
}},
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 {

199
src/views/index.html

@ -27,11 +27,10 @@
<h1 class="ui dividing header">[[ app_name ]]</h1>
<h3 class="first">Features</h3>
<div class="ui three cards">
<div class="ui three column stackable grid cards">
<div class="green card" @click="loginModal" style="cursor: pointer">
<div class="content">
<div class="header">Login</div>
<div class="meta">App</div>
<div class="description">
Scan your QRCode and you can use all this API feature
</div>
@ -40,7 +39,6 @@
<div class="green card" @click="logoutProcess" style="cursor: pointer">
<div class="content">
<div class="header">Logout</div>
<div class="meta">App</div>
<div class="description">
Remove your login session in application
</div>
@ -49,7 +47,6 @@
<div class="green card" @click="reconnectProcess" style="cursor: pointer">
<div class="content">
<div class="header">Reconnect</div>
<div class="meta">App</div>
<div class="description">
Reconnect to whatsapp server, please do this if your api doesn't work or your application is down or
restart
@ -58,53 +55,55 @@
</div>
</div>
<div class="ui three cards">
<div class="green card" @click="sendMessageModal('user')" style="cursor: pointer">
<div class="ui four column doubling grid cards">
<div class="green card" @click="infoModal" style="cursor: pointer;">
<div class="content">
<div class="header">Send Message (Text) | Private Message</div>
<div class="meta">App</div>
<div class="header">User Info</div>
<div class="description">
Send any message to any whatsapp number
You can search someone user info by phone
</div>
</div>
</div>
<div class="green card" @click="sendImageModal('user')" style="cursor:pointer;">
<div class="green card" @click="avatarModal" style="cursor: pointer;">
<div class="content">
<div class="header">Send Message (Image) | Private Message</div>
<div class="meta">App</div>
<div class="header">User Avatar</div>
<div class="description">
Send image with
<div class="ui blue horizontal label">jpg/jpeg/png</div>
type
You can search someone avatar by phone
</div>
</div>
</div>
<div class="green card" @click="sendFileModal('user')" style="cursor: pointer">
<div class="green card" @click="groupModal" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (File) | Private Message</div>
<div class="meta">App</div>
<div class="header">User List Groups</div>
<div class="description">
Send any file up to
<div class="ui blue horizontal label">10MB</div>
Display all groups you joined
</div>
</div>
</div>
<div class="green card" @click="privacyModal" style="cursor: pointer">
<div class="content">
<div class="header">User Privacy Setting</div>
<div class="description">
Get your privacy settings
</div>
</div>
</div>
</div>
<div class="ui three cards">
<div class="green card" @click="sendMessageModal('group')" style="cursor: pointer">
<div class="ui four column doubling grid cards">
<div class="green card" @click="sendMessageModal('user')" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (Text) | Group</div>
<div class="meta">App</div>
<a class="ui blue right ribbon label">Private</a>
<div class="header">Send Message </div>
<div class="description">
Send any message to any whatsapp number
</div>
</div>
</div>
<div class="green card" @click="sendImageModal('group')" style="cursor:pointer;">
<div class="green card" @click="sendImageModal('user')" style="cursor:pointer;">
<div class="content">
<div class="header">Send Message (Image) | Group</div>
<div class="meta">App</div>
<a class="ui blue right ribbon label">Private</a>
<div class="header">Send Image</div>
<div class="description">
Send image with
<div class="ui blue horizontal label">jpg/jpeg/png</div>
@ -112,52 +111,66 @@
</div>
</div>
</div>
<div class="green card" @click="sendFileModal('group')" style="cursor: pointer">
<div class="green card" @click="sendFileModal('user')" style="cursor: pointer">
<div class="content">
<div class="header">Send Message (File) | Group</div>
<div class="meta">App</div>
<a class="ui blue right ribbon label">Private</a>
<div class="header">Send File</div>
<div class="description">
Send any file up to
<div class="ui blue horizontal label">10MB</div>
<div class="ui blue horizontal label">{{ .MaxFileSize }}</div>
</div>
</div>
</div>
<div class="green card" @click="sendVideoModal('user')" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Private</a>
<div class="header">Send Video</div>
<div class="description">
Send video <div class="ui blue horizontal label">mp4</div> up to
<div class="ui blue horizontal label">{{ .MaxVideoSize }}</div>
</div>
</div>
</div>
</div>
<div class="ui four cards">
<div class="green card" @click="infoModal" style="cursor: pointer;">
<div class="ui four column doubling grid cards">
<div class="green card" @click="sendMessageModal('group')" style="cursor: pointer">
<div class="content">
<div class="header">User Info</div>
<div class="meta">App</div>
<a class="ui teal right ribbon label">Group</a>
<div class="header">Send Message</div>
<div class="description">
You can search someone user info by phone
Send any message to any whatsapp number
</div>
</div>
</div>
<div class="green card" @click="avatarModal" style="cursor: pointer;">
<div class="green card" @click="sendImageModal('group')" style="cursor:pointer;">
<div class="content">
<div class="header">User Avatar</div>
<div class="meta">App</div>
<a class="ui teal right ribbon label">Group</a>
<div class="header">Send Image</div>
<div class="description">
You can search someone avatar by phone
Send image with
<div class="ui teal horizontal label">jpg/jpeg/png</div>
type
</div>
</div>
</div>
<div class="green card" @click="groupModal" style="cursor: pointer">
<div class="green card" @click="sendFileModal('group')" style="cursor: pointer">
<div class="content">
<div class="header">User List Groups</div>
<div class="meta">App</div>
<a class="ui teal right ribbon label">Group</a>
<div class="header">Send File</div>
<div class="description">
Display all groups you joined
Send any file up to
<div class="ui teal horizontal label">{{ .MaxFileSize }}</div>
</div>
</div>
</div>
<div class="green card" @click="privacyModal" style="cursor: pointer">
<div class="green card" @click="sendVideoModal('group')" style="cursor: pointer">
<div class="content">
<div class="header">User Privacy Setting</div>
<div class="meta">App</div>
<a class="ui teal right ribbon label">Group</a>
<div class="header">Send Video</div>
<div class="description">
Get your privacy settings
Send video <div class="ui teal horizontal label">mp4</div> up to
<div class="ui teal horizontal label">{{ .MaxVideoSize }}</div>
</div>
</div>
</div>
@ -283,6 +296,37 @@
</div>
</div>
<!-- Modal SendFile -->
<div class="ui small modal" id="modalSendVideo">
<i class="close icon"></i>
<div class="header">
Send Video
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Phone / Group ID</label>
<input v-model="video_phone" type="text" placeholder="6289..."
aria-label="phone">
</div>
<div class="field" style="padding-bottom: 30px">
<label>Video</label>
<input type="file" class="inputfile" id="video_file" style="display: none" accept="video/*"/>
<label for="video_file" class="ui positive medium green left floated button" style="color: white">
<i class="ui upload icon"></i>
Upload video
</label>
</div>
</form>
</div>
<div class="actions">
<div class="ui positive right labeled icon button" @click="sendVideoProcess">
Send
<i class="send icon"></i>
</div>
</div>
</div>
<!-- Modal UserGroup -->
<div class="ui small modal" id="modalUserGroup">
<i class="close icon"></i>
@ -301,7 +345,7 @@
</thead>
<tbody v-if="data_groups != null">
<tr v-for="g in data_groups">
<td data-label="GID">[[ g.JID.User ]]</td>
<td data-label="GID">[[ g.JID.split('@')[0] ]]</td>
<td data-label="Name">[[ g.Name ]]</td>
<td data-label="Age">[[ g.Participants.length ]]</td>
<td data-label="Job">[[ g.GroupCreated ]]</td>
@ -666,6 +710,59 @@
}
}
const sendVideo = {
data() {
return {
video_type: 'user',
video_phone: '',
}
},
methods: {
sendVideoModal(type) {
this.video_type = type
$('#modalSendVideo').modal('show');
},
async sendVideoProcess() {
try {
let response = await this.sendVideoApi()
showSuccessInfo(response)
} catch (err) {
showErrorInfo(err)
}
},
sendVideoApi() {
return new Promise(async (resolve, reject) => {
try {
let payload = new FormData();
payload.append("phone", this.video_phone)
payload.append("video", $("#video_file")[0].files[0])
payload.append("type", this.video_type)
let response = await axios.post(`${this.app_host}/send/video`, payload, {
// Axios Bug, always content-type that make boundary not set default by browser https://github.com/axios/axios/issues/1603
transformRequest: (data, headers) => {
delete headers.post['Content-Type'];
return data;
}
})
this.sendVideoReset();
resolve(response.data.message)
} catch (error) {
if (error.response) {
reject(error.response.data.message)
} else {
reject(error.message)
}
}
})
},
sendVideoReset() {
this.video_phone = '';
this.video_type = 'user';
$("#video_file").val('');
},
}
}
const userGroups = {
data() {
return {
@ -843,10 +940,10 @@
data() {
return {
app_host: {{ .AppHost }},
app_name: 'Whatsapp API Multi Device App'
app_name: 'Whatsapp API Multi Device App ({{ .AppVersion }})'
}
},
mixins: [login, logout, reconnect, sendMessage, sendImage, sendFile, userGroups, userPrivacy, userAvatar, userInfo]
mixins: [login, logout, reconnect, sendMessage, sendImage, sendFile, sendVideo, userGroups, userPrivacy, userAvatar, userInfo]
}).mount('#app')
</script>
</body>
Loading…
Cancel
Save