Pastebin

pastebin-client.go at []
Login

File client/pastebin-client.go from the latest check-in


package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strconv"
)

var (
	pasteURL      = "<insert paste url here>"
	apiKey        = "<insert API key here>"
	errInvalidKey = errors.New("invalid paste key")
)

type paste struct {
	URL        string
	Inserttime string
	Mimetype   string
}

func pastesList() (io.ReadCloser, error) {
	listURL := fmt.Sprintf("%s/api/list", pasteURL)
	resp, err := http.PostForm(listURL, url.Values{"apikey": {apiKey}})
	if err != nil {
		return nil, err
	}

	return resp.Body, nil
}

func isPasteKey(key string) bool {
	if len(key) != 10 {
		return false
	}

	_, err := strconv.ParseUint(key, 16, 64)
	return err == nil
}

func pasteDelete(pasteKey string) error {
	if !isPasteKey(pasteKey) {
		return errInvalidKey
	}
	deleteURL := fmt.Sprintf("%s/api/del/%s", pasteURL, pasteKey)
	_, err := http.PostForm(deleteURL, url.Values{"apikey": {apiKey}})
	return err
}

func pastesBrowse() error {
	reader, err := pastesList()
	if err != nil {
		return err
	}
	defer reader.Close()

	jsonData, err := ioutil.ReadAll(reader)
	if err != nil {
		return err
	}

	var pastes []paste
	err = json.Unmarshal(jsonData, &pastes)
	if err != nil {
		return err
	}

	for _, p := range pastes {
		err := exec.Command("xdg-open", p.URL).Run()
		if err != nil {
			return err
		}
	}

	return nil
}

func pastesPurge(nDays uint) error {
	purgeURL := fmt.Sprintf("%s/api/purge/%d", pasteURL, nDays)
	_, err := http.PostForm(purgeURL, url.Values{"apikey": {apiKey}})
	return err
}

func pasteAdd(reader io.Reader) error {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile("data", "data")
	if err != nil {
		return err
	}
	_, err = io.Copy(part, reader)

	err = writer.Close()
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", pasteURL, body)
	req.Header.Set("Content-Type", writer.FormDataContentType())

	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	io.Copy(os.Stdout, resp.Body)
	resp.Body.Close()
	return nil
}

func main() {
	log.SetPrefix(os.Args[0] + ": ")
	log.SetFlags(0)

	flagList := flag.Bool("l", false, "list available pastes")
	flagBrowse := flag.Bool("b", false, "browse pastes")
	flagDelete := flag.String("d", "", "delete a paste by its `pasteid`")
	flagPurge := flag.Uint("p", 0, "purge pastes older than `ndays`")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Command line pastebin client\n")
		fmt.Fprintf(os.Stderr, "Usage:\n")
		fmt.Fprintf(os.Stderr, "  %s < file\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Options:\n")
		flag.PrintDefaults()
	}
	flag.Parse()

	if *flagList {
		jsonReader, err := pastesList()
		if err != nil {
			log.Fatal(err)
		}
		io.Copy(os.Stdout, jsonReader)
		jsonReader.Close()
		return
	}

	if *flagBrowse {
		if err := pastesBrowse(); err != nil {
			log.Fatal(err)
		}
		return
	}

	if *flagDelete != "" {
		if err := pasteDelete(*flagDelete); err != nil {
			log.Fatal(err)
		}
		return
	}

	if *flagPurge > 0 {
		if err := pastesPurge(*flagPurge); err != nil {
			log.Fatal(err)
		}
		return
	}

	input := os.Stdin
	if flag.Arg(0) != "" {
		file, err := os.Open(flag.Arg(0))
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()
		input = file
	}

	if err := pasteAdd(input); err != nil {
		log.Fatal(err)
	}
}