Browse Source

feat: Add IsForwarded field to request types for tracking forwarded messages

pull/271/head
Aldino Kemal 12 months ago
parent
commit
8c6b1b3e4a
  1. 5
      src/domains/send/audio.go
  2. 1
      src/domains/send/contact.go
  3. 7
      src/domains/send/file.go
  4. 13
      src/domains/send/image.go
  5. 7
      src/domains/send/link.go
  6. 7
      src/domains/send/location.go
  7. 3
      src/domains/send/presence.go
  8. 1
      src/domains/send/text.go
  9. 11
      src/domains/send/video.go
  10. 70
      src/services/send.go
  11. 14
      src/views/components/SendAudio.js
  12. 20
      src/views/components/SendContact.js
  13. 15
      src/views/components/SendFile.js
  14. 20
      src/views/components/SendImage.js
  15. 10
      src/views/components/SendLink.js
  16. 15
      src/views/components/SendLocation.js
  17. 10
      src/views/components/SendMessage.js
  18. 18
      src/views/components/SendVideo.js

5
src/domains/send/audio.go

@ -3,6 +3,7 @@ package send
import "mime/multipart"
type AudioRequest struct {
Phone string `json:"phone" form:"phone"`
Audio *multipart.FileHeader `json:"audio" form:"audio"`
Phone string `json:"phone" form:"phone"`
Audio *multipart.FileHeader `json:"audio" form:"audio"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

1
src/domains/send/contact.go

@ -4,4 +4,5 @@ type ContactRequest struct {
Phone string `json:"phone" form:"phone"`
ContactName string `json:"contact_name" form:"contact_name"`
ContactPhone string `json:"contact_phone" form:"contact_phone"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

7
src/domains/send/file.go

@ -3,7 +3,8 @@ package send
import "mime/multipart"
type FileRequest struct {
Phone string `json:"phone" form:"phone"`
File *multipart.FileHeader `json:"file" form:"file"`
Caption string `json:"caption" form:"caption"`
Phone string `json:"phone" form:"phone"`
File *multipart.FileHeader `json:"file" form:"file"`
Caption string `json:"caption" form:"caption"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

13
src/domains/send/image.go

@ -3,10 +3,11 @@ package send
import "mime/multipart"
type ImageRequest struct {
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption" form:"caption"`
Image *multipart.FileHeader `json:"image" form:"image"`
ImageURL *string `json:"image_url" form:"image_url"`
ViewOnce bool `json:"view_once" form:"view_once"`
Compress bool `json:"compress"`
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption" form:"caption"`
Image *multipart.FileHeader `json:"image" form:"image"`
ImageURL *string `json:"image_url" form:"image_url"`
ViewOnce bool `json:"view_once" form:"view_once"`
Compress bool `json:"compress"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

7
src/domains/send/link.go

@ -1,7 +1,8 @@
package send
type LinkRequest struct {
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption"`
Link string `json:"link"`
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption"`
Link string `json:"link"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

7
src/domains/send/location.go

@ -1,7 +1,8 @@
package send
type LocationRequest struct {
Phone string `json:"phone" form:"phone"`
Latitude string `json:"latitude" form:"latitude"`
Longitude string `json:"longitude" form:"longitude"`
Phone string `json:"phone" form:"phone"`
Latitude string `json:"latitude" form:"latitude"`
Longitude string `json:"longitude" form:"longitude"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

3
src/domains/send/presence.go

@ -1,5 +1,6 @@
package send
type PresenceRequest struct {
Type string `json:"type" form:"type"`
Type string `json:"type" form:"type"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

1
src/domains/send/text.go

@ -3,5 +3,6 @@ package send
type MessageRequest struct {
Phone string `json:"phone" form:"phone"`
Message string `json:"message" form:"message"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
ReplyMessageID *string `json:"reply_message_id" form:"reply_message_id"`
}

11
src/domains/send/video.go

@ -3,9 +3,10 @@ package send
import "mime/multipart"
type VideoRequest struct {
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption" form:"caption"`
Video *multipart.FileHeader `json:"video" form:"video"`
ViewOnce bool `json:"view_once" form:"view_once"`
Compress bool `json:"compress"`
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption" form:"caption"`
Video *multipart.FileHeader `json:"video" form:"video"`
ViewOnce bool `json:"view_once" form:"view_once"`
Compress bool `json:"compress"`
IsForwarded bool `json:"is_forwarded" form:"is_forwarded"`
}

70
src/services/send.go

@ -59,18 +59,23 @@ func (service serviceSend) SendText(ctx context.Context, request domainSend.Mess
return response, err
}
// Send message
// Create base message
msg := &waE2E.Message{
ExtendedTextMessage: &waE2E.ExtendedTextMessage{
Text: proto.String(request.Message),
Text: proto.String(request.Message),
ContextInfo: &waE2E.ContextInfo{},
},
}
// Add forwarding context if IsForwarded is true
if request.IsForwarded {
msg.ExtendedTextMessage.ContextInfo.IsForwarded = proto.Bool(true)
msg.ExtendedTextMessage.ContextInfo.ForwardingScore = proto.Uint32(100)
}
parsedMentions := service.getMentionFromText(ctx, request.Message)
if len(parsedMentions) > 0 {
msg.ExtendedTextMessage.ContextInfo = &waE2E.ContextInfo{
MentionedJID: parsedMentions,
}
msg.ExtendedTextMessage.ContextInfo.MentionedJID = parsedMentions
}
// Reply message
@ -207,6 +212,13 @@ func (service serviceSend) SendImage(ctx context.Context, request domainSend.Ima
ViewOnce: proto.Bool(request.ViewOnce),
}}
if request.IsForwarded {
msg.ImageMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
caption := "🖼️ Image"
if request.Caption != "" {
caption = "🖼️ " + request.Caption
@ -259,6 +271,14 @@ func (service serviceSend) SendFile(ctx context.Context, request domainSend.File
DirectPath: proto.String(uploadedFile.DirectPath),
Caption: proto.String(request.Caption),
}}
if request.IsForwarded {
msg.DocumentMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
caption := "📄 Document"
if request.Caption != "" {
caption = "📄 " + request.Caption
@ -371,6 +391,14 @@ func (service serviceSend) SendVideo(ctx context.Context, request domainSend.Vid
ThumbnailSHA256: dataWaThumbnail,
ThumbnailDirectPath: proto.String(uploaded.DirectPath),
}}
if request.IsForwarded {
msg.VideoMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
caption := "🎥 Video"
if request.Caption != "" {
caption = "🎥 " + request.Caption
@ -408,6 +436,13 @@ func (service serviceSend) SendContact(ctx context.Context, request domainSend.C
Vcard: proto.String(msgVCard),
}}
if request.IsForwarded {
msg.ContactMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
content := "👤 " + request.ContactName
ts, err := service.wrapSendMessage(ctx, dataWaRecipient, msg, content)
@ -451,6 +486,13 @@ func (service serviceSend) SendLink(ctx context.Context, request domainSend.Link
JPEGThumbnail: metadata.ImageThumb,
}}
if request.IsForwarded {
msg.ExtendedTextMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
// If we have a thumbnail image, upload it to WhatsApp's servers
if len(metadata.ImageThumb) > 0 && metadata.Height != nil && metadata.Width != nil {
uploadedThumb, err := service.uploadMedia(ctx, whatsmeow.MediaLinkThumbnail, metadata.ImageThumb, dataWaRecipient)
@ -499,6 +541,13 @@ func (service serviceSend) SendLocation(ctx context.Context, request domainSend.
},
}
if request.IsForwarded {
msg.LocationMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
content := "📍 " + request.Latitude + ", " + request.Longitude
// Send WhatsApp Message Proto
@ -543,6 +592,13 @@ func (service serviceSend) SendAudio(ctx context.Context, request domainSend.Aud
},
}
if request.IsForwarded {
msg.AudioMessage.ContextInfo = &waE2E.ContextInfo{
IsForwarded: proto.Bool(true),
ForwardingScore: proto.Uint32(100),
}
}
content := "🎵 Audio"
ts, err := service.wrapSendMessage(ctx, dataWaRecipient, msg, content)
@ -567,7 +623,9 @@ func (service serviceSend) SendPoll(ctx context.Context, request domainSend.Poll
content := "📊 " + request.Question
ts, err := service.wrapSendMessage(ctx, dataWaRecipient, service.WaCli.BuildPollCreation(request.Question, request.Options, request.MaxAnswer), content)
msg := service.WaCli.BuildPollCreation(request.Question, request.Options, request.MaxAnswer)
ts, err := service.wrapSendMessage(ctx, dataWaRecipient, msg, content)
if err != nil {
return response, err
}

14
src/views/components/SendAudio.js

@ -10,7 +10,8 @@ export default {
phone: '',
type: window.TYPEUSER,
loading: false,
selectedFileName: null
selectedFileName: null,
is_forwarded: false
}
},
computed: {
@ -27,7 +28,7 @@ export default {
}).modal('show');
},
isValidForm() {
if (this.type !== window.TYPESTATUS && !this.phone.trim()) {
if (this.type !== window.TYPEUSER && !this.phone.trim()) {
return false;
}
@ -55,6 +56,7 @@ export default {
try {
let payload = new FormData();
payload.append("phone", this.phone_id)
payload.append("is_forwarded", this.is_forwarded)
payload.append("audio", $("#file_audio")[0].files[0])
const response = await window.http.post(`/send/audio`, payload)
this.handleReset();
@ -71,6 +73,7 @@ export default {
handleReset() {
this.phone = '';
this.type = window.TYPEUSER;
this.is_forwarded = false;
$("#file_audio").val('');
this.selectedFileName = null;
},
@ -101,6 +104,13 @@ export default {
<div class="content">
<form class="ui form">
<FormRecipient v-model:type="type" v-model:phone="phone"/>
<div class="field">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark audio as forwarded</label>
</div>
</div>
<div class="field" style="padding-bottom: 30px">
<label>Audio</label>
<input type="file" style="display: none" accept="audio/*" id="file_audio" @change="handleFileChange"/>

20
src/views/components/SendContact.js

@ -12,6 +12,7 @@ export default {
card_name: '',
card_phone: '',
loading: false,
is_forwarded: false
}
},
computed: {
@ -27,6 +28,9 @@ export default {
}
}).modal('show');
},
isShowAttributes() {
return this.type !== window.TYPESTATUS;
},
isValidForm() {
if (this.type !== window.TYPESTATUS && !this.phone.trim()) {
return false;
@ -44,18 +48,15 @@ export default {
},
async handleSubmit() {
try {
this.loading = true;
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendContact').modal('hide');
} catch (err) {
showErrorInfo(err)
} finally {
this.loading = false;
}
},
async submitApi() {
if (!this.isValidForm() || this.loading) {
if (!this.isValidForm()) {
return;
}
@ -64,7 +65,8 @@ export default {
const payload = {
phone: this.phone_id,
contact_name: this.card_name,
contact_phone: this.card_phone
contact_phone: this.card_phone,
is_forwarded: this.is_forwarded
}
let response = await window.http.post(`/send/contact`, payload)
this.handleReset();
@ -83,6 +85,7 @@ export default {
this.card_name = '';
this.card_phone = '';
this.type = window.TYPEUSER;
this.is_forwarded = false;
},
},
template: `
@ -116,6 +119,13 @@ export default {
<input v-model="card_phone" type="text" placeholder="Please enter contact phone"
aria-label="contact phone">
</div>
<div class="field" v-if="isShowAttributes()">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark contact as forwarded</label>
</div>
</div>
</form>
</div>
<div class="actions">

15
src/views/components/SendFile.js

@ -17,7 +17,8 @@ export default {
type: window.TYPEUSER,
phone: '',
loading: false,
selectedFileName: null
selectedFileName: null,
is_forwarded: false
}
},
computed: {
@ -33,6 +34,9 @@ export default {
}
}).modal('show');
},
isShowAttributes() {
return this.type !== window.TYPESTATUS;
},
isValidForm() {
if (this.type !== window.TYPESTATUS && !this.phone.trim()) {
return false;
@ -63,6 +67,7 @@ export default {
let payload = new FormData();
payload.append("caption", this.caption)
payload.append("phone", this.phone_id)
payload.append("is_forwarded", this.is_forwarded)
payload.append("file", $("#file_file")[0].files[0])
let response = await window.http.post(`/send/file`, payload)
this.handleReset();
@ -81,6 +86,7 @@ export default {
this.phone = '';
this.type = window.TYPEUSER;
this.selectedFileName = null;
this.is_forwarded = false;
$("#file_file").val('');
},
handleFileChange(event) {
@ -117,6 +123,13 @@ export default {
<textarea v-model="caption" placeholder="Type some caption (optional)..."
aria-label="caption"></textarea>
</div>
<div class="field" v-if="isShowAttributes()">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark file as forwarded</label>
</div>
</div>
<div class="field" style="padding-bottom: 30px">
<label>File</label>
<input type="file" style="display: none" id="file_file" @change="handleFileChange">

20
src/views/components/SendImage.js

@ -15,7 +15,8 @@ export default {
loading: false,
selected_file: null,
image_url: null,
preview_url: null
preview_url: null,
is_forwarded: false
}
},
computed: {
@ -23,6 +24,14 @@ export default {
return this.phone + this.type;
},
},
watch: {
view_once(newValue) {
// If view_once is set to true, set is_forwarded to false
if (newValue === true) {
this.is_forwarded = false;
}
}
},
methods: {
openModal() {
$('#modalSendImage').modal({
@ -66,6 +75,7 @@ export default {
payload.append("view_once", this.view_once)
payload.append("compress", this.compress)
payload.append("caption", this.caption)
payload.append("is_forwarded", this.is_forwarded)
const fileInput = $("#file_image");
if (fileInput.length > 0 && fileInput[0].files.length > 0) {
@ -96,6 +106,7 @@ export default {
this.preview_url = null;
this.selected_file = null;
this.image_url = null;
this.is_forwarded = false;
$("#file_image").val('');
},
handleImageChange(event) {
@ -155,6 +166,13 @@ export default {
<label>Check for compressing image to smaller size</label>
</div>
</div>
<div class="field" v-if="isShowAttributes() && !view_once">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark image as forwarded</label>
</div>
</div>
<div class="field">
<label>Image URL</label>
<input type="text" v-model="image_url" placeholder="https://example.com/image.jpg"

10
src/views/components/SendLink.js

@ -13,6 +13,7 @@ export default {
caption: '',
reply_message_id: '',
loading: false,
is_forwarded: false
}
},
computed: {
@ -63,6 +64,7 @@ export default {
phone: this.phone_id,
link: this.link.trim(),
caption: this.caption.trim(),
is_forwarded: this.is_forwarded
};
if (this.reply_message_id !== '') {
payload.reply_message_id = this.reply_message_id;
@ -85,6 +87,7 @@ export default {
this.link = '';
this.caption = '';
this.reply_message_id = '';
this.is_forwarded = false;
},
},
template: `
@ -123,6 +126,13 @@ export default {
<textarea v-model="caption" placeholder="Hello this is caption"
aria-label="caption"></textarea>
</div>
<div class="field" v-if="isShowReplyId()">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark link as forwarded</label>
</div>
</div>
</form>
</div>
<div class="actions">

15
src/views/components/SendLocation.js

@ -12,6 +12,7 @@ export default {
latitude: '',
longitude: '',
loading: false,
is_forwarded: false
}
},
computed: {
@ -43,6 +44,9 @@ export default {
}
}).modal('show');
},
isShowAttributes() {
return this.type !== window.TYPESTATUS;
},
async handleSubmit() {
try {
let response = await this.submitApi()
@ -58,7 +62,8 @@ export default {
const payload = {
phone: this.phone_id,
latitude: this.latitude,
longitude: this.longitude
longitude: this.longitude,
is_forwarded: this.is_forwarded
};
const response = await window.http.post(`/send/location`, payload);
@ -78,6 +83,7 @@ export default {
this.latitude = '';
this.longitude = '';
this.type = window.TYPEUSER;
this.is_forwarded = false;
},
},
template: `
@ -111,6 +117,13 @@ export default {
<input v-model="longitude" type="text" placeholder="Please enter longitude (-180 to 180)"
aria-label="longitude">
</div>
<div class="field" v-if="isShowAttributes()">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark location as forwarded</label>
</div>
</div>
</form>
</div>
<div class="actions">

10
src/views/components/SendMessage.js

@ -11,6 +11,7 @@ export default {
phone: '',
text: '',
reply_message_id: '',
is_forwarded: false,
loading: false,
}
},
@ -58,6 +59,7 @@ export default {
const payload = {
phone: this.phone_id,
message: this.text.trim(),
is_forwarded: this.is_forwarded
};
if (this.reply_message_id !== '') {
payload.reply_message_id = this.reply_message_id;
@ -79,6 +81,7 @@ export default {
this.phone = '';
this.text = '';
this.reply_message_id = '';
this.is_forwarded = false;
},
},
template: `
@ -112,6 +115,13 @@ export default {
<textarea v-model="text" placeholder="Hello this is message text"
aria-label="message"></textarea>
</div>
<div class="field" v-if="isShowReplyId()">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark message as forwarded</label>
</div>
</div>
</form>
</div>
<div class="actions">

18
src/views/components/SendVideo.js

@ -20,6 +20,7 @@ export default {
phone: '',
loading: false,
selectedFileName: null,
is_forwarded: false
}
},
computed: {
@ -27,6 +28,14 @@ export default {
return this.phone + this.type;
},
},
watch: {
view_once(newValue) {
// If view_once is set to true, set is_forwarded to false
if (newValue === true) {
this.is_forwarded = false;
}
}
},
methods: {
openModal() {
$('#modalSendVideo').modal({
@ -81,6 +90,7 @@ export default {
payload.append("caption", this.caption.trim())
payload.append("view_once", this.view_once)
payload.append("compress", this.compress)
payload.append("is_forwarded", this.is_forwarded)
payload.append('video', $("#file_video")[0].files[0])
let response = await window.http.post(`/send/video`, payload)
this.handleReset();
@ -100,6 +110,7 @@ export default {
this.compress = false;
this.phone = '';
this.selectedFileName = null;
this.is_forwarded = false;
$("#file_video").val('');
},
handleFileChange(event) {
@ -152,6 +163,13 @@ export default {
<label>Check for compressing video to smaller size</label>
</div>
</div>
<div class="field" v-if="isShowAttributes() && !view_once">
<label>Is Forwarded</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="is forwarded" v-model="is_forwarded">
<label>Mark video as forwarded</label>
</div>
</div>
<div class="field" style="padding-bottom: 30px">
<label>Video</label>
<input type="file" style="display: none" accept="video/*" id="file_video" @change="handleFileChange">

Loading…
Cancel
Save