@@ -3,14 +3,18 @@ package usecase
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "os"
7
+ "path/filepath"
6
8
"time"
7
9
10
+ "github.com/aldinokemal/go-whatsapp-web-multidevice/config"
8
11
domainChatStorage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/chatstorage"
9
12
domainMessage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message"
10
13
"github.com/aldinokemal/go-whatsapp-web-multidevice/infrastructure/whatsapp"
11
14
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/utils"
12
15
"github.com/aldinokemal/go-whatsapp-web-multidevice/validations"
13
16
"github.com/sirupsen/logrus"
17
+ "go.mau.fi/whatsmeow"
14
18
"go.mau.fi/whatsmeow/appstate"
15
19
"go.mau.fi/whatsmeow/proto/waCommon"
16
20
"go.mau.fi/whatsmeow/proto/waE2E"
@@ -182,3 +186,126 @@ func (service serviceMessage) StarMessage(ctx context.Context, request domainMes
182
186
}
183
187
return nil
184
188
}
189
+
190
+ // DownloadMedia implements message.IMessageService.
191
+ func (service serviceMessage ) DownloadMedia (ctx context.Context , request domainMessage.DownloadMediaRequest ) (response domainMessage.DownloadMediaResponse , err error ) {
192
+ if err = validations .ValidateDownloadMedia (ctx , request ); err != nil {
193
+ return response , err
194
+ }
195
+
196
+ dataWaRecipient , err := utils .ValidateJidWithLogin (whatsapp .GetClient (), request .Phone )
197
+ if err != nil {
198
+ return response , err
199
+ }
200
+
201
+ // Query the message from chat storage
202
+ message , err := service .chatStorageRepo .GetMessageByID (request .MessageID )
203
+ if err != nil {
204
+ return response , fmt .Errorf ("message not found: %v" , err )
205
+ }
206
+
207
+ if message == nil {
208
+ return response , fmt .Errorf ("message with ID %s not found" , request .MessageID )
209
+ }
210
+
211
+ // Check if message has media
212
+ if message .MediaType == "" || message .URL == "" {
213
+ return response , fmt .Errorf ("message %s does not contain downloadable media" , request .MessageID )
214
+ }
215
+
216
+ // Verify the message is from the specified chat
217
+ if message .ChatJID != dataWaRecipient .String () {
218
+ return response , fmt .Errorf ("message %s does not belong to chat %s" , request .MessageID , dataWaRecipient .String ())
219
+ }
220
+
221
+ // Create directory structure for organized storage
222
+ chatDir := filepath .Join (config .PathMedia , utils .ExtractPhoneNumber (message .ChatJID ))
223
+ dateDir := filepath .Join (chatDir , message .Timestamp .Format ("2006-01-02" ))
224
+
225
+ err = os .MkdirAll (dateDir , 0755 )
226
+ if err != nil {
227
+ return response , fmt .Errorf ("failed to create directory: %v" , err )
228
+ }
229
+
230
+ // Create a downloadable message interface based on media type
231
+ var downloadableMsg interface {}
232
+
233
+ switch message .MediaType {
234
+ case "image" :
235
+ downloadableMsg = & waE2E.ImageMessage {
236
+ URL : proto .String (message .URL ),
237
+ MediaKey : message .MediaKey ,
238
+ FileSHA256 : message .FileSHA256 ,
239
+ FileEncSHA256 : message .FileEncSHA256 ,
240
+ FileLength : proto .Uint64 (message .FileLength ),
241
+ }
242
+ case "video" :
243
+ downloadableMsg = & waE2E.VideoMessage {
244
+ URL : proto .String (message .URL ),
245
+ MediaKey : message .MediaKey ,
246
+ FileSHA256 : message .FileSHA256 ,
247
+ FileEncSHA256 : message .FileEncSHA256 ,
248
+ FileLength : proto .Uint64 (message .FileLength ),
249
+ }
250
+ case "audio" :
251
+ downloadableMsg = & waE2E.AudioMessage {
252
+ URL : proto .String (message .URL ),
253
+ MediaKey : message .MediaKey ,
254
+ FileSHA256 : message .FileSHA256 ,
255
+ FileEncSHA256 : message .FileEncSHA256 ,
256
+ FileLength : proto .Uint64 (message .FileLength ),
257
+ }
258
+ case "document" :
259
+ downloadableMsg = & waE2E.DocumentMessage {
260
+ URL : proto .String (message .URL ),
261
+ MediaKey : message .MediaKey ,
262
+ FileSHA256 : message .FileSHA256 ,
263
+ FileEncSHA256 : message .FileEncSHA256 ,
264
+ FileLength : proto .Uint64 (message .FileLength ),
265
+ FileName : proto .String (message .Filename ),
266
+ }
267
+ case "sticker" :
268
+ downloadableMsg = & waE2E.StickerMessage {
269
+ URL : proto .String (message .URL ),
270
+ MediaKey : message .MediaKey ,
271
+ FileSHA256 : message .FileSHA256 ,
272
+ FileEncSHA256 : message .FileEncSHA256 ,
273
+ FileLength : proto .Uint64 (message .FileLength ),
274
+ }
275
+ default :
276
+ return response , fmt .Errorf ("unsupported media type: %s" , message .MediaType )
277
+ }
278
+
279
+ // Download the media using existing utils.ExtractMedia function
280
+ extractedMedia , err := utils .ExtractMedia (ctx , whatsapp .GetClient (), dateDir , downloadableMsg .(whatsmeow.DownloadableMessage ))
281
+ if err != nil {
282
+ return response , fmt .Errorf ("failed to download media: %v" , err )
283
+ }
284
+
285
+ // Get file size
286
+ fileInfo , err := os .Stat (extractedMedia .MediaPath )
287
+ if err != nil {
288
+ logrus .Warnf ("Could not get file size for %s: %v" , extractedMedia .MediaPath , err )
289
+ }
290
+
291
+ // Build response
292
+ response .MessageID = request .MessageID
293
+ response .Status = fmt .Sprintf ("Media downloaded successfully to %s" , extractedMedia .MediaPath )
294
+ response .MediaType = message .MediaType
295
+ response .Filename = filepath .Base (extractedMedia .MediaPath )
296
+ response .FilePath = extractedMedia .MediaPath
297
+ if fileInfo != nil {
298
+ response .FileSize = fileInfo .Size ()
299
+ }
300
+
301
+ logrus .Info (map [string ]any {
302
+ "message_id" : request .MessageID ,
303
+ "phone" : request .Phone ,
304
+ "chat" : dataWaRecipient .String (),
305
+ "media_type" : response .MediaType ,
306
+ "file_path" : response .FilePath ,
307
+ "file_size" : response .FileSize ,
308
+ })
309
+
310
+ return response , nil
311
+ }
0 commit comments