Implement action {add,delete,edit,list}
This commit is contained in:
parent
14df3cac03
commit
7b8d3796bd
@ -7,8 +7,19 @@ import (
|
|||||||
var actionCmd = &cobra.Command{
|
var actionCmd = &cobra.Command{
|
||||||
Use: "action",
|
Use: "action",
|
||||||
Short: "Manage and run source actions",
|
Short: "Manage and run source actions",
|
||||||
Long: `
|
Long: `Add, edit, delete, and run source actions on items.
|
||||||
`,
|
|
||||||
|
A feed source is updated by the "fetch" action, which receives no input and
|
||||||
|
returns one JSON item per line on stdout. Other source actions are run on a
|
||||||
|
specific item, receiving that item on stdin and expecting that item, with any
|
||||||
|
modifications made by the action, on stdout.
|
||||||
|
|
||||||
|
Items declare support for an action by having an "action" key containing an
|
||||||
|
object with a key for every supported action. The value of that key may be
|
||||||
|
any arbitrary JSON value. Use --force to execute an unsupported action anyway,
|
||||||
|
though the action may fail if it operated on the item's action data.
|
||||||
|
|
||||||
|
To execute the "fetch" action, use "intake source fetch".`,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -3,19 +3,50 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/Jaculabilis/intake/core"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var actionAddCmd = &cobra.Command{
|
var actionAddCmd = &cobra.Command{
|
||||||
Use: "add",
|
Use: "add [flags] -- argv...",
|
||||||
Short: "Add an action to a source",
|
Short: "Add an action to a source",
|
||||||
Long: `
|
Long: `Add an action to a source.
|
||||||
`,
|
`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
log.Fatal("not implemented")
|
actionAdd(getArgv(cmd, args))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var actionAddSource string
|
||||||
|
var actionAddAction string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
actionCmd.AddCommand(actionAddCmd)
|
actionCmd.AddCommand(actionAddCmd)
|
||||||
|
|
||||||
|
actionAddCmd.Flags().StringVarP(&actionAddSource, "source", "s", "", "Source to add action")
|
||||||
|
actionAddCmd.MarkFlagRequired("source")
|
||||||
|
|
||||||
|
actionAddCmd.Flags().StringVarP(&actionAddAction, "action", "a", "", "Action name")
|
||||||
|
actionAddCmd.MarkFlagRequired("action")
|
||||||
|
}
|
||||||
|
|
||||||
|
func actionAdd(argv []string) {
|
||||||
|
if actionAddSource == "" {
|
||||||
|
log.Fatal("error: --source is empty")
|
||||||
|
}
|
||||||
|
if actionAddAction == "" {
|
||||||
|
log.Fatal("error: --action is empty")
|
||||||
|
}
|
||||||
|
if len(argv) == 0 {
|
||||||
|
log.Fatal("error: no argv provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := openAndMigrateDb()
|
||||||
|
|
||||||
|
err := core.AddAction(db, actionAddSource, actionAddAction, argv)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Added action %s to source %s", actionAddAction, actionAddSource)
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,48 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/Jaculabilis/intake/core"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var actionDeleteCmd = &cobra.Command{
|
var actionDeleteCmd = &cobra.Command{
|
||||||
Use: "delete",
|
Use: "delete",
|
||||||
|
Aliases: []string{"rm"},
|
||||||
Short: "Delete an action from a source",
|
Short: "Delete an action from a source",
|
||||||
Long: `
|
Long: `Delete an action from a source.
|
||||||
`,
|
`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
log.Fatal("not implemented")
|
actionDelete()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var actionDeleteSource string
|
||||||
|
var actionDeleteAction string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
actionCmd.AddCommand(actionDeleteCmd)
|
actionCmd.AddCommand(actionDeleteCmd)
|
||||||
|
|
||||||
|
actionDeleteCmd.Flags().StringVarP(&actionDeleteSource, "source", "s", "", "Source to add action")
|
||||||
|
actionDeleteCmd.MarkFlagRequired("source")
|
||||||
|
|
||||||
|
actionDeleteCmd.Flags().StringVarP(&actionDeleteAction, "action", "a", "", "Action name")
|
||||||
|
actionDeleteCmd.MarkFlagRequired("action")
|
||||||
|
}
|
||||||
|
|
||||||
|
func actionDelete() {
|
||||||
|
if actionDeleteSource == "" {
|
||||||
|
log.Fatal("error: --source is empty")
|
||||||
|
}
|
||||||
|
if actionDeleteAction == "" {
|
||||||
|
log.Fatal("error: --action is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := openAndMigrateDb()
|
||||||
|
|
||||||
|
err := core.DeleteAction(db, actionDeleteSource, actionDeleteAction)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Deleted action %s from source %s", actionDeleteAction, actionDeleteSource)
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,50 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/Jaculabilis/intake/core"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var actionEditCmd = &cobra.Command{
|
var actionEditCmd = &cobra.Command{
|
||||||
Use: "edit",
|
Use: "edit",
|
||||||
Short: "Edit an action",
|
Short: "Edit an action on a source",
|
||||||
Long: `
|
Long: `Edit an action on a source.
|
||||||
`,
|
`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
log.Fatal("not implemented")
|
actionEdit(getArgv(cmd, args))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var actionEditSource string
|
||||||
|
var actionEditAction string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
actionCmd.AddCommand(actionEditCmd)
|
actionCmd.AddCommand(actionEditCmd)
|
||||||
|
|
||||||
|
actionEditCmd.Flags().StringVarP(&actionEditSource, "source", "s", "", "Source to edit action")
|
||||||
|
actionEditCmd.MarkFlagRequired("source")
|
||||||
|
|
||||||
|
actionEditCmd.Flags().StringVarP(&actionEditAction, "action", "a", "", "Action name")
|
||||||
|
actionEditCmd.MarkFlagRequired("action")
|
||||||
|
}
|
||||||
|
|
||||||
|
func actionEdit(argv []string) {
|
||||||
|
if actionEditSource == "" {
|
||||||
|
log.Fatal("error: --source is empty")
|
||||||
|
}
|
||||||
|
if actionEditAction == "" {
|
||||||
|
log.Fatal("error: --action is empty")
|
||||||
|
}
|
||||||
|
if len(argv) == 0 {
|
||||||
|
log.Fatal("error: no argv provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := openAndMigrateDb()
|
||||||
|
|
||||||
|
err := core.UpdateAction(db, actionEditSource, actionEditAction, argv)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Updated action %s on source %s", actionEditAction, actionEditSource)
|
||||||
}
|
}
|
||||||
|
66
cmd/actionList.go
Normal file
66
cmd/actionList.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/Jaculabilis/intake/core"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var actionListCmd = &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Short: "List actions on a source",
|
||||||
|
Long: `List actions on a source.
|
||||||
|
`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
actionList()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var actionListSource string
|
||||||
|
var actionListArgv bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
actionCmd.AddCommand(actionListCmd)
|
||||||
|
|
||||||
|
actionListCmd.Flags().StringVarP(&actionListSource, "source", "s", "", "Source to list actions")
|
||||||
|
actionListCmd.MarkFlagRequired("source")
|
||||||
|
|
||||||
|
actionListCmd.Flags().BoolVarP(&actionListArgv, "argv", "a", false, "Include action command")
|
||||||
|
}
|
||||||
|
|
||||||
|
func actionList() {
|
||||||
|
if actionListSource == "" {
|
||||||
|
log.Fatal("error: --source is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := openAndMigrateDb()
|
||||||
|
|
||||||
|
actions, err := core.GetActionsForSource(db, actionListSource)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
slices.SortFunc(actions, actionSort)
|
||||||
|
|
||||||
|
if actionListArgv {
|
||||||
|
actionArgv := make(map[string][]string)
|
||||||
|
for _, name := range actions {
|
||||||
|
argv, err := core.GetArgvForAction(db, actionListSource, name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: could not get argv for source %s action %s: %v", actionListSource, name, err)
|
||||||
|
}
|
||||||
|
actionArgv[name] = argv
|
||||||
|
}
|
||||||
|
for _, name := range actions {
|
||||||
|
fmt.Printf("%s %v\n", name, actionArgv[name])
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for _, action := range actions {
|
||||||
|
fmt.Println(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
cmd/root.go
21
cmd/root.go
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Jaculabilis/intake/core"
|
"github.com/Jaculabilis/intake/core"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -65,3 +66,23 @@ func openAndMigrateDb() *core.DB {
|
|||||||
}
|
}
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getArgv(cmd *cobra.Command, args []string) []string {
|
||||||
|
lenAtDash := cmd.Flags().ArgsLenAtDash()
|
||||||
|
if lenAtDash == -1 {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return args[lenAtDash:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort "fetch" action ahead of other actions
|
||||||
|
func actionSort(a string, b string) int {
|
||||||
|
if a == "fetch" {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b == "fetch" {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return strings.Compare(a, b)
|
||||||
|
}
|
||||||
|
@ -20,8 +20,12 @@ var sourceListCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sourceListShowActions bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
sourceCmd.AddCommand(sourceListCmd)
|
sourceCmd.AddCommand(sourceListCmd)
|
||||||
|
|
||||||
|
sourceListCmd.Flags().BoolVarP(&sourceListShowActions, "actions", "a", false, "Include source actions")
|
||||||
}
|
}
|
||||||
|
|
||||||
func sourceList() {
|
func sourceList() {
|
||||||
@ -31,10 +35,24 @@ func sourceList() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error: %v", err)
|
log.Fatalf("error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slices.Sort(names)
|
slices.Sort(names)
|
||||||
|
|
||||||
|
if sourceListShowActions {
|
||||||
|
sourceActions := make(map[string][]string)
|
||||||
|
for _, name := range names {
|
||||||
|
actions, err := core.GetActionsForSource(db, name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: could not get actions for source %s: %v", name, err)
|
||||||
|
}
|
||||||
|
slices.SortFunc(actions, actionSort)
|
||||||
|
sourceActions[name] = actions
|
||||||
|
}
|
||||||
|
for _, name := range names {
|
||||||
|
fmt.Printf("%s %v\n", name, sourceActions[name])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
fmt.Println(name)
|
fmt.Println(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -81,7 +81,7 @@ func DeleteAction(db *DB, source string, name string) error {
|
|||||||
_, err := db.Exec(`
|
_, err := db.Exec(`
|
||||||
delete from actions
|
delete from actions
|
||||||
where source = ? and name = ?
|
where source = ? and name = ?
|
||||||
`)
|
`, source, name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,11 @@ func TestActionCreate(t *testing.T) {
|
|||||||
if len(argv) != 2 || argv[0] != "echo" || argv[1] != "goodbye" {
|
if len(argv) != 2 || argv[0] != "echo" || argv[1] != "goodbye" {
|
||||||
t.Fatalf("expected [echo goodbye], got: %v", argv)
|
t.Fatalf("expected [echo goodbye], got: %v", argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = DeleteAction(db, "test", "hello")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExecute(t *testing.T) {
|
func TestExecute(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user