Thorben Günther"go fix" string changes64d083b7 months agoHistory
475 lines · 11.9 KB · Go
RawDownload
package main import (	"context"	"fmt"	"io"	"log"	"mime"	"net/http"	"os"	"path/filepath"	"slices"	"strings" 	"git.sr.ht/~emersion/gqlclient"	"github.com/dustin/go-humanize"	"github.com/spf13/cobra" 	"git.sr.ht/~xenrox/hut/srht/pastesrht"	"git.sr.ht/~xenrox/hut/termfmt") func newPasteCommand() *cobra.Command {	cmd := &cobra.Command{		Use:   "paste",		Short: "Use the paste API",	}	cmd.AddCommand(newPasteCreateCommand())	cmd.AddCommand(newPasteDeleteCommand())	cmd.AddCommand(newPasteListCommand())	cmd.AddCommand(newPasteShowCommand())	cmd.AddCommand(newPasteUpdateCommand())	cmd.AddCommand(newPasteUserWebhookCommand())	return cmd} func newPasteCreateCommand() *cobra.Command {	var visibility string	var name string	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context() 		pasteVisibility, err := pastesrht.ParseVisibility(visibility)		if err != nil {			log.Fatal(err)		} 		c := createClient("paste", cmd) 		if name != "" && len(args) > 0 {			log.Fatalln("--name is only supported when reading from stdin")		} 		var files []gqlclient.Upload		for _, filename := range args {			f, err := os.Open(filename)			if err != nil {				log.Fatalf("failed to open input file: %v", err)			}			defer f.Close() 			t := mime.TypeByExtension(filepath.Ext(filename))			if t == "" {				t = "text/plain"			} 			files = append(files, gqlclient.Upload{				Filename: filepath.Base(filename),				MIMEType: t,				Body:     f,			})		} 		if len(args) == 0 {			files = append(files, gqlclient.Upload{				Filename: name,				MIMEType: "text/plain",				Body:     os.Stdin,			})		} 		paste, err := pastesrht.CreatePaste(c.Client, ctx, files, pasteVisibility)		if err != nil {			log.Fatal(err)		} 		if termfmt.IsTerminal() {			log.Printf("Created paste %v/%v/%v", c.BaseURL, paste.User.CanonicalName, paste.Id)		} else {			fmt.Printf("%v/%v/%v\n", c.BaseURL, paste.User.CanonicalName, paste.Id)		}	} 	cmd := &cobra.Command{		Use:   "create [filenames...]",		Short: "Create a new paste",		Run:   run,	}	cmd.Flags().StringVarP(&visibility, "visibility", "v", "unlisted", "paste visibility")	cmd.RegisterFlagCompletionFunc("visibility", completeVisibility)	cmd.Flags().StringVarP(&name, "name", "n", "", "paste name (when reading from stdin)")	return cmd} func newPasteDeleteCommand() *cobra.Command {	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context() 		for _, arg := range args {			id, _, instance := parseResourceName(arg)			c := createClientWithInstance("paste", cmd, instance) 			paste, err := pastesrht.Delete(c.Client, ctx, id)			if err != nil {				log.Fatalf("failed to delete paste %s: %v", id, err)			} 			if paste == nil {				log.Printf("Paste %s does not exist\n", id)			} else {				log.Printf("Deleted paste %s\n", paste.Id)			}		}	} 	cmd := &cobra.Command{		Use:               "delete <ID...>",		Short:             "Delete pastes",		Args:              cobra.MinimumNArgs(1),		ValidArgsFunction: completePasteID,		Run:               run,	}	return cmd} func newPasteListCommand() *cobra.Command {	var count, printed int	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context()		c := createClient("paste", cmd)		var cursor *pastesrht.Cursor 		err := pagerify(func(p pager) error {			pastes, err := pastesrht.Pastes(c.Client, ctx, cursor)			if err != nil {				return err			} 			for _, paste := range pastes.Results {				if count != 0 && printed == count {					return pagerDone				}				printPaste(p, &paste)				fmt.Fprintln(p)				printed += 1			} 			cursor = pastes.Cursor			if p.IsDone(cursor, len(pastes.Results)) {				return pagerDone			} 			return nil		}, count)		if err != nil {			log.Fatal(err)		} 	} 	cmd := &cobra.Command{		Use:   "list",		Short: "List pastes",		Run:   run,	}	cmd.Flags().IntVar(&count, "count", 0, "number of pastes to fetch")	cmd.RegisterFlagCompletionFunc("count", cobra.NoFileCompletions)	return cmd} func printPaste(w io.Writer, paste *pastesrht.Paste) {	fmt.Fprintf(w, "%s %s %s\n", termfmt.DarkYellow.Sprint(paste.Id),		paste.Visibility.TermString(), humanize.Time(paste.Created.Time))	for _, file := range paste.Files {		if file.Filename != nil && *file.Filename != "" {			fmt.Fprintf(w, "  %s\n", *file.Filename)		}	}} func newPasteShowCommand() *cobra.Command {	cmd := &cobra.Command{		Use:               "show <id>",		Short:             "Display a paste",		Args:              cobra.ExactArgs(1),		ValidArgsFunction: completePasteID,	}	cmd.Run = func(cmd *cobra.Command, args []string) {		ctx := cmd.Context()		id, _, instance := parseResourceName(args[0])		c := createClientWithInstance("paste", cmd, instance) 		paste, err := pastesrht.ShowPaste(c.Client, ctx, id)		if err != nil {			log.Fatal(err)		} else if paste == nil {			log.Fatalf("Paste %q does not exist", id)		} 		fmt.Printf("%s %s %s\n", termfmt.DarkYellow.Sprint(paste.Id),			paste.Visibility.TermString(), humanize.Time(paste.Created.Time)) 		for _, file := range paste.Files {			fmt.Print("\n■ ")			if file.Filename != nil && *file.Filename != "" {				fmt.Println(termfmt.Bold.String(*file.Filename))			} else {				fmt.Println(termfmt.Dim.String("(untitled)"))			}			fmt.Println() 			fetchPasteFile(ctx, c.HTTP, &file)		}	}	return cmd} func fetchPasteFile(ctx context.Context, c *http.Client, file *pastesrht.File) {	req, err := http.NewRequestWithContext(ctx, http.MethodGet, string(file.Contents), nil)	if err != nil {		log.Fatalf("Failed to create request to fetch file: %v", err)	} 	resp, err := c.Do(req)	if err != nil {		log.Fatalf("Failed to fetch file: %v", err)	}	defer resp.Body.Close() 	if _, err := io.Copy(os.Stdout, resp.Body); err != nil {		log.Fatalf("Failed to copy to stdout: %v", err)	}} func newPasteUpdateCommand() *cobra.Command {	var visibility string	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context()		c := createClient("paste", cmd) 		pasteVisibility, err := pastesrht.ParseVisibility(visibility)		if err != nil {			log.Fatal(err)		} 		paste, err := pastesrht.Update(c.Client, ctx, args[0], pasteVisibility)		if err != nil {			log.Fatal(err)		} 		if paste == nil {			log.Fatalf("Paste %s does not exist\n", args[0])		} 		log.Printf("Updated paste %s visibility to %s\n", paste.Id, pasteVisibility)	} 	cmd := &cobra.Command{		Use:               "update <ID>",		Short:             "Update a paste's visibility",		Args:              cobra.ExactArgs(1),		ValidArgsFunction: completePasteID,		Run:               run,	}	cmd.Flags().StringVarP(&visibility, "visibility", "v", "", "paste visibility")	cmd.MarkFlagRequired("visibility")	cmd.RegisterFlagCompletionFunc("visibility", completeVisibility)	return cmd} func newPasteUserWebhookCommand() *cobra.Command {	cmd := &cobra.Command{		Use:   "user-webhook",		Short: "Manage user webhooks",	}	cmd.AddCommand(newPasteUserWebhookCreateCommand())	cmd.AddCommand(newPasteUserWebhookListCommand())	cmd.AddCommand(newPasteUserWebhookDeleteCommand())	return cmd} func newPasteUserWebhookCreateCommand() *cobra.Command {	var events []string	var stdin bool	var url, query string	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context()		c := createClient("paste", cmd) 		var config pastesrht.UserWebhookInput		config.Url = url 		whEvents, err := pastesrht.ParseEvents(events)		if err != nil {			log.Fatal(err)		}		config.Events = whEvents		config.Query = readWebhookQuery(stdin, query) 		webhook, err := pastesrht.CreateUserWebhook(c.Client, ctx, config)		if err != nil {			log.Fatal(err)		} 		log.Printf("Created user webhook with ID %d\n", webhook.Id)	} 	cmd := &cobra.Command{		Use:               "create",		Short:             "Create a user webhook",		Args:              cobra.ExactArgs(0),		ValidArgsFunction: cobra.NoFileCompletions,		Run:               run,	}	cmd.Flags().StringSliceVarP(&events, "events", "e", nil, "webhook events")	cmd.RegisterFlagCompletionFunc("events", completePasteUserWebhookEvents)	cmd.MarkFlagRequired("events")	cmd.Flags().BoolVar(&stdin, "stdin", !isStdinTerminal, "read webhook query from stdin")	cmd.Flags().StringVarP(&query, "query", "q", "", "webhook query")	cmd.RegisterFlagCompletionFunc("query", cobra.NoFileCompletions)	cmd.MarkFlagsMutuallyExclusive("query", "stdin")	cmd.Flags().StringVarP(&url, "url", "u", "", "payload url")	cmd.RegisterFlagCompletionFunc("url", cobra.NoFileCompletions)	cmd.MarkFlagRequired("url")	return cmd} func newPasteUserWebhookListCommand() *cobra.Command {	var count, printed int	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context()		c := createClient("paste", cmd)		var cursor *pastesrht.Cursor 		err := pagerify(func(p pager) error {			webhooks, err := pastesrht.UserWebhooks(c.Client, ctx, cursor)			if err != nil {				return err			} 			for _, webhook := range webhooks.Results {				if count != 0 && printed == count {					return pagerDone				}				fmt.Fprintf(p, "%s %s\n", termfmt.DarkYellow.Sprintf("#%d", webhook.Id), webhook.Url)				printed += 1			} 			cursor = webhooks.Cursor			if p.IsDone(cursor, len(webhooks.Results)) {				return pagerDone			} 			return nil		}, count)		if err != nil {			log.Fatal(err)		}	} 	cmd := &cobra.Command{		Use:   "list",		Short: "List user webhooks",		Args:  cobra.ExactArgs(0),		Run:   run,	}	cmd.Flags().IntVar(&count, "count", 0, "number of webhooks to fetch")	cmd.RegisterFlagCompletionFunc("count", cobra.NoFileCompletions)	return cmd} func newPasteUserWebhookDeleteCommand() *cobra.Command {	run := func(cmd *cobra.Command, args []string) {		ctx := cmd.Context()		c := createClient("paste", cmd) 		id, err := parseInt32(args[0])		if err != nil {			log.Fatal(err)		} 		webhook, err := pastesrht.DeleteUserWebhook(c.Client, ctx, id)		if err != nil {			log.Fatal(err)		} 		log.Printf("Deleted user webhook with ID %d\n", webhook.Id)	} 	cmd := &cobra.Command{		Use:               "delete <ID>",		Short:             "Delete a user webhook",		Args:              cobra.ExactArgs(1),		ValidArgsFunction: completePasteUserWebhookID,		Run:               run,	}	return cmd} func completePasteID(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {	ctx := cmd.Context()	c := createClient("paste", cmd)	var pasteList []string 	pastes, err := pastesrht.PasteCompletionList(c.Client, ctx)	if err != nil {		return nil, cobra.ShellCompDirectiveNoFileComp	} 	for _, paste := range pastes.Results {		if cmd.Name() == "delete" && slices.Contains(cmd.Flags().Args(), paste.Id) {			continue		} 		str := paste.Id		var files strings.Builder 		for i, file := range paste.Files {			if file.Filename != nil && *file.Filename != "" {				if i != 0 {					files.WriteString(", ")				}				files.WriteString(*file.Filename)			}		} 		if files.String() != "" {			str += fmt.Sprintf("\t%s", files.String())		} 		pasteList = append(pasteList, str)	} 	return pasteList, cobra.ShellCompDirectiveNoFileComp} func completePasteUserWebhookEvents(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {	var eventList []string	events := [3]string{"paste_created", "paste_updated", "paste_deleted"}	set := strings.ToLower(cmd.Flag("events").Value.String())	for _, event := range events {		if !strings.Contains(set, event) {			eventList = append(eventList, event)		}	}	return eventList, cobra.ShellCompDirectiveNoFileComp} func completePasteUserWebhookID(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {	ctx := cmd.Context()	c := createClient("paste", cmd)	var webhookList []string 	webhooks, err := pastesrht.UserWebhooks(c.Client, ctx, nil)	if err != nil {		return nil, cobra.ShellCompDirectiveNoFileComp	} 	for _, webhook := range webhooks.Results {		s := fmt.Sprintf("%d\t%s", webhook.Id, webhook.Url)		webhookList = append(webhookList, s)	} 	return webhookList, cobra.ShellCompDirectiveNoFileComp}