From 534e8977be1aefb00e07308c1524590cf320f521 Mon Sep 17 00:00:00 2001 From: Aldino Kemal Date: Mon, 24 Mar 2025 14:59:16 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20Add=20IsForwarded=20field=20to=20reques?= =?UTF-8?q?t=20types=20for=20tracking=20forwarded=20m=E2=80=A6=20(#271)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: Add IsForwarded field to request types for tracking forwarded messages --- src/domains/send/audio.go | 5 +- src/domains/send/contact.go | 1 + src/domains/send/file.go | 7 +-- src/domains/send/image.go | 13 +++--- src/domains/send/link.go | 7 +-- src/domains/send/location.go | 7 +-- src/domains/send/presence.go | 3 +- src/domains/send/text.go | 1 + src/domains/send/video.go | 11 +++-- src/services/send.go | 70 +++++++++++++++++++++++++--- src/views/components/SendAudio.js | 14 +++++- src/views/components/SendContact.js | 20 ++++++-- src/views/components/SendFile.js | 15 +++++- src/views/components/SendImage.js | 20 +++++++- src/views/components/SendLink.js | 10 ++++ src/views/components/SendLocation.js | 15 +++++- src/views/components/SendMessage.js | 10 ++++ src/views/components/SendVideo.js | 18 +++++++ 18 files changed, 208 insertions(+), 39 deletions(-) diff --git a/src/domains/send/audio.go b/src/domains/send/audio.go index 16da723..5d37080 100644 --- a/src/domains/send/audio.go +++ b/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"` } diff --git a/src/domains/send/contact.go b/src/domains/send/contact.go index dacadcf..8840e80 100644 --- a/src/domains/send/contact.go +++ b/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"` } diff --git a/src/domains/send/file.go b/src/domains/send/file.go index ca57790..663fea2 100644 --- a/src/domains/send/file.go +++ b/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"` } diff --git a/src/domains/send/image.go b/src/domains/send/image.go index b6baf95..18450b2 100644 --- a/src/domains/send/image.go +++ b/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"` } diff --git a/src/domains/send/link.go b/src/domains/send/link.go index c0bf49e..7979bf1 100644 --- a/src/domains/send/link.go +++ b/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"` } diff --git a/src/domains/send/location.go b/src/domains/send/location.go index 43660bd..3d8a661 100644 --- a/src/domains/send/location.go +++ b/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"` } diff --git a/src/domains/send/presence.go b/src/domains/send/presence.go index 301e3e3..baeed08 100644 --- a/src/domains/send/presence.go +++ b/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"` } diff --git a/src/domains/send/text.go b/src/domains/send/text.go index 332762f..d5a15c3 100644 --- a/src/domains/send/text.go +++ b/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"` } diff --git a/src/domains/send/video.go b/src/domains/send/video.go index 5ba739d..818a9e4 100644 --- a/src/domains/send/video.go +++ b/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"` } diff --git a/src/services/send.go b/src/services/send.go index bdfdd10..48a0383 100644 --- a/src/services/send.go +++ b/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 } diff --git a/src/views/components/SendAudio.js b/src/views/components/SendAudio.js index b68f63e..ca4452d 100644 --- a/src/views/components/SendAudio.js +++ b/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 {
+
+ +
+ + +
+
diff --git a/src/views/components/SendContact.js b/src/views/components/SendContact.js index 7758302..6dce006 100644 --- a/src/views/components/SendContact.js +++ b/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 {
+
+ +
+ + +
+
diff --git a/src/views/components/SendFile.js b/src/views/components/SendFile.js index a5de1dc..22bbf0b 100644 --- a/src/views/components/SendFile.js +++ b/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 {
+
+ +
+ + +
+
diff --git a/src/views/components/SendImage.js b/src/views/components/SendImage.js index 0827842..722df8e 100644 --- a/src/views/components/SendImage.js +++ b/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 {
+
+ +
+ + +
+
+
+ +
+ + +
+
diff --git a/src/views/components/SendLocation.js b/src/views/components/SendLocation.js index 226bbc1..1021f80 100644 --- a/src/views/components/SendLocation.js +++ b/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 {
+
+ +
+ + +
+
diff --git a/src/views/components/SendMessage.js b/src/views/components/SendMessage.js index 2fffa25..e7993b3 100644 --- a/src/views/components/SendMessage.js +++ b/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 {
+
+ +
+ + +
+
diff --git a/src/views/components/SendVideo.js b/src/views/components/SendVideo.js index d00dc60..d4b0ea1 100644 --- a/src/views/components/SendVideo.js +++ b/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 {
+
+ +
+ + +
+