go-playground/playground.go

84 lines
1.8 KiB
Go

package playground
import (
"context"
"crypto/md5"
"fmt"
"io"
"net/http"
"os"
"strings"
)
var shareURL = "https://play.golang.org/share"
var cache = make(map[string]Code)
// Code is a playground code
type Code string
func (c Code) URL() string {
return fmt.Sprintf("https://play.golang.org/p/%s", c)
}
// Share creates a share link from text
func Share(ctx context.Context, contents string) (Code, error) {
return share(ctx, contents)
}
// ShareFile creates a share link from a file
func ShareFile(ctx context.Context, path string) (Code, error) {
stat, err := os.Stat(path)
if err != nil {
return "", fmt.Errorf("could not stat file: %w", err)
}
if stat.IsDir() {
return "", fmt.Errorf("%s is a directory, not a file", path)
}
if !strings.HasSuffix(stat.Name(), ".go") {
return "", fmt.Errorf("%s is not a Go file", path)
}
fi, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("could not open file: %w", err)
}
defer fi.Close()
contents, err := io.ReadAll(fi)
if err != nil {
return "", fmt.Errorf("could not read file: %w", err)
}
return share(ctx, string(contents))
}
func share(ctx context.Context, contents string) (Code, error) {
hash := fmt.Sprintf("%x", md5.Sum([]byte(contents)))
if link, ok := cache[hash]; ok {
return link, nil
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, shareURL, strings.NewReader(contents))
if err != nil {
return "", fmt.Errorf("could not create request: %w", err)
}
req.Header.Set("User-Agent", "git.jojodev.com/golang/go-playground")
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("could not create share link: %w", err)
}
defer res.Body.Close()
b, err := io.ReadAll(res.Body)
if err != nil {
return "", fmt.Errorf("could not read response body: %w", err)
}
cache[hash] = Code(b)
return cache[hash], nil
}