From a0af655a566c6af872b26da6f5ef6981988d57ad Mon Sep 17 00:00:00 2001 From: Rama Priyanto Date: Fri, 20 Feb 2026 18:04:35 +0700 Subject: [PATCH] fix:knowlegde base file --- .../mapper/knowledge_base.mapper.go | 58 +++++++++++++---- .../repository/knowledge_base.repository.go | 24 ++++--- .../service/knowledge_base.service.go | 62 ++++++++++--------- 3 files changed, 91 insertions(+), 53 deletions(-) diff --git a/app/module/knowledge_base/mapper/knowledge_base.mapper.go b/app/module/knowledge_base/mapper/knowledge_base.mapper.go index 1b7d6da..e1d0333 100644 --- a/app/module/knowledge_base/mapper/knowledge_base.mapper.go +++ b/app/module/knowledge_base/mapper/knowledge_base.mapper.go @@ -2,29 +2,61 @@ package mapper import ( "narasi-ahli-be/app/database/entity" + "path/filepath" + res "narasi-ahli-be/app/module/knowledge_base/response" ) -func KnowledgeBaseResponseMapper(kb *entity.KnowledgeBase, host string) (out *res.KnowledgeBaseResponse) { +func KnowledgeBaseResponseMapper( + kb *entity.KnowledgeBase, + host string, +) (out *res.KnowledgeBaseResponse) { + if kb == nil { return nil } + viewerBase := host + "/knowledge-base/viewer/" + + var journalUrl, audioUrl, videoUrl *string + + // JOURNAL + if kb.FileJournalUrl != nil && *kb.FileJournalUrl != "" { + filename := filepath.Base(*kb.FileJournalUrl) + url := viewerBase + filename + journalUrl = &url + } + + // AUDIO + if kb.FileAudioUrl != nil && *kb.FileAudioUrl != "" { + filename := filepath.Base(*kb.FileAudioUrl) + url := viewerBase + filename + audioUrl = &url + } + + // VIDEO + if kb.FileVideoUrl != nil && *kb.FileVideoUrl != "" { + filename := filepath.Base(*kb.FileVideoUrl) + url := viewerBase + filename + videoUrl = &url + } + out = &res.KnowledgeBaseResponse{ - ID: kb.ID, - AgentId: kb.AgentId, - AgentName: kb.AgentName, - CreatedById: kb.CreatedById, - Title: kb.Title, - Status: kb.Status, + ID: kb.ID, + AgentId: kb.AgentId, + AgentName: kb.AgentName, + CreatedById: kb.CreatedById, + Title: kb.Title, + Status: kb.Status, - FileJournalUrl: kb.FileJournalUrl, - FileAudioUrl: kb.FileAudioUrl, - FileVideoUrl: kb.FileVideoUrl, + // 🔥 HANYA viewer URL yang dikirim + FileJournalUrl: journalUrl, + FileAudioUrl: audioUrl, + FileVideoUrl: videoUrl, - IsActive: kb.IsActive, - CreatedAt: kb.CreatedAt, - UpdatedAt: kb.UpdatedAt, + IsActive: kb.IsActive, + CreatedAt: kb.CreatedAt, + UpdatedAt: kb.UpdatedAt, } return out diff --git a/app/module/knowledge_base/repository/knowledge_base.repository.go b/app/module/knowledge_base/repository/knowledge_base.repository.go index d29bea0..94bcb5d 100644 --- a/app/module/knowledge_base/repository/knowledge_base.repository.go +++ b/app/module/knowledge_base/repository/knowledge_base.repository.go @@ -118,25 +118,29 @@ func (r *KnowledgeBaseRepository) Delete(id uint) (err error) { return r.DB.DB.Delete(&entity.KnowledgeBase{}, id).Error } -func (r *KnowledgeBaseRepository) FindByFilename(filename string) (data *entity.KnowledgeBase, fileType string, err error) { - query := r.DB.DB.Model(&entity.KnowledgeBase{}).Where("is_active = ?", true) +func (r *KnowledgeBaseRepository) FindByFilename(filename string) (*entity.KnowledgeBase, string, error) { - // cari berdasarkan url yang mengandung filename + var kb entity.KnowledgeBase like := "%" + filename - // journal - var kb entity.KnowledgeBase - if err := query.Where("file_journal_url LIKE ?", like).First(&kb).Error; err == nil { + if err := r.DB.DB. + Where("is_active = ?", true). + Where("file_journal_url LIKE ?", like). + First(&kb).Error; err == nil { return &kb, "journal", nil } - // audio - if err := query.Where("file_audio_url LIKE ?", like).First(&kb).Error; err == nil { + if err := r.DB.DB. + Where("is_active = ?", true). + Where("file_audio_url LIKE ?", like). + First(&kb).Error; err == nil { return &kb, "audio", nil } - // video - if err := query.Where("file_video_url LIKE ?", like).First(&kb).Error; err == nil { + if err := r.DB.DB. + Where("is_active = ?", true). + Where("file_video_url LIKE ?", like). + First(&kb).Error; err == nil { return &kb, "video", nil } diff --git a/app/module/knowledge_base/service/knowledge_base.service.go b/app/module/knowledge_base/service/knowledge_base.service.go index e5d555f..ddb66fe 100644 --- a/app/module/knowledge_base/service/knowledge_base.service.go +++ b/app/module/knowledge_base/service/knowledge_base.service.go @@ -88,9 +88,11 @@ func (s *KnowledgeBaseService) uploadFileToMinio( newFilename := fmt.Sprintf("%s_%d%s", filenameWithoutExt, now.UnixNano(), ext) objectName := fmt.Sprintf( - "knowledge-base/%s/%s/%s", + "knowledge-base/%s/%s/%d/%d/%s", agentId, folder, + now.Year(), + now.Month(), newFilename, ) @@ -100,13 +102,16 @@ func (s *KnowledgeBaseService) uploadFileToMinio( objectName, src, fileHeader.Size, - minio.PutObjectOptions{}, + minio.PutObjectOptions{ + ContentType: mime.TypeByExtension(ext), + }, ) if err != nil { return nil, err } - return &newFilename, nil + // 🔥 RETURN OBJECT PATH, BUKAN FILENAME + return &objectName, nil } func (s *KnowledgeBaseService) All(req request.KnowledgeBaseQueryRequest) (data []*response.KnowledgeBaseResponse, paging paginator.Pagination, err error) { @@ -134,36 +139,39 @@ func getFileExtension(filename string) string { return parts[len(parts)-1] } -func (s *KnowledgeBaseService) Viewer(c *fiber.Ctx) (err error) { +func (s *KnowledgeBaseService) Viewer(c *fiber.Ctx) error { + filename := c.Params("filename") result, folder, err := s.Repo.FindByFilename(filename) if err != nil { - return err + return fiber.NewError(fiber.StatusNotFound, "file not found") + } + + var objectName string + + switch folder { + case "journal": + objectName = *result.FileJournalUrl + case "audio": + objectName = *result.FileAudioUrl + case "video": + objectName = *result.FileVideoUrl + default: + return fiber.NewError(fiber.StatusNotFound, "invalid file type") } ctx := context.Background() bucketName := s.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName - objectName := fmt.Sprintf("knowledge-base/%s/%s/%s", *result.AgentId, folder, filename) - - s.Log.Info(). - Str("timestamp", time.Now().Format(time.RFC3339)). - Str("Service:Resource", "KnowledgeBase:Viewer"). - Interface("objectName", objectName). - Msg("") - minioClient, err := s.MinioStorage.ConnectMinio() if err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "error": true, - "msg": err.Error(), - }) + return fiber.ErrInternalServerError } fileContent, err := minioClient.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{}) if err != nil { - return err + return fiber.NewError(fiber.StatusNotFound, "file not found in storage") } defer fileContent.Close() @@ -171,13 +179,11 @@ func (s *KnowledgeBaseService) Viewer(c *fiber.Ctx) (err error) { if contentType == "" { contentType = "application/octet-stream" } + c.Set("Content-Type", contentType) - if _, err := io.Copy(c.Response().BodyWriter(), fileContent); err != nil { - return err - } - - return nil + _, err = io.Copy(c.Response().BodyWriter(), fileContent) + return err } func (s *KnowledgeBaseService) Show(id uint) (data *response.KnowledgeBaseResponse, err error) { @@ -233,19 +239,15 @@ func (s *KnowledgeBaseService) Create(c *fiber.Ctx) (data *response.KnowledgeBas entity := req.ToEntity() - viewerBase := s.Cfg.App.Domain + "/knowledge-base/viewer/" if journalFilename != nil { - journalUrl := viewerBase + *journalFilename - entity.FileJournalUrl = &journalUrl + entity.FileJournalUrl = journalFilename } if audioFilename != nil { - audioUrl := viewerBase + *audioFilename - entity.FileAudioUrl = &audioUrl + entity.FileAudioUrl = audioFilename } if videoFilename != nil { - videoUrl := viewerBase + *videoFilename - entity.FileVideoUrl = &videoUrl + entity.FileVideoUrl = videoFilename } if req.Status < 0 {