125 lines
3 KiB
Go
125 lines
3 KiB
Go
package readlist
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Service handles read later operations
|
|
type Service struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewService creates a new read later service
|
|
func NewService(db *gorm.DB) *Service {
|
|
return &Service{db: db}
|
|
}
|
|
|
|
// Create adds a new URL to read later
|
|
func (s *Service) Create(url string) (*ReadLaterItem, error) {
|
|
item := &ReadLaterItem{
|
|
ID: uuid.New().String(),
|
|
URL: url,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
// Parse URL and extract content
|
|
if err := item.ParseURL(); err != nil {
|
|
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
|
}
|
|
|
|
if err := s.db.Create(item).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to create read later item: %w", err)
|
|
}
|
|
|
|
return item, nil
|
|
}
|
|
|
|
// Get retrieves a read later item by ID
|
|
func (s *Service) Get(id string) (*ReadLaterItem, error) {
|
|
var item ReadLaterItem
|
|
if err := s.db.First(&item, "id = ?", id).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, nil
|
|
}
|
|
return nil, fmt.Errorf("failed to get read later item: %w", err)
|
|
}
|
|
return &item, nil
|
|
}
|
|
|
|
// List retrieves all read later items
|
|
func (s *Service) List(includeArchived bool) ([]ReadLaterItem, error) {
|
|
var items []ReadLaterItem
|
|
query := s.db.Order("created_at desc")
|
|
|
|
if !includeArchived {
|
|
query = query.Where("archived_at IS NULL")
|
|
}
|
|
|
|
if err := query.Find(&items).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to list read later items: %w", err)
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
// MarkRead marks an item as read
|
|
func (s *Service) MarkRead(id string) error {
|
|
now := time.Now()
|
|
if err := s.db.Model(&ReadLaterItem{}).
|
|
Where("id = ?", id).
|
|
Updates(map[string]interface{}{
|
|
"read_at": &now,
|
|
"updated_at": now,
|
|
}).Error; err != nil {
|
|
return fmt.Errorf("failed to mark item as read: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Archive marks an item as archived
|
|
func (s *Service) Archive(id string) error {
|
|
now := time.Now()
|
|
if err := s.db.Model(&ReadLaterItem{}).
|
|
Where("id = ?", id).
|
|
Updates(map[string]interface{}{
|
|
"archived_at": &now,
|
|
"updated_at": now,
|
|
}).Error; err != nil {
|
|
return fmt.Errorf("failed to archive item: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Unarchive removes the archived status from an item
|
|
func (s *Service) Unarchive(id string) error {
|
|
now := time.Now()
|
|
if err := s.db.Model(&ReadLaterItem{}).
|
|
Where("id = ?", id).
|
|
Updates(map[string]interface{}{
|
|
"archived_at": nil,
|
|
"updated_at": now,
|
|
}).Error; err != nil {
|
|
return fmt.Errorf("failed to unarchive item: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Delete removes a read later item
|
|
func (s *Service) Delete(id string) error {
|
|
if err := s.db.Delete(&ReadLaterItem{}, "id = ?", id).Error; err != nil {
|
|
return fmt.Errorf("failed to delete read later item: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Reset deletes all read later items (for testing)
|
|
func (s *Service) Reset() error {
|
|
if err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&ReadLaterItem{}).Error; err != nil {
|
|
return fmt.Errorf("failed to reset read later items: %w", err)
|
|
}
|
|
return nil
|
|
}
|