summaryrefslogtreecommitdiffci
path: root/internal/router/lang-blog-title.go
blob: 6e80671a2a78044fad84d911794e6245ac5f69b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package router

import (
	"bytes"
	"fmt"
	"html/template"
	"log/slog"
	"strconv"
	"strings"

	"github.com/SayaAndy/saya-today-web/config"
	"github.com/SayaAndy/saya-today-web/internal/b2"
	"github.com/SayaAndy/saya-today-web/internal/frontmatter"
	"github.com/SayaAndy/saya-today-web/locale"
	"github.com/gofiber/fiber/v2"
	"github.com/yuin/goldmark"
)

func init() {
	tm.Add("blog-page", "views/layouts/general-page.html", "views/pages/blog-page.html")
}

func Lang_Blog_Title(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client, md goldmark.Markdown) func(c *fiber.Ctx) error {
	return func(c *fiber.Ctx) error {
		ip := c.IP()
		slog.Debug("client entering blog page", slog.String("ip", ip), slog.String("page", c.Path()))

		lang := c.Params("lang")
		for _, availableLang := range langs {
			if availableLang.Name == lang {
				goto langIsAvailable
			}
		}
		return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language", lang))

	langIsAvailable:
		metadata, parsedMarkdown, err := readBlogPost(md, b2Client, lang+"/"+c.Params("title"))
		if err != nil {
			c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
			return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("failed to find '%s' post", c.Params("title")))
		}

		geolocationParts := strings.Split(metadata.Geolocation, " ")
		var x, y, areaError string
		if len(geolocationParts) >= 2 {
			x = geolocationParts[0]
			y = geolocationParts[1]
		}
		if len(geolocationParts) >= 3 {
			areaError = geolocationParts[2]
		}

		content, err := tm.Render("blog-page", fiber.Map{
			"Title":                 metadata.Title,
			"PublishedDate":         metadata.PublishedTime.Format("2006-01-02 15:04:05 -07:00"),
			"PublishedYear":         strconv.Itoa(metadata.PublishedTime.Year()),
			"ParsedMarkdown":        template.HTML(parsedMarkdown),
			"MapLocationX":          x,
			"MapLocationY":          y,
			"MapLocationAreaMeters": areaError,
			"Lang":                  lang,
			"QueryString":           string(c.Request().URI().QueryString()),
		})
		if err != nil {
			slog.Warn("failed to generate page", slog.String("page", "/"+lang+"/blog/"+c.Params("title")), slog.String("error", err.Error()))
			c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
			return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate page")
		}

		return c.Type("html").Send(content)
	}
}

func readBlogPost(md goldmark.Markdown, b2Client *b2.B2Client, sourceName string) (metadata *frontmatter.Metadata, html string, err error) {
	metadata, markdown, err := b2Client.ReadFrontmatter(sourceName + ".md")
	if err != nil {
		return nil, "", fmt.Errorf("failed to read a frontmatter file: %w", err)
	}

	var buf bytes.Buffer
	if err := md.Convert(markdown, &buf); err != nil {
		return nil, "", fmt.Errorf("convert source context from md to html: %w", err)
	}

	return metadata, buf.String(), nil
}