diff --git a/cmd/actionExecute.go b/cmd/actionExecute.go index 2ea29a2..3f56ca6 100644 --- a/cmd/actionExecute.go +++ b/cmd/actionExecute.go @@ -1,8 +1,12 @@ package cmd import ( + "encoding/json" + "fmt" "log" + "time" + "github.com/Jaculabilis/intake/core" "github.com/spf13/cobra" ) @@ -10,13 +14,83 @@ var actionExecuteCmd = &cobra.Command{ Use: "execute", Aliases: []string{"exec"}, Short: "Run a source action for an item", - Long: ` -`, + Long: fmt.Sprintf(`Execute a source action for an item. + +The "fetch" action is special and does not execute for any specific item. +Use "intake source fetch" to run the fetch action. + +In a dry run, the item will be printed in the chosen format and not updated. + +%s`, makeFormatHelpText()), Run: func(cmd *cobra.Command, args []string) { - log.Fatal("not implemented") + actionExecute() }, } +var actionExecuteSource string +var actionExecuteAction string +var actionExecuteItem string +var actionExecuteFormat string +var actionExecuteDryRun bool + func init() { actionCmd.AddCommand(actionExecuteCmd) + + actionExecuteCmd.PersistentFlags().StringVarP(&actionExecuteSource, "source", "s", "", "Source of the item") + actionExecuteCmd.MarkFlagRequired("source") + + actionExecuteCmd.PersistentFlags().StringVarP(&actionExecuteItem, "item", "i", "", "Item to run action on") + actionExecuteCmd.MarkFlagRequired("item") + + actionExecuteCmd.PersistentFlags().StringVarP(&actionExecuteAction, "action", "a", "", "Action to run") + actionExecuteCmd.MarkFlagRequired("action") + + actionExecuteCmd.Flags().StringVarP(&actionExecuteFormat, "format", "f", "headlines", "Feed format for returned items.") + actionExecuteCmd.Flags().BoolVar(&actionExecuteDryRun, "dry-run", false, "Instead of updating the item, print it") +} + +func actionExecute() { + formatter := formatAs(actionExecuteFormat) + + if actionExecuteSource == "" { + log.Fatal("error: --source is empty") + } + if actionExecuteAction == "" { + log.Fatal("error: --action is empty") + } + if actionExecuteItem == "" { + log.Fatal("error: --item is empty") + } + + db := openAndMigrateDb() + + argv, err := core.GetArgvForAction(db, actionExecuteSource, actionExecuteAction) + if err != nil { + log.Fatalf("error: failed to get action: %v", err) + } + + item, err := core.GetItem(db, actionExecuteSource, actionExecuteItem) + if err != nil { + log.Fatalf("error: failed to get item: %v", err) + } + + itemJson, err := json.Marshal(item) + if err != nil { + log.Fatalf("error: failed to serialize item: %v", err) + } + + newItem, err := core.Execute(actionExecuteSource, argv, nil, string(itemJson), time.Minute) + if err != nil { + log.Fatalf("error: failed to execute action: %v", err) + } + if len(newItem) != 1 { + log.Fatalf("error: expected action to produce exactly one item, got %d", len(newItem)) + } + + if actionExecuteDryRun { + fmt.Println(formatter(newItem[0])) + return + } + + // TODO } diff --git a/core/source.go b/core/source.go index d29340b..f220220 100644 --- a/core/source.go +++ b/core/source.go @@ -135,6 +135,22 @@ func getItems(db *DB, query string, args ...any) ([]Item, error) { return items, nil } +func GetItem(db *DB, source string, id string) (Item, error) { + items, err := getItems(db, ` + select source, id, created, active, title, author, body, link, time + from items + where source = ? + and id = ? + `, source, id) + if err != nil { + return Item{}, err + } + if len(items) == 0 { + return Item{}, fmt.Errorf("no item in %s with id %s", source, id) + } + return items[0], nil +} + func GetAllActiveItems(db *DB) ([]Item, error) { return getItems(db, ` select