small pixel drawing of a pufferfish j3s.sh

atom/atom.go

package atom

import (
	"bufio"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const maxFeed = 10

type post struct {
	title   string
	updated string
	link    string
	// starting with content disabled because a lot of my content is nonsensical
	// to any reasonable xml parser tbh
	//	content string
}

func Handler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/atom+xml")

	posts, err := getPosts("thought/*")
	if err != nil {
		log.Println(err)
	}

	// TODO: sort them by date, then
	if len(posts) > maxFeed {
		posts = posts[:maxFeed]
	}

	var updated string
	if len(posts) > 0 {
		updated = posts[0].updated
	}

	// SET HEADER TYPE TBH
	fmt.Fprintf(w, `<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>j3s.sh</title>
  <link rel="self" href="https://j3s.sh/feed.atom" />
  <link href="https://j3s.sh/" />
  <updated>%s</updated>
  <author>
    <name>Jes Olson</name>
  </author>
  <id>https://j3s.sh/</id>
`, updated)

	for _, p := range posts {
		// add content in future? idk prob not
		fmt.Fprintf(w, `
  <entry>
    <title>%s</title>
    <link href="%s"/>
    <id>%s</id>
    <updated>%s</updated>
  </entry>
`, p.title, p.link, p.link, p.updated)
	}
	fmt.Fprint(w, `
</feed>`)
}

func getPosts(dir string) ([]post, error) {
	var posts []post
	files, err := filepath.Glob(dir)
	if err != nil {
		return nil, err
	}

	for _, f := range files {
		post, err := fileToPost(f)
		if err != nil {
			// this can be failed intentionally for drafts or posts too small for rss updoots
			// add a print statement here if blog posts mysteriously vanish from the atom feed
			//
			// lmao
			continue
		}
		posts = append(posts, post)
	}

	return posts, err
}

func fileToPost(file string) (post, error) {
	var p post

	f, err := os.Open(file)
	if err != nil {
		return p, err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	scanner.Scan() // this moves to the next token
	// strip spaces
	title := scanner.Text()
	p.title = strings.TrimSpace(title)
	scanner.Scan()
	timestr := strings.TrimSpace(scanner.Text())
	updated, err := time.Parse(timeLayoutPost, timestr)
	if err != nil {
		return p, err
	}
	//	for scanner.Scan() {
	//		p.content = p.content + scanner.Text()
	//	}
	p.updated = updated.Format(timeLayoutAtom)
	p.link = "https://j3s.sh/" + file
	return p, err
}

type TimeStr string

var timeLayoutPost = "2006-01-02"
var timeLayoutAtom = "2006-01-02T15:04:05.000Z"