fix:knowlegde base file
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Rama Priyanto 2026-02-20 18:04:35 +07:00
parent 29387100fa
commit a0af655a56
3 changed files with 91 additions and 53 deletions

View File

@ -2,29 +2,61 @@ package mapper
import ( import (
"narasi-ahli-be/app/database/entity" "narasi-ahli-be/app/database/entity"
"path/filepath"
res "narasi-ahli-be/app/module/knowledge_base/response" 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 { if kb == nil {
return 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{ out = &res.KnowledgeBaseResponse{
ID: kb.ID, ID: kb.ID,
AgentId: kb.AgentId, AgentId: kb.AgentId,
AgentName: kb.AgentName, AgentName: kb.AgentName,
CreatedById: kb.CreatedById, CreatedById: kb.CreatedById,
Title: kb.Title, Title: kb.Title,
Status: kb.Status, Status: kb.Status,
FileJournalUrl: kb.FileJournalUrl, // 🔥 HANYA viewer URL yang dikirim
FileAudioUrl: kb.FileAudioUrl, FileJournalUrl: journalUrl,
FileVideoUrl: kb.FileVideoUrl, FileAudioUrl: audioUrl,
FileVideoUrl: videoUrl,
IsActive: kb.IsActive, IsActive: kb.IsActive,
CreatedAt: kb.CreatedAt, CreatedAt: kb.CreatedAt,
UpdatedAt: kb.UpdatedAt, UpdatedAt: kb.UpdatedAt,
} }
return out return out

View File

@ -118,25 +118,29 @@ func (r *KnowledgeBaseRepository) Delete(id uint) (err error) {
return r.DB.DB.Delete(&entity.KnowledgeBase{}, id).Error return r.DB.DB.Delete(&entity.KnowledgeBase{}, id).Error
} }
func (r *KnowledgeBaseRepository) FindByFilename(filename string) (data *entity.KnowledgeBase, fileType string, err error) { func (r *KnowledgeBaseRepository) FindByFilename(filename string) (*entity.KnowledgeBase, string, error) {
query := r.DB.DB.Model(&entity.KnowledgeBase{}).Where("is_active = ?", true)
// cari berdasarkan url yang mengandung filename var kb entity.KnowledgeBase
like := "%" + filename like := "%" + filename
// journal if err := r.DB.DB.
var kb entity.KnowledgeBase Where("is_active = ?", true).
if err := query.Where("file_journal_url LIKE ?", like).First(&kb).Error; err == nil { Where("file_journal_url LIKE ?", like).
First(&kb).Error; err == nil {
return &kb, "journal", nil return &kb, "journal", nil
} }
// audio if err := r.DB.DB.
if err := query.Where("file_audio_url LIKE ?", like).First(&kb).Error; err == nil { Where("is_active = ?", true).
Where("file_audio_url LIKE ?", like).
First(&kb).Error; err == nil {
return &kb, "audio", nil return &kb, "audio", nil
} }
// video if err := r.DB.DB.
if err := query.Where("file_video_url LIKE ?", like).First(&kb).Error; err == nil { Where("is_active = ?", true).
Where("file_video_url LIKE ?", like).
First(&kb).Error; err == nil {
return &kb, "video", nil return &kb, "video", nil
} }

View File

@ -88,9 +88,11 @@ func (s *KnowledgeBaseService) uploadFileToMinio(
newFilename := fmt.Sprintf("%s_%d%s", filenameWithoutExt, now.UnixNano(), ext) newFilename := fmt.Sprintf("%s_%d%s", filenameWithoutExt, now.UnixNano(), ext)
objectName := fmt.Sprintf( objectName := fmt.Sprintf(
"knowledge-base/%s/%s/%s", "knowledge-base/%s/%s/%d/%d/%s",
agentId, agentId,
folder, folder,
now.Year(),
now.Month(),
newFilename, newFilename,
) )
@ -100,13 +102,16 @@ func (s *KnowledgeBaseService) uploadFileToMinio(
objectName, objectName,
src, src,
fileHeader.Size, fileHeader.Size,
minio.PutObjectOptions{}, minio.PutObjectOptions{
ContentType: mime.TypeByExtension(ext),
},
) )
if err != nil { if err != nil {
return nil, err 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) { 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] 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") filename := c.Params("filename")
result, folder, err := s.Repo.FindByFilename(filename) result, folder, err := s.Repo.FindByFilename(filename)
if err != nil { 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() ctx := context.Background()
bucketName := s.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName 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() minioClient, err := s.MinioStorage.ConnectMinio()
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return fiber.ErrInternalServerError
"error": true,
"msg": err.Error(),
})
} }
fileContent, err := minioClient.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{}) fileContent, err := minioClient.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{})
if err != nil { if err != nil {
return err return fiber.NewError(fiber.StatusNotFound, "file not found in storage")
} }
defer fileContent.Close() defer fileContent.Close()
@ -171,13 +179,11 @@ func (s *KnowledgeBaseService) Viewer(c *fiber.Ctx) (err error) {
if contentType == "" { if contentType == "" {
contentType = "application/octet-stream" contentType = "application/octet-stream"
} }
c.Set("Content-Type", contentType) c.Set("Content-Type", contentType)
if _, err := io.Copy(c.Response().BodyWriter(), fileContent); err != nil { _, err = io.Copy(c.Response().BodyWriter(), fileContent)
return err return err
}
return nil
} }
func (s *KnowledgeBaseService) Show(id uint) (data *response.KnowledgeBaseResponse, err error) { 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() entity := req.ToEntity()
viewerBase := s.Cfg.App.Domain + "/knowledge-base/viewer/"
if journalFilename != nil { if journalFilename != nil {
journalUrl := viewerBase + *journalFilename entity.FileJournalUrl = journalFilename
entity.FileJournalUrl = &journalUrl
} }
if audioFilename != nil { if audioFilename != nil {
audioUrl := viewerBase + *audioFilename entity.FileAudioUrl = audioFilename
entity.FileAudioUrl = &audioUrl
} }
if videoFilename != nil { if videoFilename != nil {
videoUrl := viewerBase + *videoFilename entity.FileVideoUrl = videoFilename
entity.FileVideoUrl = &videoUrl
} }
if req.Status < 0 { if req.Status < 0 {