diff options
| author | Christine Dodrill <me@christine.website> | 2018-07-01 13:20:01 -0700 |
|---|---|---|
| committer | Christine Dodrill <me@christine.website> | 2018-07-01 13:20:01 -0700 |
| commit | 599712fab9127013e2d89dadabd839c847730637 (patch) | |
| tree | 2a69843e6a5fbdb69cf4c4600e5a8693a3c4a708 /cmd/site/main.go | |
| parent | 7d8c210f1499bce3558f107402f2c7ccf8417e7d (diff) | |
| download | xesite-599712fab9127013e2d89dadabd839c847730637.tar.xz xesite-599712fab9127013e2d89dadabd839c847730637.zip | |
rip out mage
Diffstat (limited to 'cmd/site/main.go')
| -rw-r--r-- | cmd/site/main.go | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/cmd/site/main.go b/cmd/site/main.go new file mode 100644 index 0000000..e0cc20d --- /dev/null +++ b/cmd/site/main.go @@ -0,0 +1,205 @@ +package main + +import ( + "context" + "html/template" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "time" + + "github.com/GeertJohan/go.rice" + "github.com/Xe/jsonfeed" + "github.com/Xe/ln" + "github.com/gorilla/feeds" + blackfriday "github.com/russross/blackfriday" + "github.com/tj/front" +) + +var port = os.Getenv("PORT") + +func main() { + if port == "" { + port = "29384" + } + + s, err := Build() + if err != nil { + ln.FatalErr(context.Background(), err, ln.Action("Build")) + } + + ln.Log(context.Background(), ln.F{"action": "http_listening", "port": port}) + http.ListenAndServe(":"+port, s) +} + +// Site is the parent object for https://christine.website's backend. +type Site struct { + Posts Posts + Resume template.HTML + + rssFeed *feeds.Feed + jsonFeed *jsonfeed.Feed + + mux *http.ServeMux + + templates map[string]*template.Template + tlock sync.RWMutex +} + +func (s *Site) ServeHTTP(w http.ResponseWriter, r *http.Request) { + ln.Log(r.Context(), ln.F{"action": "Site.ServeHTTP", "user_ip_address": r.RemoteAddr, "path": r.RequestURI}) + s.mux.ServeHTTP(w, r) +} + +// Build creates a new Site instance or fails. +func Build() (*Site, error) { + type postFM struct { + Title string + Date string + } + + s := &Site{ + rssFeed: &feeds.Feed{ + Title: "Christine Dodrill's Blog", + Link: &feeds.Link{Href: "https://christine.website/blog"}, + Description: "My blog posts and rants about various technology things.", + Author: &feeds.Author{Name: "Christine Dodrill", Email: "me@christine.website"}, + Created: bootTime, + Copyright: "This work is copyright Christine Dodrill. My viewpoints are my own and not the view of any employer past, current or future.", + }, + jsonFeed: &jsonfeed.Feed{ + Version: jsonfeed.CurrentVersion, + Title: "Christine Dodrill's Blog", + HomePageURL: "https://christine.website", + FeedURL: "https://christine.website/blog.json", + Description: "My blog posts and rants about various technology things.", + UserComment: "This is a JSON feed of my blogposts. For more information read: https://jsonfeed.org/version/1", + Icon: icon, + Favicon: icon, + Author: jsonfeed.Author{ + Name: "Christine Dodrill", + Avatar: icon, + }, + }, + mux: http.NewServeMux(), + templates: map[string]*template.Template{}, + } + + err := filepath.Walk("./blog/", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + fin, err := os.Open(path) + if err != nil { + return err + } + defer fin.Close() + + content, err := ioutil.ReadAll(fin) + if err != nil { + return err + } + + var fm postFM + remaining, err := front.Unmarshal(content, &fm) + if err != nil { + return err + } + + output := blackfriday.Run(remaining) + + p := &Post{ + Title: fm.Title, + Date: fm.Date, + Link: strings.Split(path, ".")[0], + Body: string(remaining), + BodyHTML: template.HTML(output), + } + + s.Posts = append(s.Posts, p) + + return nil + }) + if err != nil { + return nil, err + } + + sort.Sort(sort.Reverse(s.Posts)) + + cb, err := rice.FindBox("css") + if err != nil { + return nil, err + } + + sb, err := rice.FindBox("static") + if err != nil { + return nil, err + } + + s.Resume = template.HTML(blackfriday.Run(sb.MustBytes("resume/resume.md"))) + + for _, item := range s.Posts { + itime, _ := time.Parse("2006-01-02", item.Date) + s.rssFeed.Items = append(s.rssFeed.Items, &feeds.Item{ + Title: item.Title, + Link: &feeds.Link{Href: "https://christine.website/" + item.Link}, + Description: item.Summary, + Created: itime, + }) + + s.jsonFeed.Items = append(s.jsonFeed.Items, jsonfeed.Item{ + ID: "https://christine.website/" + item.Link, + URL: "https://christine.website/" + item.Link, + Title: item.Title, + DatePublished: itime, + ContentHTML: string(item.BodyHTML), + }) + } + + // Add HTTP routes here + s.mux.Handle("/", s.renderTemplatePage("index.html", nil)) + s.mux.Handle("/resume", s.renderTemplatePage("resume.html", s.Resume)) + s.mux.Handle("/blog", s.renderTemplatePage("blogindex.html", s.Posts)) + s.mux.Handle("/contact", s.renderTemplatePage("contact.html", nil)) + s.mux.HandleFunc("/blog.rss", s.createFeed) + s.mux.HandleFunc("/blog.atom", s.createAtom) + s.mux.HandleFunc("/blog.json", s.createJsonFeed) + s.mux.HandleFunc("/blog/", s.showPost) + s.mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(sb.HTTPBox()))) + s.mux.Handle("/css/", http.StripPrefix("/css/", http.FileServer(cb.HTTPBox()))) + + return s, nil +} + +const icon = "https://christine.website/static/img/avatar.png" + +// Post is a single blogpost. +type Post struct { + Title string `json:"title"` + Link string `json:"link"` + Summary string `json:"summary,omitifempty"` + Body string `json:"-"` + BodyHTML template.HTML `json:"body"` + Date string `json:"date"` +} + +// Posts implements sort.Interface for a slice of Post objects. +type Posts []*Post + +func (p Posts) Len() int { return len(p) } +func (p Posts) Less(i, j int) bool { + iDate, _ := time.Parse("2006-01-02", p[i].Date) + jDate, _ := time.Parse("2006-01-02", p[j].Date) + + return iDate.Unix() < jDate.Unix() +} +func (p Posts) Swap(i, j int) { p[i], p[j] = p[j], p[i] } |
