Files
asciinema/api/api.go
2014-11-13 20:45:59 +01:00

106 lines
2.1 KiB
Go

package api
import (
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"os"
"time"
)
type Frame struct {
Delay float64
Data []byte
}
type Api interface {
CreateAsciicast([]Frame, time.Duration, int, int, string, string) (string, error)
}
func New(url, token string) *AsciinemaApi {
return &AsciinemaApi{
url: url,
token: token,
http: &HttpClient{},
}
}
type AsciinemaApi struct {
url string
token string
http HTTP
}
func (a *AsciinemaApi) CreateAsciicast(frames []Frame, duration time.Duration, cols, rows int, command, title string) (string, error) {
files := map[string]io.Reader{
"asciicast[stdout]:stdout": gzippedDataReader(frames),
"asciicast[stdout_timing]:stdout.time": gzippedTimingReader(frames),
"asciicast[meta]:meta.json": metadataReader(duration, cols, rows, command, title),
}
// TODO: set proper user agent
response, err := a.http.PostForm(a.url+"/api/asciicasts", os.Getenv("USER"), a.token, files)
if err != nil {
return "", err
}
defer response.Body.Close()
body := &bytes.Buffer{}
_, err = body.ReadFrom(response.Body)
if err != nil {
return "", err
}
// TODO: handle non-200 statuses
return body.String(), nil
}
func gzippedDataReader(frames []Frame) io.Reader {
data := &bytes.Buffer{}
w := gzip.NewWriter(data)
for _, frame := range frames {
w.Write(frame.Data)
}
w.Close()
return data
}
func gzippedTimingReader(frames []Frame) io.Reader {
timing := &bytes.Buffer{}
w := gzip.NewWriter(timing)
for _, frame := range frames {
w.Write([]byte(fmt.Sprintf("%f %d\n", frame.Delay, len(frame.Data))))
}
w.Close()
return timing
}
func metadataReader(duration time.Duration, cols, rows int, command, title string) io.Reader {
metadata := map[string]interface{}{
"duration": duration.Seconds(),
"title": title,
"command": command,
"shell": os.Getenv("SHELL"),
"term": map[string]interface{}{
"type": os.Getenv("TERM"),
"columns": cols,
"lines": rows,
},
}
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
encoder.Encode(metadata)
return buf
}