mirror of
https://github.com/fiatjaf/nak.git
synced 2025-04-23 01:49:56 -04:00
223 lines
5.9 KiB
Go
223 lines
5.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/nbd-wtf/go-nostr/keyer"
|
|
"github.com/nbd-wtf/go-nostr/nipb0/blossom"
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
var blossomCmd = &cli.Command{
|
|
Name: "blossom",
|
|
Suggest: true,
|
|
UseShortOptionHandling: true,
|
|
Usage: "an army knife for blossom things",
|
|
DisableSliceFlagSeparator: true,
|
|
Flags: append(defaultKeyFlags,
|
|
&cli.StringFlag{
|
|
Name: "server",
|
|
Aliases: []string{"s"},
|
|
Usage: "the hostname of the target mediaserver",
|
|
Required: true,
|
|
},
|
|
),
|
|
Commands: []*cli.Command{
|
|
{
|
|
Name: "list",
|
|
Usage: "lists blobs from a pubkey",
|
|
Description: `takes one pubkey passed as an argument or derives one from the --sec supplied. if that is given then it will also pre-authorize the list, which some servers may require.`,
|
|
DisableSliceFlagSeparator: true,
|
|
ArgsUsage: "[pubkey]",
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
|
var client *blossom.Client
|
|
pubkey := c.Args().First()
|
|
if pubkey != "" {
|
|
client = blossom.NewClient(client.GetMediaServer(), keyer.NewReadOnlySigner(pubkey))
|
|
} else {
|
|
var err error
|
|
client, err = getBlossomClient(ctx, c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
bds, err := client.List(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, bd := range bds {
|
|
stdout(bd)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "upload",
|
|
Usage: "uploads a file to a specific mediaserver.",
|
|
Description: `takes any number of local file paths and uploads them to a mediaserver, printing the resulting blob descriptions when successful.`,
|
|
DisableSliceFlagSeparator: true,
|
|
ArgsUsage: "[files...]",
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
|
client, err := getBlossomClient(ctx, c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hasError := false
|
|
for _, fpath := range c.Args().Slice() {
|
|
bd, err := client.UploadFile(ctx, fpath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
hasError = true
|
|
continue
|
|
}
|
|
|
|
j, _ := json.Marshal(bd)
|
|
stdout(string(j))
|
|
}
|
|
|
|
if hasError {
|
|
os.Exit(3)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "download",
|
|
Usage: "downloads files from mediaservers",
|
|
Description: `takes any number of sha256 hashes as hex, downloads them and prints them to stdout (unless --output is specified).`,
|
|
DisableSliceFlagSeparator: true,
|
|
ArgsUsage: "[sha256...]",
|
|
Flags: []cli.Flag{
|
|
&cli.StringSliceFlag{
|
|
Name: "output",
|
|
Aliases: []string{"o"},
|
|
Usage: "file name to save downloaded file to, can be passed multiple times when downloading multiple hashes",
|
|
},
|
|
},
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
|
client, err := getBlossomClient(ctx, c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
outputs := c.StringSlice("output")
|
|
|
|
hasError := false
|
|
for i, hash := range c.Args().Slice() {
|
|
if len(outputs)-1 >= i && outputs[i] != "--" {
|
|
// save to this file
|
|
err := client.DownloadToFile(ctx, hash, outputs[i])
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
hasError = true
|
|
}
|
|
} else {
|
|
// if output wasn't specified, print to stdout
|
|
data, err := client.Download(ctx, hash)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
hasError = true
|
|
continue
|
|
}
|
|
os.Stdout.Write(data)
|
|
}
|
|
}
|
|
|
|
if hasError {
|
|
os.Exit(2)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "del",
|
|
Aliases: []string{"delete"},
|
|
Usage: "deletes a file from a mediaserver",
|
|
Description: `takes any number of sha256 hashes, signs authorizations and deletes them from the current mediaserver.
|
|
|
|
if any of the files are not deleted command will fail, otherwise it will succeed. it will also print error messages to stderr and the hashes it successfully deletes to stdout.`,
|
|
DisableSliceFlagSeparator: true,
|
|
ArgsUsage: "[sha256...]",
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
|
client, err := getBlossomClient(ctx, c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hasError := false
|
|
for _, hash := range c.Args().Slice() {
|
|
err := client.Delete(ctx, hash)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
hasError = true
|
|
continue
|
|
}
|
|
|
|
stdout(hash)
|
|
}
|
|
|
|
if hasError {
|
|
os.Exit(3)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "check",
|
|
Usage: "asks the mediaserver if it has the specified hashes.",
|
|
Description: `uses the HEAD request to succintly check if the server has the specified sha256 hash.
|
|
|
|
if any of the files are not found the command will fail, otherwise it will succeed. it will also print error messages to stderr and the hashes it finds to stdout.`,
|
|
DisableSliceFlagSeparator: true,
|
|
ArgsUsage: "[sha256...]",
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
|
client, err := getBlossomClient(ctx, c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hasError := false
|
|
for _, hash := range c.Args().Slice() {
|
|
err := client.Check(ctx, hash)
|
|
if err != nil {
|
|
hasError = true
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
continue
|
|
}
|
|
|
|
stdout(hash)
|
|
}
|
|
|
|
if hasError {
|
|
os.Exit(2)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "mirror",
|
|
Usage: "",
|
|
Description: ``,
|
|
DisableSliceFlagSeparator: true,
|
|
ArgsUsage: "",
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
|
return nil
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
func getBlossomClient(ctx context.Context, c *cli.Command) (*blossom.Client, error) {
|
|
keyer, _, err := gatherKeyerFromArguments(ctx, c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return blossom.NewClient(c.String("server"), keyer), nil
|
|
}
|