summaryrefslogtreecommitdiffci
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--internal/router/api-v1-like.go117
-rw-r--r--internal/router/client-cache.go82
-rw-r--r--internal/router/lang-blog-title.go1
-rw-r--r--main.go2
-rw-r--r--static/input.css36
-rw-r--r--views/layouts/general-page.html14
-rw-r--r--views/pages/blog-catalogue.html2
-rw-r--r--views/pages/blog-page.html6
-rw-r--r--views/pages/global-map.html2
-rw-r--r--views/partials/blog-page-like-button.html6
10 files changed, 27 insertions, 241 deletions
diff --git a/internal/router/api-v1-like.go b/internal/router/api-v1-like.go
deleted file mode 100644
index 1732c77..0000000
--- a/internal/router/api-v1-like.go
+++ /dev/null
@@ -1,117 +0,0 @@
-package router
-
-import (
- "fmt"
- "log/slog"
- "net/url"
- "strconv"
- "strings"
-
- "github.com/SayaAndy/saya-today-web/internal/b2"
- "github.com/gofiber/fiber/v2"
-)
-
-func init() {
- tm.Add("blog-page-like-button", "views/partials/blog-page-like-button.html")
-}
-
-func Api_V1_Like_Put(b2 *b2.B2Client) func(c *fiber.Ctx) error {
- return func(c *fiber.Ctx) error {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
-
- referer := c.Get("Referer", "")
- if referer == "" {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is empty")
- }
- urlStruct, err := url.ParseRequestURI(referer)
- if err != nil {
- return c.Status(fiber.ErrBadRequest.Code).SendString(fmt.Sprintf("'Referer' header is invalid: %s", err.Error()))
- }
-
- path := urlStruct.EscapedPath()
- pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) != 3 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/blog/{page}'")
- }
-
- lang, page := pathParts[0], pathParts[2]
-
- pageLink := lang + "/" + page + ".md"
- if pages, _ := b2.Scan(pageLink); len(pages) == 0 {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server did not find '%s' article", pageLink))
- }
-
- ip := c.IP()
- newLikeStatus, err := strconv.ParseBool(c.FormValue("like", "true"))
- if err != nil {
- return c.Status(fiber.ErrBadRequest.Code).SendString("invalid 'like' value")
- }
-
- if newLikeStatus {
- CCache.LikeOn(ip, page)
- } else {
- CCache.LikeOff(ip, page)
- }
-
- slog.Debug("someone pressed the like button!", slog.String("ip", ip), slog.String("page", page), slog.String("new_like_status", fmt.Sprint(newLikeStatus)))
- if c.Get("HX-Request", "false") == "true" {
- content, err := tm.Render("blog-page-like-button", fiber.Map{
- "Liked": newLikeStatus,
- })
- if err != nil {
- slog.Warn("failed to generate div", slog.String("path", path), slog.String("error", err.Error()))
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate div")
- }
- c.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8)
- return c.Status(fiber.StatusOK).Send(content)
- }
-
- return c.Status(fiber.StatusOK).SendString(fmt.Sprint(newLikeStatus))
- }
-}
-
-func Api_V1_Like_Get(b2 *b2.B2Client) func(c *fiber.Ctx) error {
- return func(c *fiber.Ctx) error {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
-
- referer := c.Get("Referer", "")
- if referer == "" {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is empty")
- }
- urlStruct, err := url.ParseRequestURI(referer)
- if err != nil {
- return c.Status(fiber.ErrBadRequest.Code).SendString(fmt.Sprintf("'Referer' header is invalid: %s", err.Error()))
- }
-
- path := urlStruct.EscapedPath()
- pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) != 3 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/blog/{page}'")
- }
-
- lang, page := pathParts[0], pathParts[2]
-
- pageLink := lang + "/" + page + ".md"
- if pages, _ := b2.Scan(pageLink); len(pages) == 0 {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server did not find '%s' article", pageLink))
- }
-
- ip := c.IP()
- likeStatus := CCache.GetLikeStatus(ip, page)
-
- slog.Debug("someone requested the like status!", slog.String("ip", ip), slog.String("page", page), slog.Bool("like_status", likeStatus))
- if c.Get("HX-Request", "false") == "true" {
- content, err := tm.Render("blog-page-like-button", fiber.Map{
- "Liked": likeStatus,
- })
- if err != nil {
- slog.Warn("failed to generate div", slog.String("path", path), slog.String("error", err.Error()))
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate div")
- }
- c.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8)
- return c.Status(fiber.StatusOK).Send(content)
- }
-
- return c.Status(fiber.StatusOK).SendString(fmt.Sprint(likeStatus))
- }
-}
diff --git a/internal/router/client-cache.go b/internal/router/client-cache.go
index 3104a66..a4a0cc2 100644
--- a/internal/router/client-cache.go
+++ b/internal/router/client-cache.go
@@ -9,90 +9,40 @@ import (
)
type ClientCache struct {
- hashMap map[string]string
- mutexLikeMap map[string]*sync.Mutex
- mutexHashMap map[string]*sync.Mutex
- likePageMap map[string]map[string]struct{}
- salt []byte
+ hashMap map[string][]byte
+ mutexMap map[string]*sync.Mutex
+ salt []byte
}
var CCache *ClientCache
func NewClientCache(salt []byte) *ClientCache {
return &ClientCache{
- hashMap: make(map[string]string),
- mutexLikeMap: make(map[string]*sync.Mutex),
- mutexHashMap: make(map[string]*sync.Mutex),
- likePageMap: make(map[string]map[string]struct{}),
- salt: salt,
+ hashMap: make(map[string][]byte),
+ mutexMap: make(map[string]*sync.Mutex),
+ salt: salt,
}
}
-func (c *ClientCache) GetHash(id string) string {
+func (c *ClientCache) GetHash(id string) []byte {
+
if val, ok := c.hashMap[id]; ok {
- slog.Debug("gave an old hash", slog.String("hash", val))
+ slog.Debug("gave an old hash", slog.String("hash", base64.RawStdEncoding.EncodeToString(val)))
return val
}
- if _, ok := c.mutexHashMap[id]; !ok {
- c.mutexHashMap[id] = &sync.Mutex{}
+ if _, ok := c.mutexMap[id]; !ok {
+ c.mutexMap[id] = &sync.Mutex{}
}
- c.mutexHashMap[id].Lock()
- defer c.mutexHashMap[id].Unlock()
+ c.mutexMap[id].Lock()
+ defer c.mutexMap[id].Unlock()
if val, ok := c.hashMap[id]; ok {
- slog.Debug("gave a newly generated hash", slog.String("hash", val))
+ slog.Debug("gave a newly generated hash", slog.String("hash", base64.RawStdEncoding.EncodeToString(val)))
return val
}
- c.hashMap[id] = base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(id), c.salt, 1, 64*1024, 4, 32))
- slog.Debug("generated hash", slog.String("hash", c.hashMap[id]))
+ c.hashMap[id] = argon2.IDKey([]byte(id), c.salt, 1, 64*1024, 4, 32)
+ slog.Debug("generated hash", slog.String("hash", base64.RawStdEncoding.EncodeToString(c.hashMap[id])))
return c.hashMap[id]
}
-
-func (c *ClientCache) GetLikeStatus(id string, page string) bool {
- if _, ok := c.likePageMap[page]; !ok {
- return false
- }
- _, ok := c.likePageMap[page][c.GetHash(id)]
- return ok
-}
-
-func (c *ClientCache) LikeOn(id string, page string) (alreadyLiked bool) {
- if _, ok := c.mutexLikeMap[id]; !ok {
- c.mutexLikeMap[id] = &sync.Mutex{}
- }
- c.mutexLikeMap[id].Lock()
- defer c.mutexLikeMap[id].Unlock()
-
- hash := c.GetHash(id)
-
- if userSet, ok := c.likePageMap[page]; ok {
- _, alreadyLiked = userSet[hash]
- c.likePageMap[page][hash] = struct{}{}
- return
- }
-
- c.likePageMap[page] = make(map[string]struct{})
- c.likePageMap[page][hash] = struct{}{}
- return
-}
-
-func (c *ClientCache) LikeOff(id string, page string) (alreadyUnliked bool) {
- if _, ok := c.mutexLikeMap[id]; !ok {
- c.mutexLikeMap[id] = &sync.Mutex{}
- }
- c.mutexLikeMap[id].Lock()
- defer c.mutexLikeMap[id].Unlock()
-
- if _, ok := c.likePageMap[page]; !ok {
- return true
- }
- hash := c.GetHash(id)
- if _, ok := c.likePageMap[page][hash]; !ok {
- return true
- }
-
- delete(c.likePageMap[page], hash)
- return false
-}
diff --git a/internal/router/lang-blog-title.go b/internal/router/lang-blog-title.go
index bafb0d2..5b80ec8 100644
--- a/internal/router/lang-blog-title.go
+++ b/internal/router/lang-blog-title.go
@@ -24,6 +24,7 @@ func Lang_Blog_Title(l map[string]*locale.LocaleConfig, langs []string, b2Client
return func(c *fiber.Ctx) error {
ip := c.IP()
slog.Debug("client entering blog page", slog.String("ip", ip), slog.String("page", c.Path()))
+ go CCache.GetHash(ip)
lang := c.Params("lang")
if !slices.Contains(langs, lang) {
diff --git a/main.go b/main.go
index 1853721..9f95c04 100644
--- a/main.go
+++ b/main.go
@@ -88,8 +88,6 @@ func main() {
app.Get("/:lang/blog/:title", router.Lang_Blog_Title(localization, availableLanguages, b2Client, md))
app.Get("/api/v1/tz", router.Api_V1_TZ())
app.Get("/api/v1/blog-search", router.Api_V1_BlogSearch(localization, availableLanguages, b2Client))
- app.Get("/api/v1/like", router.Api_V1_Like_Get(b2Client))
- app.Put("/api/v1/like", router.Api_V1_Like_Put(b2Client))
app.Static("/", "./static")
diff --git a/static/input.css b/static/input.css
index 18910eb..9f834a6 100644
--- a/static/input.css
+++ b/static/input.css
@@ -139,18 +139,10 @@ a:hover {
color: var(--main-medium-color);
}
-.text-main-light {
- color: var(--main-light-color);
-}
-
.text-background-dark {
color: var(--background-dark-color);
}
-.text-background-light {
- color: var(--background-dark-color);
-}
-
.text-secondary {
color: var(--secondary-color);
}
@@ -159,14 +151,6 @@ a:hover {
background-color: var(--main-dark-color);
}
-.bg-main-medium {
- background-color: var(--main-medium-color);
-}
-
-.bg-main-light {
- background-color: var(--main-light-color);
-}
-
.bg-background-dark {
background-color: var(--background-dark-color);
}
@@ -183,26 +167,6 @@ a:hover {
border-color: var(--main-medium-color);
}
-.border-main-light {
- border-color: var(--main-light-color);
-}
-
-.border-background-dark {
- border-color: var(--background-dark-color);
-}
-
-.border-background-light {
- border-color: var(--background-light-color);
-}
-
-.border-inset {
- border-style: inset;
-}
-
-.border-outset {
- border-style: outset;
-}
-
.desktop-sidebar-custom {
width: 5vw;
background-size: calc(var(--squares-and-triangles-background-size) * 1vw);
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index 9885d66..cd19bd0 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -8,7 +8,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,200;1,300;1,400;1,500;1,600;1,700;1,800&family=Patua+One&display=swap" rel="stylesheet">
- {{ block "top-embeds" . }}{{ end }}
+ {{ block "header" . }}{{ end }}
<link href="/output.css" rel="stylesheet">
</head>
@@ -66,19 +66,17 @@
<p class="text-[2vmax] font-spectral italic text-left mt-auto">{{ .Title }}</p>
<p id="published-date" class="grow text-[1.5vmax] font-spectral text-secondary text-right mt-auto">{{ .PublishedDate }}</p>
</div>
- {{ block "header" . }}{{ end }}
<hr class="border-t-4 border-dotted border-main-dark mb-[0.8vmin]">
{{ block "body" . }}{{ end }}
<div class="flex flex-row mt-[0.8vmin] mb-[0.4vmin]">
- {{ block "footer" . }}{{ end }}
- <p class="grow content-center text-[1vmax]/[1] font-spectral italic text-right text-secondary mr-2">
+ <p class="grow text-[0.8vmax]/[0.9] font-spectral italic text-right text-secondary mr-2">
All the photos on <a href="https://saya.today/">saya.today</a> are licensed under <a href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a> by <a href="https://t.me/EarlInisMona">Saya Andy</a> © {{ .PublishedYear }}
</p>
- <img class="max-w-[1vmax] max-h-[1vmax] self-center" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="CC">
- <img class="max-w-[1vmax] max-h-[1vmax] self-center" src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="BY">
- <img class="max-w-[1vmax] max-h-[1vmax] self-center" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg" alt="SA">
+ <img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="" style="max-width:1.2vh; max-height:1.2vh;">
+ <img src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="" style="max-width:1.2vh; max-height:1.2vh;">
+ <img src="https://mirrors.creativecommons.org/presskit/icons/sa.svg" alt="" style="max-width:1.2vh; max-height:1.2vh;">
</div>
<hr class="border-t-4 border-dotted border-main-dark mb-[0.8vmin]">
@@ -211,7 +209,7 @@
});
</script>
- {{ block "bottom-embeds" . }}{{ end }}
+ {{ block "footer" . }}{{ end }}
</body>
</html>
diff --git a/views/pages/blog-catalogue.html b/views/pages/blog-catalogue.html
index 25b0685..9fa8ea7 100644
--- a/views/pages/blog-catalogue.html
+++ b/views/pages/blog-catalogue.html
@@ -56,7 +56,7 @@
</div>
{{ end }}
-{{ define "bottom-embeds" }}
+{{ define "footer" }}
<script>
function selectAll() {
const tagsContainers = document.querySelectorAll('form.tags-list');
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html
index 83860d7..755744d 100644
--- a/views/pages/blog-page.html
+++ b/views/pages/blog-page.html
@@ -1,4 +1,4 @@
-{{ define "top-embeds" }}
+{{ define "header" }}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/2.8.3/css/lightgallery.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/2.8.3/css/lg-zoom.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/2.8.3/css/lg-thumbnail.min.css">
@@ -26,10 +26,6 @@
{{ end }}
{{ define "footer" }}
-<div hx-get="/api/v1/like" hx-target="this" hx-swap="outerHTML" hx-trigger="load"></div>
-{{ end }}
-
-{{ define "bottom-embeds" }}
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/lightgallery.min.js"></script>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/plugins/lg-zoom.min.js"></script>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/plugins/lg-thumbnail.min.js"></script>
diff --git a/views/pages/global-map.html b/views/pages/global-map.html
index 569166f..6185076 100644
--- a/views/pages/global-map.html
+++ b/views/pages/global-map.html
@@ -263,5 +263,7 @@
});
</script>
+ {{ block "footer" . }}{{ end }}
+
</body>
</html>
diff --git a/views/partials/blog-page-like-button.html b/views/partials/blog-page-like-button.html
deleted file mode 100644
index 50a9d7a..0000000
--- a/views/partials/blog-page-like-button.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<button
- hx-put="/api/v1/like" hx-vals='{"like": {{ not .Liked }}}' hx-target="this" hx-swap="outerHTML" hx-trigger="click"
- class="text-[0.8vmax]/[0.9] font-spectral text-left px-[0.4vmax] py-[0.2vmax] {{ if .Liked }}bg-main-light hover:bg-main-medium{{ else }}bg-main-dark hover:bg-main-medium{{ end }} text-background-dark cursor-pointer {{ if .Liked }}border-inset{{ else }}border-outset{{ end }} border-[0.3vmax] border-background-dark">
- <i class="fas fa-thumbs-up w-[0.8vmax] h-[0.8vmax] mr-[0.4vmax]"></i>
- <span>Нраица!</span>
-</button> \ No newline at end of file