intake/cmd/actionExecute.go

139 lines
4.0 KiB
Go
Raw Permalink Normal View History

2025-01-21 16:42:59 +00:00
package cmd
import (
2025-01-23 21:32:09 +00:00
"encoding/json"
"fmt"
2025-01-21 16:42:59 +00:00
"log"
2025-01-23 21:32:09 +00:00
"time"
2025-01-21 16:42:59 +00:00
2025-01-23 21:32:09 +00:00
"github.com/Jaculabilis/intake/core"
2025-01-21 16:42:59 +00:00
"github.com/spf13/cobra"
)
var actionExecuteCmd = &cobra.Command{
Use: "execute",
Aliases: []string{"exec"},
Short: "Run a source action for an item",
2025-01-23 21:32:09 +00:00
Long: fmt.Sprintf(`Execute a source action for an item.
The item must declare support for the action by having the action's name
in its "action" field. Use --force to execute the action anyway.
2025-01-23 21:32:09 +00:00
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()),
2025-01-21 16:42:59 +00:00
Run: func(cmd *cobra.Command, args []string) {
2025-01-23 21:32:09 +00:00
actionExecute()
2025-01-21 16:42:59 +00:00
},
}
2025-01-23 21:32:09 +00:00
var actionExecuteSource string
var actionExecuteAction string
var actionExecuteItem string
var actionExecuteFormat string
var actionExecuteDryRun bool
2025-01-23 21:50:45 +00:00
var actionExecuteDiff bool
var actionExecuteForce bool
2025-01-23 21:32:09 +00:00
2025-01-21 16:42:59 +00:00
func init() {
actionCmd.AddCommand(actionExecuteCmd)
2025-01-23 21:32:09 +00:00
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")
2025-01-23 21:32:09 +00:00
actionExecuteCmd.Flags().BoolVar(&actionExecuteDryRun, "dry-run", false, "Instead of updating the item, print it")
2025-01-23 21:50:45 +00:00
actionExecuteCmd.Flags().BoolVar(&actionExecuteDiff, "diff", false, "Show which fields of the item changed")
actionExecuteCmd.Flags().BoolVar(&actionExecuteForce, "force", false, "Execute the action even if the item does not support it")
2025-01-23 21:32:09 +00:00
}
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()
item, err := core.GetItem(db, actionExecuteSource, actionExecuteItem)
2025-01-23 21:32:09 +00:00
if err != nil {
log.Fatalf("error: failed to get item: %v", err)
2025-01-23 21:32:09 +00:00
}
if item.Action[actionExecuteAction] == nil {
if actionExecuteForce {
log.Printf("warning: force-executing %s on %s/%s", actionExecuteAction, actionExecuteSource, actionExecuteItem)
} else {
log.Fatalf("error: %s/%s does not support %s", actionExecuteSource, actionExecuteItem, actionExecuteAction)
}
}
argv, err := core.GetArgvForAction(db, actionExecuteSource, actionExecuteAction)
2025-01-23 21:32:09 +00:00
if err != nil {
log.Fatalf("error: failed to get action: %v", err)
2025-01-23 21:32:09 +00:00
}
itemJson, err := json.Marshal(item)
if err != nil {
log.Fatalf("error: failed to serialize item: %v", err)
}
2025-01-23 21:50:45 +00:00
res, err := core.Execute(actionExecuteSource, argv, nil, string(itemJson), time.Minute)
2025-01-23 21:32:09 +00:00
if err != nil {
log.Fatalf("error: failed to execute action: %v", err)
}
2025-01-23 21:50:45 +00:00
if len(res) != 1 {
log.Fatalf("error: expected action to produce exactly one item, got %d", len(res))
}
newItem := res[0]
2025-01-23 22:24:16 +00:00
core.BackfillItem(&newItem, &item)
2025-01-23 21:50:45 +00:00
if actionExecuteDiff {
if item.Title != newItem.Title {
log.Printf("title: %s => %s", item.Title, newItem.Title)
}
if item.Author != newItem.Author {
log.Printf("author: %s => %s", item.Author, newItem.Author)
}
if item.Body != newItem.Body {
log.Printf("body: %s => %s", item.Body, newItem.Body)
}
if item.Link != newItem.Link {
log.Printf("link: %s => %s", item.Link, newItem.Link)
}
if item.Time != newItem.Time {
log.Printf("time: %d => %d", item.Time, newItem.Time)
}
if core.ItemsAreEqual(item, newItem) {
2025-01-23 21:50:45 +00:00
log.Printf("no changes\n")
}
2025-01-23 21:32:09 +00:00
}
if actionExecuteDryRun {
2025-01-23 21:50:45 +00:00
fmt.Println(formatter(res[0]))
2025-01-23 21:32:09 +00:00
return
}
2025-01-23 22:24:16 +00:00
if err = core.UpdateItems(db, []core.Item{newItem}); err != nil {
log.Fatalf("error: failed to update item: %v", err)
}
2025-01-21 16:42:59 +00:00
}