commit 87b3cbca26ba637be9b916021f77760d72fe0199 Author: blek Date: Fri Nov 3 02:09:45 2023 +1000 init repo diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..58b4422 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +bfile_cli diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..308d5bd --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module blek/bfile_cli + +go 1.21.3 + +require github.com/alecthomas/kong v0.8.1 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..86ba948 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY= +github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= diff --git a/main.go b/main.go new file mode 100644 index 0000000..b4d1f1b --- /dev/null +++ b/main.go @@ -0,0 +1,111 @@ +package main + +import "os" +import "fmt" +import "time" +import "mime" +import "bytes" +import "strings" +import "net/http" +import "io/ioutil" +import "path/filepath" +import "mime/multipart" +import "net/textproto" + +import "github.com/alecthomas/kong" + +var Args struct { + Upload struct { + Filename string `optional:"" short:"n" help:"A short name by which the file can be accessed"` + File string `arg:"" help:"The URL or a path to a file to upload"` + + Instance string `arg:"" help:"The URL of the instance to upload the file to"` + Tos bool `short:"t" default:"false"` + } `cmd:"" help:"Upload a file"` +} + +func upload(args *kong.Context) { + + if strings.HasSuffix(Args.Upload.Instance, "/") { + fmt.Fprintf(os.Stderr, "Error: instance URL must not end with /\n") + os.Exit(1) + } + + if ! Args.Upload.Tos { + fmt.Println("You must agree to the ToS!"); + fmt.Println("It can be found at", Args.Upload.Instance + "/tos") + os.Exit(2) + } + + if _, err := os.Stat(Args.Upload.File); err != nil { + fmt.Fprintf(os.Stderr, "Error: can't read file %s\n", Args.Upload.File) + os.Exit(1) + } + + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + ftype := mime.TypeByExtension(filepath.Ext(Args.Upload.File)) + if ftype == "" { + ftype = "application/x-octet-stream" + } + + fileHeader := textproto.MIMEHeader{} + fileHeader.Set("Content-Type", ftype) + fileHeader.Set("Content-Disposition", fmt.Sprintf("form-data; name=\"file\"; filename=\"%s\"", Args.Upload.File)) + part, err := writer.CreatePart(fileHeader) + if err != nil { + panic(err) + } + + tosHeader := textproto.MIMEHeader{} + tosHeader.Set("Content-Type", "text/plain") + tosHeader.Set("Content-Disposition", fmt.Sprintf("form-data; name=\"tos_consent\"; filename=\"%s\"", Args.Upload.File)) + tos, err := writer.CreatePart(tosHeader) + if err != nil { + panic(err) + } + tos.Write([]byte("on")) + + file, err := ioutil.ReadFile(Args.Upload.File) + if err != nil { + panic(err) + } + + part.Write([]byte(file)) + + writer.Close() + + req, err := http.NewRequest("POST", Args.Upload.Instance + "/curlapi/upload", body) + if err != nil { + panic(err) + } + + cType := writer.FormDataContentType() + req.Header.Set("Content-Type", cType) + req.Header.Set("Content-Length", fmt.Sprintf("%d", body.Len())) + + client := &http.Client{Timeout: 120 * time.Second} + api, err := client.Do(req) + if err != nil { + panic(err) + } + + defer api.Body.Close() + data, err := ioutil.ReadAll(api.Body) + if err != nil { + panic(err) + } + fmt.Println(string(data)) +} + +func main() { + args := kong.Parse(&Args) + + switch args.Command() { + case "upload ": + upload(args) + default: + panic(args.Command()) + } +} \ No newline at end of file