You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
weekly/main.go

233 lines
4.5 KiB

package main
import (
"bytes"
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"os/exec"
"strings"
tt "text/template"
"time"
"github.com/jinzhu/now"
"p83.nl/go/ekster/pkg/jf2"
"p83.nl/go/ekster/pkg/microsub"
"willnorris.com/go/microformats"
)
var (
show = flag.Bool("show", false, "Show the output")
server = flag.String("endpoint", "", "Micropub endpoint specified in shpub")
)
// Summary is a summary of the last few posts on a blog
type Summary struct {
PostTypes map[string]string
Name string
Items []microsub.Item
Grouped map[string][]microsub.Item
}
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
func main() {
flag.Parse()
if !*show && *server == "" {
log.Println("Specify -endpoint when using micropub")
return
}
args := flag.Args()
u, err := url.Parse(args[0])
if err != nil {
log.Fatal(err)
}
var buf bytes.Buffer
items, err := getEntriesForFeed(u)
if err != nil {
log.Fatal(err)
}
monday := now.With(time.Now()).Monday().AddDate(0, 0, -7)
items = filterEntriesAfter(items, monday)
summary := getSummary(monday, items)
err = outputEntries(summary, &buf)
if err != nil {
log.Fatal(err)
}
if *show {
io.Copy(os.Stdout, &buf)
} else {
fmt.Println("micropub")
err = micropub(summary.Name, buf.String(), *server)
if err != nil {
log.Fatal(err)
}
}
}
func getSummary(monday time.Time, items []microsub.Item) Summary {
year, week := monday.ISOWeek()
grouped := make(map[string][]microsub.Item)
for _, item := range items {
itemType := postTypeDiscovery(&item)
grouped[itemType] = append(grouped[itemType], item)
}
summary := Summary{
Name: fmt.Sprintf("Digest for Week %d-%d", week, year),
Items: items,
Grouped: grouped,
}
return summary
}
func outputEntries(summary Summary, w io.Writer) error {
summary.PostTypes = map[string]string{
"checkin": "Checkins",
"event": "Events",
"repost": "Reposts",
"like": "Likes",
"reply": "Replies",
"bookmark": "Bookmarks",
"photo": "Photos",
"note": "Notes",
"article": "Articles",
}
t, err := tt.ParseFiles("templates/weekly.md.tmpl")
if err != nil {
log.Fatal(err)
}
err = t.Execute(w, summary)
if err != nil {
return err
}
return nil
}
func postTypeDiscovery(item *microsub.Item) string {
if item == nil {
return ""
}
if item.Checkin != nil {
return "checkin"
}
if item.Type == "event" {
return "event"
}
if len(item.RepostOf) > 0 && validURL(item.RepostOf[0]) {
return "repost"
}
if len(item.LikeOf) > 0 && validURL(item.LikeOf[0]) {
return "like"
}
if len(item.InReplyTo) > 0 && validURL(item.InReplyTo[0]) {
return "reply"
}
if len(item.BookmarkOf) > 0 && validURL(item.BookmarkOf[0]) {
return "bookmark"
}
if len(item.Photo) > 0 && validURL(item.Photo[0]) {
return "photo"
}
var content, name string
if item.Content != nil {
content = item.Content.Text
}
if content == "" {
if item.Summary != "" {
content = item.Summary
}
}
if content == "" {
return "note"
}
name = item.Name
if name == "" {
return "note"
}
name = strings.Join(strings.Fields(strings.TrimSpace(name)), " ")
content = strings.Join(strings.Fields(strings.TrimSpace(content)), " ")
if !strings.HasPrefix(content, name) {
return "article"
}
return "note"
}
func validURL(u string) bool {
_, err := url.Parse(u)
return err == nil
}
func getEntriesForFeed(u *url.URL) ([]microsub.Item, error) {
resp, err := http.Get(u.String())
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("status is not 200, but %d", resp.StatusCode)
}
md := microformats.Parse(resp.Body, u)
items := jf2.SimplifyMicroformatDataItems(md)
return items, nil
}
func filterEntriesAfter(items []microsub.Item, from time.Time) []microsub.Item {
var result []microsub.Item
for _, item := range items {
published, err := time.Parse(time.RFC3339, item.Published)
if err != nil {
continue
}
if !published.After(from) {
continue
}
found := false
for _, cat := range item.Category {
if cat == "weekly-digest" {
found = true
}
}
if found {
continue
}
result = append(result, item)
}
return result
}
func micropub(name, content, server string) error {
var args []string
if server != "" {
args = append(args, "-s", server)
}
args = append(args, "-d", "article", "-c", "weekly-digest", "--json", "-x", "p3k-content-type=text/markdown", name, content)
cmd := exec.Command("shpub", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}