github.com/soulteary/pocket-bookcase@v0.0.0-20240428065142-0b5a9a0fc98a/internal/cmd/add.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/soulteary/pocket-bookcase/internal/core"
     9  	"github.com/soulteary/pocket-bookcase/internal/model"
    10  	"github.com/spf13/cobra"
    11  )
    12  
    13  func addCmd() *cobra.Command {
    14  	cmd := &cobra.Command{
    15  		Use:   "add url",
    16  		Short: "Bookmark the specified URL",
    17  		Args:  cobra.ExactArgs(1),
    18  		Run:   addHandler,
    19  	}
    20  
    21  	cmd.Flags().StringP("title", "i", "", "Custom title for this bookmark")
    22  	cmd.Flags().StringP("excerpt", "e", "", "Custom excerpt for this bookmark")
    23  	cmd.Flags().StringSliceP("tags", "t", []string{}, "Comma-separated tags for this bookmark")
    24  	cmd.Flags().BoolP("offline", "o", false, "Save bookmark without fetching data from internet")
    25  	cmd.Flags().BoolP("no-archival", "a", false, "Save bookmark without creating offline archive")
    26  	cmd.Flags().Bool("log-archival", false, "Log the archival process")
    27  
    28  	return cmd
    29  }
    30  
    31  func addHandler(cmd *cobra.Command, args []string) {
    32  	cfg, deps := initShiori(cmd.Context(), cmd)
    33  
    34  	// Read flag and arguments
    35  	url := args[0]
    36  	title, _ := cmd.Flags().GetString("title")
    37  	excerpt, _ := cmd.Flags().GetString("excerpt")
    38  	tags, _ := cmd.Flags().GetStringSlice("tags")
    39  	offline, _ := cmd.Flags().GetBool("offline")
    40  	noArchival, _ := cmd.Flags().GetBool("no-archival")
    41  	logArchival, _ := cmd.Flags().GetBool("log-archival")
    42  
    43  	// Normalize input
    44  	title = validateTitle(title, "")
    45  	excerpt = normalizeSpace(excerpt)
    46  
    47  	// Create bookmark item
    48  	book := model.BookmarkDTO{
    49  		URL:           url,
    50  		Title:         title,
    51  		Excerpt:       excerpt,
    52  		CreateArchive: !noArchival,
    53  	}
    54  
    55  	// Set bookmark tags
    56  	book.Tags = make([]model.Tag, len(tags))
    57  	for i, tag := range tags {
    58  		book.Tags[i].Name = strings.TrimSpace(tag)
    59  	}
    60  
    61  	// Clean up bookmark URL
    62  	var err error
    63  	book.URL, err = core.RemoveUTMParams(book.URL)
    64  	if err != nil {
    65  		cError.Printf("Failed to clean URL: %v\n", err)
    66  		os.Exit(1)
    67  	}
    68  
    69  	// Make sure bookmark's title not empty
    70  	if book.Title == "" {
    71  		book.Title = book.URL
    72  	}
    73  
    74  	// Save bookmark to database
    75  	books, err := deps.Database.SaveBookmarks(cmd.Context(), true, book)
    76  	if err != nil {
    77  		cError.Printf("Failed to save bookmark: %v\n", err)
    78  		os.Exit(1)
    79  	}
    80  
    81  	book = books[0]
    82  
    83  	// If it's not offline mode, fetch data from internet.
    84  	if !offline {
    85  		cInfo.Println("Downloading article...")
    86  
    87  		var isFatalErr bool
    88  		content, contentType, err := core.DownloadBookmark(book.URL)
    89  		if err != nil {
    90  			cError.Printf("Failed to download: %v\n", err)
    91  		}
    92  
    93  		if err == nil && content != nil {
    94  			request := core.ProcessRequest{
    95  				DataDir:     cfg.Storage.DataDir,
    96  				Bookmark:    book,
    97  				Content:     content,
    98  				ContentType: contentType,
    99  				LogArchival: logArchival,
   100  				KeepTitle:   title != "",
   101  				KeepExcerpt: excerpt != "",
   102  			}
   103  
   104  			book, isFatalErr, err = core.ProcessBookmark(deps, request)
   105  			content.Close()
   106  
   107  			if err != nil {
   108  				cError.Printf("Failed: %v\n", err)
   109  			}
   110  
   111  			if isFatalErr {
   112  				os.Exit(1)
   113  			}
   114  		}
   115  
   116  		// Save bookmark to database
   117  		_, err = deps.Database.SaveBookmarks(cmd.Context(), false, book)
   118  		if err != nil {
   119  			cError.Printf("Failed to save bookmark with content: %v\n", err)
   120  			os.Exit(1)
   121  		}
   122  	}
   123  
   124  	// Print added bookmark
   125  	fmt.Println()
   126  	printBookmarks(book)
   127  }