aboutsummaryrefslogtreecommitdiff
path: root/client/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'client/main.go')
-rw-r--r--client/main.go196
1 files changed, 196 insertions, 0 deletions
diff --git a/client/main.go b/client/main.go
new file mode 100644
index 0000000..279c88d
--- /dev/null
+++ b/client/main.go
@@ -0,0 +1,196 @@
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+
+ "gopkg.in/yaml.v3"
+)
+
+var ConfigFn = filepath.Join(os.Getenv("HOME"), ".paste")
+var TokenFN = filepath.Join(os.Getenv("HOME"), ".paste-token")
+
+var logger = log.New(os.Stderr, "", 0)
+var httpC = &http.Client{}
+
+type Paste struct {
+ Id string
+ Title string
+ Tags map[string]struct{}
+ Content string
+}
+
+type Config struct {
+ Username string
+ Password string
+ Hostname string
+}
+
+func loadConfig(fn string) (*Config, error) {
+ fh, err := os.Open(fn)
+ if err != nil {
+ return nil, err
+ }
+ dec := yaml.NewDecoder(fh)
+ dec.KnownFields(true)
+
+ c := &Config{}
+ err = dec.Decode(c)
+
+ return c, err
+}
+
+func (c *Config) NoTokenReq(method, pth string, data interface{}) (*http.Response, error) {
+ b, err := json.Marshal(data)
+ if err != nil {
+ return nil, err
+ }
+
+ buf := bytes.NewBuffer(b)
+
+ req, err := http.NewRequest(method, c.Hostname+pth, buf)
+ if err != nil {
+ logger.Fatal(err)
+ }
+ req.Header.Add("Content-type", "application/json")
+
+ resp, err := httpC.Do(req)
+ if err != nil {
+ logger.Fatal(err)
+ }
+
+ return resp, err
+}
+
+func (c *Config) Req(method, pth string, data interface{}) (*http.Response, error) {
+ b, err := json.Marshal(data)
+ if err != nil {
+ return nil, err
+ }
+
+ buf := bytes.NewBuffer(b)
+
+ req, err := http.NewRequest(method, c.Hostname+pth, buf)
+ if err != nil {
+ logger.Fatal(err)
+ }
+ req.Header.Add("Authorization", "Bearer "+c.Token())
+ req.Header.Add("Content-type", "application/json")
+
+ resp, err := httpC.Do(req)
+ if err != nil {
+ logger.Fatal(err)
+ }
+
+ return resp, err
+}
+
+func (c *Config) Token() string {
+ s, err := c.GetToken()
+ if err != nil {
+ logger.Fatal(err)
+ }
+ return s
+}
+
+func (c *Config) GetToken() (string, error) {
+ resp, err := c.NoTokenReq("POST", "/login", map[string]string{
+ "Username": c.Username,
+ "Password": c.Password,
+ })
+ if err != nil {
+ return "", err
+ }
+
+ respData := map[string]string{}
+
+ dec := json.NewDecoder(resp.Body)
+ err = dec.Decode(&respData)
+ if err != nil {
+ return "", err
+ }
+
+ token, ok := respData["token"]
+ if !ok {
+ logger.Fatal("Cannot have empty token")
+ }
+
+ // logger.Println(token)
+
+ return token, nil
+}
+
+func (c *Config) NewPaste(title string) {
+ buf := &bytes.Buffer{}
+
+ _, err := io.Copy(buf, os.Stdin)
+ if err != nil {
+ logger.Fatal(err)
+ }
+
+ p := &Paste{
+ Title: title,
+ Content: buf.String(),
+ }
+
+ resp, err := c.Req("POST", "/new", p)
+ if err != nil {
+ logger.Fatal(err)
+ }
+
+ if resp.StatusCode != 200 {
+ io.Copy(os.Stderr, resp.Body)
+ os.Exit(1)
+ }
+
+ out := map[string]string{}
+
+ dec := json.NewDecoder(resp.Body)
+ err = dec.Decode(&out)
+ if err != nil {
+ logger.Println(err)
+ }
+
+ fmt.Printf("%s/view/%s\n", c.Hostname, out["id"])
+}
+
+func main() {
+ fl := flag.NewFlagSet("simple pastebin client", flag.ExitOnError)
+
+ fl.StringVar(&ConfigFn, "c", ConfigFn, "Configuration file")
+ title := fl.String("t", "", "Optional title for the message")
+ debug := fl.Bool("d", false, "debugging add information to the logging output DEBUG=true|false controls this as well")
+
+ _ = fl.Parse(os.Args[1:])
+
+ if d := os.Getenv("DEBUG"); d == "true" || *debug {
+ logger.SetFlags(log.LstdFlags | log.Llongfile)
+ }
+
+ conf, err := loadConfig(ConfigFn)
+ if err != nil {
+ logger.Println(err)
+
+ fmt.Println("")
+ fmt.Println("//")
+ fmt.Println("// Example configuration file")
+ enc := yaml.NewEncoder(os.Stdout)
+ enc.SetIndent(2)
+ enc.Encode(&Config{
+ Username: "changeme",
+ Password: "changeme",
+ Hostname: "https://example.com/paste",
+ })
+
+ os.Exit(1)
+ }
+
+ conf.NewPaste(*title)
+}