FRE-683: Add contacts & attachments management
- Implemented contact CRUD operations (list, add, edit, delete) - Implemented attachment management (list, upload, download) - Created internal/contact/manager.go for contact persistence - Created internal/attachment/manager.go for attachment storage - Added CLI commands in cmd/contacts.go and cmd/attachments.go - Integrated contact and attachment commands into root CLI Files: - internal/contact/types.go - Contact data models - internal/contact/manager.go - Contact CRUD operations - internal/attachment/manager.go - Attachment file operations - cmd/contacts.go - Contact CLI commands - cmd/attachments.go - Attachment CLI commands Contacts stored in ~/.config/pop/contacts.json Attachments stored in ~/.config/pop/attachments/
This commit is contained in:
124
cmd/attachments.go
Normal file
124
cmd/attachments.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/frenocorp/pop/internal/attachment"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func attachmentCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "attachment",
|
||||
Short: "Manage attachments",
|
||||
Long: `List, download, and upload attachments.`,
|
||||
}
|
||||
|
||||
cmd.AddCommand(attachmentListCmd())
|
||||
cmd.AddCommand(attachmentDownloadCmd())
|
||||
cmd.AddCommand(attachmentUploadCmd())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func attachmentListCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all attachments",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
manager := attachment.NewAttachmentManager()
|
||||
|
||||
ids, err := manager.List()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list attachments: %w", err)
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
fmt.Println("No attachments found")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("Attachments:")
|
||||
for _, id := range ids {
|
||||
fmt.Printf(" - %s\n", id)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func attachmentDownloadCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "download <attachment-id> [output-dir]",
|
||||
Short: "Download an attachment",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("attachment ID is required")
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
outputDir := "."
|
||||
if len(args) > 1 {
|
||||
outputDir = args[1]
|
||||
}
|
||||
|
||||
manager := attachment.NewAttachmentManager()
|
||||
|
||||
data, err := manager.Get(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get attachment: %w", err)
|
||||
}
|
||||
|
||||
if err := manager.Download(id, id, outputDir); err != nil {
|
||||
return fmt.Errorf("failed to download attachment: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Downloaded attachment %s to %s\n", id, outputDir)
|
||||
fmt.Printf("Size: %d bytes\n", len(data))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func attachmentUploadCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "upload <attachment-id> <file-path>",
|
||||
Short: "Upload an attachment",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("attachment ID and file path are required")
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
filePath := args[1]
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
manager := attachment.NewAttachmentManager()
|
||||
|
||||
if err := manager.Upload(id, file.Name(), file); err != nil {
|
||||
return fmt.Errorf("failed to upload attachment: %w", err)
|
||||
}
|
||||
|
||||
info, _ := file.Stat()
|
||||
fmt.Printf("Uploaded attachment %s (%s, %d bytes)\n", id, file.Name(), info.Size())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func readAll(r io.Reader) ([]byte, error) {
|
||||
return io.ReadAll(r)
|
||||
}
|
||||
Reference in New Issue
Block a user