/*
Filename: main.go
Description: holy moly. a cat that says holy moly (or anything else you want it to). original image by x.com/BasiilLeaf
Created by: osh
at: 20:19 on Monday, the 20th of July, 2026
Last edited 00:27 on Friday, the 21st of August, 2026
*/
package main
import (
"bytes"
"context"
"crypto/sha256"
_ "embed"
"fmt"
"html"
"image"
"image/color"
"image/draw"
"image/png"
"io"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
xdraw "golang.org/x/image/draw"
"golang.org/x/image/font"
"golang.org/x/image/font/gofont/goregular"
"golang.org/x/image/font/opentype"
"golang.org/x/image/math/fixed"
"github.com/lrstanley/go-ytdlp"
)
//go:embed holymolyblank.png
var holymolyblank []byte
//go:embed holymolycutout.png
var holymolycutout []byte
const (
textX = 458 // x coord speech bubble centre
textY = 152 // y coord speech bubble centre
maxTextWidth = 160 // max width before overflow of the text bubble
maxLines = 3 // max number of lines total
maxFontSize = 10 // max font size that the text can be
minFontSize = 8 // min font size that the text can be
cutoutX = 363 // speech bubble cutout left
cutoutY = 106 // speech bubble cutout top
cutoutW = 188 // speech bubble cutout width
cutoutH = 94 // speech bubble cutout height
textRescaleQuality = 2 // text is rendered at 1/textRescaleQuality and then rescaled back up
)
var (
baseImage image.Image
cutoutImage image.Image
gofont *opentype.Font
cacheDir = filepath.Join(os.TempDir(), "holymoly-cache")
cutoutPath = filepath.Join(os.TempDir(), "holymoly-cutout.png")
cookiesPath string
)
func main() {
// holymoly.png
var err error
baseImage, err = png.Decode(bytes.NewReader(holymolyblank))
if err != nil {
log.Fatal(err)
}
cutoutImage, err = png.Decode((bytes.NewReader(holymolycutout)))
if err != nil {
log.Fatal(err)
}
gofont, err = opentype.Parse(goregular.TTF)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile(cutoutPath, holymolycutout, 0o644); err != nil {
log.Fatal(err)
}
// setup ytdlp
if cookies := os.Getenv("COOKIES"); cookies != "" {
b, err := os.ReadFile(cookies)
if err != nil {
log.Fatal("cookies:", err)
}
cookiesPath = filepath.Join(os.TempDir(), "cookies.txt")
if err := os.WriteFile(cookiesPath, b, 0o600); err != nil {
log.Fatal(err)
}
}
if os.Getenv("FFMPEG") == "" {
log.Fatalln("$FFMPEG unset")
}
installed, err := ytdlp.InstallAll(context.Background())
for _, elem := range installed {
if elem.Downloaded {
log.Println("downloaded", elem.Executable, "version", elem.Version)
}
}
if _, err := ytdlp.New().UpdateTo(context.Background(), "nightly"); err != nil {
log.Println("yt-dlp update:", err)
}
// start the server
var port string
if port = os.Getenv("PORT"); port == "" {
log.Fatalln("$PORT unset")
}
port = ":" + port
log.Println("started on", port)
http.HandleFunc("/", handle)
log.Fatal(http.ListenAndServe(port, nil))
}
// parse what we pass with ?text + any flags
func handle(w http.ResponseWriter, r *http.Request) {
text := r.URL.Query().Get("text")
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
// embed credit when viewed in a browser
const pageHTML = `
holy moly
cat by @BasiilLeaf ↗
change what's said by adding ?text= to the url, like this.
_ for a space, \ for a new line, like this.
embeds into anywhere as an image.
source code: Tangled.sh ↗
`
if r.Header.Get("Sec-Fetch-Dest") == "document" {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Vary", "Sec-Fetch-Dest")
fmt.Fprintf(w, pageHTML, "https://x.com/BasiilLeaf/status/1704587547853406445", html.EscapeString(r.URL.RequestURI()), "https://x.com/BasiilLeaf/status/1704587547853406445")
return
}
// embed media — take the raw tail after embed= so a pasted url keeps its own ?&…
if _, media, ok := strings.Cut(r.URL.RawQuery, "embed="); ok && media != "" {
gif, err := embed(r.Context(), media)
if err != nil {
http.Error(w, "render failed", http.StatusInternalServerError)
log.Printf("embed %q: %v", media, err)
return
}
w.Header().Set("Content-Type", "image/gif")
w.Header().Set("Cache-Control", "public, max-age=86400")
w.Header().Set("Vary", "Sec-Fetch-Dest")
w.Write(gif)
return
}
// parse
text = strings.ReplaceAll(text, "_", " ")
chamame := r.URL.Query().Get("chamame") == "oshdubh"
credit := r.URL.Query().Get("credit") != "none" && !chamame
if chamame {
re := regexp.MustCompile(`\s*\(.*\)`)
text = re.ReplaceAllString(text, "")
}
if strings.TrimSpace(text) == "" {
text = "holy moly"
}
// return the image
face, lines, err := fit(text)
var img []byte
if err == nil {
img, err = render(face, lines, credit)
}
if err != nil {
http.Error(w, "render failed", http.StatusInternalServerError)
log.Printf("render %q: %v", lines, err)
return
}
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Cache-Control", "public, max-age=86400")
w.Header().Set("Vary", "Sec-Fetch-Dest")
w.Write(img)
var logstr strings.Builder
for query, values := range r.URL.Query() {
fmt.Fprintf(&logstr, "%v: %v ", query, strings.Join(values, ", "))
}
log.Println(logstr.String())
}
// composite the image
func render(face font.Face, lines []string, credit bool) ([]byte, error) {
// build our canvas
out := image.NewRGBA(baseImage.Bounds())
draw.Draw(out, out.Bounds(), image.White, image.Point{}, draw.Src)
draw.Draw(out, out.Bounds(), baseImage, image.Point{}, draw.Over)
small := image.NewRGBA(image.Rect(0, 0, out.Bounds().Dx()/textRescaleQuality, out.Bounds().Dy()/textRescaleQuality)) // smaller canvas for lower quality text
metrics := face.Metrics()
// where we want to draw onto
lineHeight := metrics.Height
blockTop := fixed.I(textY/textRescaleQuality) - lineHeight.Mul(fixed.I(len(lines)))/2
// draw the lines
for i, line := range lines {
width := font.MeasureString(face, line)
d := font.Drawer{
Dst: small,
Src: image.Black,
Face: face,
Dot: fixed.Point26_6{ // draw in the centre, using i to make it centred vertically for multiline strings
X: fixed.I(textX/textRescaleQuality) - width/2,
Y: blockTop + lineHeight.Mul(fixed.I(i)) + metrics.Ascent,
},
}
d.DrawString(line)
}
// baked in credit
if credit {
cf, err := opentype.NewFace(gofont, &opentype.FaceOptions{
Size: 7, DPI: 90, Hinting: font.HintingFull,
})
if err != nil {
return nil, err
}
d := font.Drawer{
Dst: small,
Src: image.NewUniform(color.Gray{Y: 128}),
Face: cf,
Dot: fixed.Point26_6{X: fixed.I(4), Y: cf.Metrics().Ascent + fixed.I(3)},
}
d.DrawString("@BasiilLeaf")
}
xdraw.NearestNeighbor.Scale(out, out.Bounds(), small, small.Bounds(), xdraw.Over, nil)
// encode the bytes as a png and return
var buf bytes.Buffer
if err := png.Encode(&buf, out); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// resize the text, respecting our limits, to get the text into the speech bubble
func fit(text string) (face font.Face, lines []string, err error) {
limit := fixed.I(maxTextWidth / textRescaleQuality) // measure based on our lower qualty text canvas
// scale down until it fits
for size := maxFontSize; size >= minFontSize; size-- {
face, err = opentype.NewFace(gofont, &opentype.FaceOptions{
Size: float64(size), DPI: 72, Hinting: font.HintingFull,
})
if err != nil {
return nil, nil, err
}
lines = lines[:0]
for seg := range strings.SplitSeq(text, "\\") {
line := ""
for word := range strings.FieldsSeq(seg) {
switch {
case line == "": // first word
line = word
case font.MeasureString(face, line+" "+word) > limit: // would overflow
lines = append(lines, line)
line = word
default:
line += " " + word
}
}
lines = append(lines, line) // force the break at backslashes
}
// catch any words too big for the bubble, giving them their own lines
widest := fixed.Int26_6(0)
for _, l := range lines {
if w := font.MeasureString(face, l); w > widest {
widest = w
}
}
if len(lines) <= maxLines && widest <= limit {
return face, lines, nil
}
}
return face, lines, nil
}
// download the passed media, and composite an image with it embedded
func embed(ctx context.Context, url string) ([]byte, error) {
key := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
// serve a previously rendered gif if we have one
cached := filepath.Join(cacheDir, key+".gif")
if cachedBytes, err := os.ReadFile(cached); err == nil {
log.Println("serving cached gif for", url)
return cachedBytes, nil
}
log.Println("downloading", url)
ext := strings.ToLower(filepath.Ext(strings.SplitN(url, "?", 2)[0])) // filetype detect
switch ext {
case ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp":
dst := filepath.Join(os.TempDir(), key+ext)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("fetch %s: %s", url, resp.Status)
}
f, err := os.Create(dst)
if err != nil {
return nil, err
}
if _, err := io.Copy(f, resp.Body); err != nil {
f.Close()
return nil, err
}
f.Close()
default:
out := filepath.Join(os.TempDir(), key+".%(ext)s")
//lowest quality version
download := ytdlp.New().
Format("wv*[height<=480]+wa/w[height<=480]").
Output(out)
if cookiesPath != "" {
download = download.Cookies(cookiesPath)
}
details, _ := download.Run(ctx, url)
if details.ExitCode != 0 {
return nil, fmt.Errorf("exited with code %v: %v\n", details.ExitCode, details.Stderr)
}
log.Println("running", details.Executable, strings.Join(details.Args, " "))
}
matches, err := filepath.Glob(filepath.Join(os.TempDir(), key+".*"))
if err != nil || len(matches) == 0 {
return nil, fmt.Errorf("no download saved")
}
video := matches[0]
defer os.Remove(video)
// ffmpeg reformatting
filter := fmt.Sprintf(
"color=c=white:s=645x432:d=600[bg];"+
"[0:v]scale=%d:%d:force_original_aspect_ratio=increase,crop=%d:%d,fps=15[v];"+
"[bg][v]overlay=%d:%d:shortest=1[bgv];"+
"[bgv][1:v]overlay=0:0[flat];"+
"[flat]split[a][b];[a]palettegen[p];[b][p]paletteuse",
cutoutW, cutoutH, cutoutW, cutoutH, cutoutX, cutoutY,
)
// gif it
var buf bytes.Buffer
cmd := exec.CommandContext(ctx, os.Getenv("FFMPEG"),
"-i", video,
"-i", cutoutPath,
"-filter_complex", filter,
"-f", "gif",
"pipe:1",
)
cmd.Stdout = &buf
if err := cmd.Run(); err != nil {
return nil, err
}
// cache the result
if err := os.MkdirAll(cacheDir, 0o755); err == nil {
os.WriteFile(cached, buf.Bytes(), 0o644)
}
return buf.Bytes(), nil
}