mirror of
https://github.com/jimeh/mje.git
synced 2026-02-19 01:46:40 +00:00
refactor(commands): split commands package into multiple sub-packages
This commit is contained in:
@@ -1,27 +1,32 @@
|
||||
package commands
|
||||
package midjourney
|
||||
|
||||
import (
|
||||
"github.com/jimeh/go-midjourney"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewMidjourney(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
func New(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
cmd := &cobra.Command{
|
||||
Use: "midjourney",
|
||||
Aliases: []string{"mj"},
|
||||
Short: "Query the Midjourney API directly",
|
||||
}
|
||||
|
||||
recentJobsCmd, err := NewMidjourneyRecentJobs(mc)
|
||||
collectionsCmd, err := NewCollections(mc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wordsCmd, err := NewMidjourneyWords(mc)
|
||||
recentJobsCmd, err := NewRecentJobs(mc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wordsCmd, err := NewWords(mc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
collectionsCmd,
|
||||
recentJobsCmd,
|
||||
wordsCmd,
|
||||
)
|
||||
116
commands/midjourney/recent_jobs.go
Normal file
116
commands/midjourney/recent_jobs.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package midjourney
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jimeh/go-midjourney"
|
||||
"github.com/jimeh/mje/commands/render"
|
||||
"github.com/jimeh/mje/commands/shared"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type Job struct {
|
||||
ID string `json:"id,omitempty" yaml:"id,omitempty"`
|
||||
Status string `json:"current_status,omitempty" yaml:"current_status,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
EnqueueTime time.Time `json:"enqueue_time,omitempty" yaml:"enqueue_time,omitempty"`
|
||||
Prompt string `json:"prompt,omitempty" yaml:"prompt,omitempty"`
|
||||
ImagePaths []string `json:"image_paths,omitempty" yaml:"image_paths,omitempty"`
|
||||
ThumbnailURLs *ThumbnailURLs `json:"thumbnail_urls,omitempty" yaml:"thumbnail_url,omitempty"`
|
||||
IsPublished bool `json:"is_published,omitempty" yaml:"is_published,omitempty"`
|
||||
UserID string `json:"user_id,omitempty" yaml:"user_id,omitempty"`
|
||||
Username string `json:"username,omitempty" yaml:"username,omitempty"`
|
||||
FullCommand string `json:"full_command,omitempty" yaml:"full_command,omitempty"`
|
||||
ReferenceJobID string `json:"reference_job_id,omitempty" yaml:"reference_job_id,omitempty"`
|
||||
}
|
||||
|
||||
type ThumbnailURLs struct {
|
||||
Small string `json:"small,omitempty" yaml:"small,omitempty"`
|
||||
Medium string `json:"medium,omitempty" yaml:"medium,omitempty"`
|
||||
Large string `json:"large,omitempty" yaml:"large,omitempty"`
|
||||
}
|
||||
|
||||
func NewRecentJobs(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
cmd := &cobra.Command{
|
||||
Use: "recent-jobs",
|
||||
Aliases: []string{"jobs", "recent", "rj", "j", "r"},
|
||||
Short: "List recent jobs",
|
||||
RunE: recentJobsRunE(mc),
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
||||
cmd.Flags().IntP("amount", "a", 50, "amount of jobs to list")
|
||||
cmd.Flags().StringP("type", "t", "", "type of jobs to list")
|
||||
cmd.Flags().StringP("order", "o", "new", "either \"new\" or \"oldest\"")
|
||||
cmd.Flags().StringP("user-id", "u", "", "user ID to list jobs for")
|
||||
cmd.Flags().StringP(
|
||||
"collection-id", "c", "", "collection ID to list jobs for",
|
||||
)
|
||||
cmd.Flags().IntP("page", "p", 0, "page to fetch")
|
||||
cmd.Flags().StringP("prompt", "s", "", "prompt text to search for")
|
||||
cmd.Flags().Bool("dedupe", true, "dedupe results")
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func recentJobsRunE(mc *midjourney.Client) shared.RunEFunc {
|
||||
return func(cmd *cobra.Command, _ []string) error {
|
||||
fs := cmd.Flags()
|
||||
q := &midjourney.RecentJobsQuery{}
|
||||
|
||||
if v, err := fs.GetInt("amount"); err == nil && v > 0 {
|
||||
q.Amount = v
|
||||
}
|
||||
if v, err := fs.GetString("type"); err == nil && v != "" {
|
||||
q.JobType = midjourney.JobType(v)
|
||||
}
|
||||
if v, err := fs.GetString("order"); err == nil && v != "" {
|
||||
q.OrderBy = midjourney.Order(v)
|
||||
}
|
||||
if v, err := fs.GetString("user-id"); err == nil && v != "" {
|
||||
q.UserID = v
|
||||
}
|
||||
if v, err := fs.GetString("collection-id"); err == nil && v != "" {
|
||||
q.CollectionID = v
|
||||
}
|
||||
if v, err := fs.GetInt("page"); err == nil && v != 0 {
|
||||
q.Page = v
|
||||
}
|
||||
if v, err := fs.GetString("prompt"); err == nil && v != "" {
|
||||
q.Prompt = v
|
||||
}
|
||||
if v, err := fs.GetBool("dedupe"); err == nil {
|
||||
q.Dedupe = v
|
||||
}
|
||||
|
||||
rj, err := mc.RecentJobs(cmd.Context(), q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := []*Job{}
|
||||
for _, j := range rj.Jobs {
|
||||
r = append(r, &Job{
|
||||
ID: j.ID,
|
||||
Status: string(j.CurrentStatus),
|
||||
Type: string(j.Type),
|
||||
EnqueueTime: j.EnqueueTime.Time,
|
||||
Prompt: j.Prompt,
|
||||
ImagePaths: j.ImagePaths,
|
||||
ThumbnailURLs: &ThumbnailURLs{
|
||||
Small: j.ThumbnailURL(midjourney.ThumbnailSizeSmall),
|
||||
Medium: j.ThumbnailURL(midjourney.ThumbnailSizeMedium),
|
||||
Large: j.ThumbnailURL(midjourney.ThumbnailSizeLarge),
|
||||
},
|
||||
IsPublished: j.IsPublished,
|
||||
UserID: j.UserID,
|
||||
Username: j.Username,
|
||||
FullCommand: j.FullCommand,
|
||||
ReferenceJobID: j.ReferenceJobID,
|
||||
})
|
||||
}
|
||||
format := shared.FlagString(cmd, "format")
|
||||
|
||||
return render.Render(cmd.OutOrStdout(), format, r)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,25 @@
|
||||
package commands
|
||||
package midjourney
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/jimeh/go-midjourney"
|
||||
"github.com/jimeh/mje/commands/render"
|
||||
"github.com/jimeh/mje/commands/shared"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewMidjourneyWords(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
type Word struct {
|
||||
Word string `json:"word"`
|
||||
ImageURL string `json:"image_url"`
|
||||
}
|
||||
|
||||
func NewWords(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
cmd := &cobra.Command{
|
||||
Use: "words",
|
||||
Aliases: []string{"w"},
|
||||
Short: "Get dictionary words",
|
||||
RunE: midjourneyWordsRunE(mc),
|
||||
RunE: wordsRunE(mc),
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
||||
@@ -24,7 +31,7 @@ func NewMidjourneyWords(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func midjourneyWordsRunE(mc *midjourney.Client) runEFunc {
|
||||
func wordsRunE(mc *midjourney.Client) shared.RunEFunc {
|
||||
return func(cmd *cobra.Command, _ []string) error {
|
||||
fs := cmd.Flags()
|
||||
q := &midjourney.WordsQuery{}
|
||||
@@ -47,24 +54,19 @@ func midjourneyWordsRunE(mc *midjourney.Client) runEFunc {
|
||||
return err
|
||||
}
|
||||
|
||||
r := []*MidjourneyWord{}
|
||||
r := []*Word{}
|
||||
for _, w := range words {
|
||||
r = append(r, &MidjourneyWord{
|
||||
r = append(r, &Word{
|
||||
Word: w.Word,
|
||||
ImageURL: w.ImageURL(),
|
||||
})
|
||||
}
|
||||
|
||||
format := flagString(cmd, "format")
|
||||
format := shared.FlagString(cmd, "format")
|
||||
sort.SliceStable(r, func(i, j int) bool {
|
||||
return r[i].Word < r[j].Word
|
||||
})
|
||||
|
||||
return render(cmd.OutOrStdout(), format, r)
|
||||
return render.Render(cmd.OutOrStdout(), format, r)
|
||||
}
|
||||
}
|
||||
|
||||
type MidjourneyWord struct {
|
||||
Word string `json:"word"`
|
||||
ImageURL string `json:"image_url"`
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jimeh/go-midjourney"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewMidjourneyRecentJobs(mc *midjourney.Client) (*cobra.Command, error) {
|
||||
cmd := &cobra.Command{
|
||||
Use: "recent-jobs",
|
||||
Aliases: []string{"jobs", "recent", "rj", "j", "r"},
|
||||
Short: "List recent jobs",
|
||||
RunE: midjourneyRecentJobsRunE(mc),
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
||||
cmd.Flags().IntP("amount", "a", 50, "amount of jobs to list")
|
||||
cmd.Flags().StringP("type", "t", "", "type of jobs to list")
|
||||
cmd.Flags().StringP("order", "o", "new", "either \"new\" or \"oldest\"")
|
||||
cmd.Flags().StringP("user-id", "u", "", "user ID to list jobs for")
|
||||
cmd.Flags().IntP("page", "p", 0, "page to fetch")
|
||||
cmd.Flags().StringP("prompt", "s", "", "prompt text to search for")
|
||||
cmd.Flags().Bool("dedupe", true, "dedupe results")
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func midjourneyRecentJobsRunE(mc *midjourney.Client) runEFunc {
|
||||
return func(cmd *cobra.Command, _ []string) error {
|
||||
fs := cmd.Flags()
|
||||
q := &midjourney.RecentJobsQuery{}
|
||||
|
||||
if v, err := fs.GetInt("amount"); err == nil && v > 0 {
|
||||
q.Amount = v
|
||||
}
|
||||
if v, err := fs.GetString("type"); err == nil && v != "" {
|
||||
q.JobType = midjourney.JobType(v)
|
||||
}
|
||||
if v, err := fs.GetString("order"); err == nil && v != "" {
|
||||
q.OrderBy = midjourney.Order(v)
|
||||
}
|
||||
if v, err := fs.GetString("user-id"); err == nil && v != "" {
|
||||
q.UserID = v
|
||||
}
|
||||
if v, err := fs.GetInt("page"); err == nil && v != 0 {
|
||||
q.Page = v
|
||||
}
|
||||
if v, err := fs.GetString("prompt"); err == nil && v != "" {
|
||||
q.Prompt = v
|
||||
}
|
||||
if v, err := fs.GetBool("dedupe"); err == nil {
|
||||
q.Dedupe = v
|
||||
}
|
||||
|
||||
rj, err := mc.RecentJobs(cmd.Context(), q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := []*MidjourneyJob{}
|
||||
for _, j := range rj.Jobs {
|
||||
r = append(r, &MidjourneyJob{
|
||||
ID: j.ID,
|
||||
Status: string(j.CurrentStatus),
|
||||
Type: string(j.Type),
|
||||
EnqueueTime: j.EnqueueTime.Time,
|
||||
Prompt: j.Prompt,
|
||||
ImagePaths: j.ImagePaths,
|
||||
IsPublished: j.IsPublished,
|
||||
UserID: j.UserID,
|
||||
Username: j.Username,
|
||||
FullCommand: j.FullCommand,
|
||||
ReferenceJobID: j.ReferenceJobID,
|
||||
})
|
||||
}
|
||||
format := flagString(cmd, "format")
|
||||
|
||||
return render(cmd.OutOrStdout(), format, r)
|
||||
}
|
||||
}
|
||||
|
||||
type MidjourneyJob struct {
|
||||
ID string `json:"id,omitempty" yaml:"id,omitempty"`
|
||||
Status string `json:"current_status,omitempty" yaml:"current_status,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
EnqueueTime time.Time `json:"enqueue_time,omitempty" yaml:"enqueue_time,omitempty"`
|
||||
Prompt string `json:"prompt,omitempty" yaml:"prompt,omitempty"`
|
||||
ImagePaths []string `json:"image_paths,omitempty" yaml:"image_paths,omitempty"`
|
||||
IsPublished bool `json:"is_published,omitempty" yaml:"is_published,omitempty"`
|
||||
UserID string `json:"user_id,omitempty" yaml:"user_id,omitempty"`
|
||||
Username string `json:"username,omitempty" yaml:"username,omitempty"`
|
||||
FullCommand string `json:"full_command,omitempty" yaml:"full_command,omitempty"`
|
||||
ReferenceJobID string `json:"reference_job_id,omitempty" yaml:"reference_job_id,omitempty"`
|
||||
}
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/jimeh/go-midjourney"
|
||||
mjcmds "github.com/jimeh/mje/commands/midjourney"
|
||||
"github.com/jimeh/mje/commands/shared"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type runEFunc func(cmd *cobra.Command, _ []string) error
|
||||
|
||||
type Info struct {
|
||||
Version string
|
||||
Commit string
|
||||
@@ -52,7 +52,7 @@ func New(info Info) (*cobra.Command, error) {
|
||||
"MidJourney API URL",
|
||||
)
|
||||
|
||||
midjourneyCmd, err := NewMidjourney(mc)
|
||||
midjourneyCmd, err := mjcmds.New(mc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func New(info Info) (*cobra.Command, error) {
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func persistentPreRunE(mc *midjourney.Client) runEFunc {
|
||||
func persistentPreRunE(mc *midjourney.Client) shared.RunEFunc {
|
||||
return func(cmd *cobra.Command, _ []string) error {
|
||||
err := setupZerolog(cmd)
|
||||
if err != nil {
|
||||
@@ -89,7 +89,7 @@ func setupMidJourney(cmd *cobra.Command, mc *midjourney.Client) error {
|
||||
opts = append(opts, midjourney.WithAuthToken(v))
|
||||
}
|
||||
|
||||
apiURL := flagString(cmd, "api-url")
|
||||
apiURL := shared.FlagString(cmd, "api-url")
|
||||
if apiURL == "" {
|
||||
apiURL = os.Getenv("MIDJOURNEY_API_URL")
|
||||
}
|
||||
@@ -141,22 +141,12 @@ func setupZerolog(cmd *cobra.Command) error {
|
||||
case "plain":
|
||||
output := zerolog.ConsoleWriter{Out: out}
|
||||
output.FormatTimestamp = func(i interface{}) string { return "" }
|
||||
log.Logger = zerolog.New(output).With().Logger()
|
||||
log.Logger = zerolog.New(output).Level(level).With().Logger()
|
||||
case "json":
|
||||
log.Logger = zerolog.New(out).With().Timestamp().Logger()
|
||||
log.Logger = zerolog.New(out).Level(level)
|
||||
default:
|
||||
return fmt.Errorf("unknown log-format: %s", logFormat)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func flagString(cmd *cobra.Command, name string) string {
|
||||
var r string
|
||||
|
||||
if f := cmd.Flag(name); f != nil {
|
||||
r = f.Value.String()
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package commands
|
||||
package render
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func render(w io.Writer, format string, v interface{}) error {
|
||||
func Render(w io.Writer, format string, v any) error {
|
||||
if format == "yaml" || format == "yml" {
|
||||
return renderYAML(w, v)
|
||||
return YAML(w, v)
|
||||
}
|
||||
|
||||
if format == "json" {
|
||||
return renderJSON(w, v)
|
||||
return JSON(w, v)
|
||||
}
|
||||
|
||||
if wt, ok := v.(io.WriterTo); ok {
|
||||
@@ -34,17 +34,17 @@ func render(w io.Writer, format string, v interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return renderJSON(w, v)
|
||||
return JSON(w, v)
|
||||
}
|
||||
|
||||
func renderYAML(w io.Writer, v interface{}) error {
|
||||
func YAML(w io.Writer, v interface{}) error {
|
||||
enc := yaml.NewEncoder(w)
|
||||
enc.SetIndent(2)
|
||||
|
||||
return enc.Encode(v)
|
||||
}
|
||||
|
||||
func renderJSON(w io.Writer, v interface{}) error {
|
||||
func JSON(w io.Writer, v interface{}) error {
|
||||
enc := json.NewEncoder(w)
|
||||
enc.SetIndent("", " ")
|
||||
|
||||
13
commands/shared/flag_string.go
Normal file
13
commands/shared/flag_string.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package shared
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func FlagString(cmd *cobra.Command, name string) string {
|
||||
var r string
|
||||
|
||||
if f := cmd.Flag(name); f != nil {
|
||||
r = f.Value.String()
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
5
commands/shared/run.go
Normal file
5
commands/shared/run.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package shared
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
type RunEFunc func(cmd *cobra.Command, _ []string) error
|
||||
Reference in New Issue
Block a user