101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
package inbox
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"gorm.io/gorm"
|
|
"senlinai-agent/backend/internal/domain"
|
|
)
|
|
|
|
type CaptureInput struct {
|
|
ProjectID uint
|
|
UserID uint
|
|
SourceType string
|
|
Title string
|
|
Body string
|
|
}
|
|
|
|
type Suggestion struct {
|
|
Kind string `json:"kind"`
|
|
Title string `json:"title"`
|
|
Body string `json:"body"`
|
|
}
|
|
|
|
type Analyzer interface {
|
|
Analyze(item domain.InboxItem, userID uint) ([]Suggestion, error)
|
|
}
|
|
|
|
type StaticAnalyzer struct {
|
|
Suggestions []Suggestion
|
|
}
|
|
|
|
func (a StaticAnalyzer) Analyze(item domain.InboxItem, userID uint) ([]Suggestion, error) {
|
|
return a.Suggestions, nil
|
|
}
|
|
|
|
type Service struct {
|
|
db *gorm.DB
|
|
analyzer Analyzer
|
|
}
|
|
|
|
func NewService(database *gorm.DB, analyzer Analyzer) *Service {
|
|
return &Service{db: database, analyzer: analyzer}
|
|
}
|
|
|
|
func (s *Service) Capture(input CaptureInput) (*domain.InboxItem, error) {
|
|
if input.ProjectID == 0 || input.UserID == 0 {
|
|
return nil, errors.New("project and user are required")
|
|
}
|
|
if input.SourceType == "" {
|
|
return nil, errors.New("source type is required")
|
|
}
|
|
item := &domain.InboxItem{
|
|
ProjectID: input.ProjectID,
|
|
CreatedBy: input.UserID,
|
|
SourceType: input.SourceType,
|
|
Title: input.Title,
|
|
Body: input.Body,
|
|
Status: "open",
|
|
}
|
|
return item, s.db.Create(item).Error
|
|
}
|
|
|
|
func (s *Service) Analyze(itemID uint, userID uint) ([]Suggestion, error) {
|
|
var item domain.InboxItem
|
|
if err := s.db.First(&item, itemID).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
if s.analyzer == nil {
|
|
return []Suggestion{}, nil
|
|
}
|
|
return s.analyzer.Analyze(item, userID)
|
|
}
|
|
|
|
func (s *Service) Confirm(itemID uint, selected []Suggestion) error {
|
|
return s.db.Transaction(func(tx *gorm.DB) error {
|
|
var item domain.InboxItem
|
|
if err := tx.First(&item, itemID).Error; err != nil {
|
|
return err
|
|
}
|
|
for _, suggestion := range selected {
|
|
switch suggestion.Kind {
|
|
case "task":
|
|
if err := tx.Create(&domain.Task{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, Title: suggestion.Title, Description: suggestion.Body}).Error; err != nil {
|
|
return err
|
|
}
|
|
case "note":
|
|
if err := tx.Create(&domain.Note{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, Title: suggestion.Title, Markdown: suggestion.Body}).Error; err != nil {
|
|
return err
|
|
}
|
|
case "source":
|
|
if err := tx.Create(&domain.Source{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, Kind: "link", Title: suggestion.Title, ContentText: suggestion.Body}).Error; err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return errors.New("unsupported suggestion kind")
|
|
}
|
|
}
|
|
return tx.Model(&item).Update("status", "processed").Error
|
|
})
|
|
}
|