small pixel drawing of a pufferfish j3s.sh

main.go

package main

import (
	"html/template"
	"log"
	"net/http"
	"os"
	"io"
	"path/filepath"
	"strings"
	"bytes"

	"git.j3s.sh/j3s.sh/feed"
	"github.com/SlyMarbo/rss"
	"filippo.io/age"
	"filippo.io/age/armor"
)

// templateData is a mega-struct that gets
// passed to every single template - put whatever
// you want in it tbh.
//
// "data" is a global object that contains arbitrary
// data for use in templates. it's useful for it to be
// global since it may need to be available in arbitrary
// contexts. maybe that sucks. but idfk!
type templateData struct {
	FriendFeeds []rss.Feed
}

var data templateData

// the populate function populates the global "data" variable
// with ... data. with which to pass into templates.
func (t *templateData) populate() {
	t.FriendFeeds = feed.FetchFriendFeeds()
}

func main() {
	data.populate()

	fs := http.FileServer(http.Dir("./static"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	http.HandleFunc("/age.html", serveAge)
	http.HandleFunc("/review/", babyHandler)
	http.HandleFunc("/thought/", babyHandler)
	http.HandleFunc("/", serveTemplate)

	log.Println("listening on :4666 tbh")
	err := http.ListenAndServe(":4666", nil)
	if err != nil {
		log.Fatal(err)
	}
}

func serveTemplate(w http.ResponseWriter, r *http.Request) {
	lp := filepath.Join("templates", "layout.html")
	if r.URL.Path == "/" {
		r.URL.Path = "index.html"
		// TODO: add some arbitrary refresh handler for fetchFriendPosts
	}
	fp := filepath.Join("templates", filepath.Clean(r.URL.Path))

	info, err := os.Stat(fp)
	if err != nil {
		if os.IsNotExist(err) {
			http.NotFound(w, r)
			return
		}
	}

	if info.IsDir() {
		http.NotFound(w, r)
		return
	}

	tmpl, err := template.ParseFiles(lp, fp)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}

	err = tmpl.ExecuteTemplate(w, "layout", data)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
	}
}

func babyHandler(w http.ResponseWriter, r *http.Request) {
	lp := filepath.Join("templates", "simple-layout.html")
	fp := filepath.Join(strings.TrimPrefix(filepath.Clean(r.URL.Path), "/"))

	info, err := os.Stat(fp)
	if err != nil {
		if os.IsNotExist(err) {
			http.NotFound(w, r)
			return
		}
	}

	if info.IsDir() {
		http.NotFound(w, r)
		return
	}

	content, err := os.ReadFile(fp)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}

	tmpl, err := template.ParseFiles(lp)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}

	err = tmpl.ExecuteTemplate(w, "simple-layout", string(content))
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
	}
}

type AgeForm struct {
	Success bool
    PublicKey string
    Message string
}

func serveAge(w http.ResponseWriter, r *http.Request) {
	lp := filepath.Join("templates", "layout.html")
	fp := filepath.Join("templates", "age.html")

	tmpl, err := template.ParseFiles(lp, fp)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}

	if r.Method != http.MethodPost {
		tmpl.ExecuteTemplate(w, "layout", nil)
		return
	}

	formdeets := AgeForm{
		PublicKey:   r.FormValue("pubkey"),
		Message: r.FormValue("message"),
	}

	recipient, err := age.ParseX25519Recipient(formdeets.PublicKey)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}

	buf := &bytes.Buffer{}
	armorWriter := armor.NewWriter(buf)

	write, err := age.Encrypt(armorWriter, recipient)
	if err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}
	if _, err := io.WriteString(write, formdeets.Message); err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}
	if err := write.Close(); err != nil {
		log.Println(err.Error())
		http.Error(w, http.StatusText(500), 500)
		return
	}
	if err := armorWriter.Close(); err != nil {
		log.Fatalf("Failed to close armor: %v", err)
	}

	log.Printf("%+v", buf)

	tmpl.ExecuteTemplate(w, "layout", buf.String())
}