hmn/src/website/snippet.go

99 lines
3.3 KiB
Go

package website
import (
"errors"
"fmt"
"net/http"
"strconv"
"git.handmade.network/hmn/hmn/src/db"
"git.handmade.network/hmn/hmn/src/hmndata"
"git.handmade.network/hmn/hmn/src/oops"
"git.handmade.network/hmn/hmn/src/templates"
)
type SnippetData struct {
templates.BaseData
Snippet templates.TimelineItem
}
func Snippet(c *RequestContext) ResponseData {
snippetId := -1
snippetIdStr, found := c.PathParams["snippetid"]
if found && snippetIdStr != "" {
var err error
if snippetId, err = strconv.Atoi(snippetIdStr); err != nil {
return FourOhFour(c)
}
}
if snippetId < 1 {
return FourOhFour(c)
}
s, err := hmndata.FetchSnippet(c.Context(), c.Conn, c.CurrentUser, snippetId, hmndata.SnippetQuery{})
if err != nil {
if errors.Is(err, db.NotFound) {
return FourOhFour(c)
} else {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch snippet"))
}
}
c.Perf.EndBlock()
snippet := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Tags, s.Owner, c.Theme)
opengraph := []templates.OpenGraphItem{
{Property: "og:site_name", Value: "Handmade.Network"},
{Property: "og:type", Value: "article"},
{Property: "og:url", Value: snippet.Url},
{Property: "og:title", Value: fmt.Sprintf("Snippet by %s", snippet.OwnerName)},
{Property: "og:description", Value: string(snippet.Description)},
}
if len(snippet.EmbedMedia) > 0 {
media := snippet.EmbedMedia[0]
switch media.Type {
case templates.TimelineItemMediaTypeImage:
opengraph = append(opengraph,
templates.OpenGraphItem{Property: "og:image", Value: media.AssetUrl},
templates.OpenGraphItem{Property: "og:image:width", Value: strconv.Itoa(media.Width)},
templates.OpenGraphItem{Property: "og:image:height", Value: strconv.Itoa(media.Height)},
templates.OpenGraphItem{Property: "og:image:type", Value: media.MimeType},
templates.OpenGraphItem{Name: "twitter:card", Value: "summary_large_image"},
)
case templates.TimelineItemMediaTypeVideo:
opengraph = append(opengraph,
templates.OpenGraphItem{Property: "og:video", Value: media.AssetUrl},
templates.OpenGraphItem{Property: "og:video:width", Value: strconv.Itoa(media.Width)},
templates.OpenGraphItem{Property: "og:video:height", Value: strconv.Itoa(media.Height)},
templates.OpenGraphItem{Property: "og:video:type", Value: media.MimeType},
templates.OpenGraphItem{Name: "twitter:card", Value: "player"},
)
case templates.TimelineItemMediaTypeAudio:
opengraph = append(opengraph,
templates.OpenGraphItem{Property: "og:audio", Value: media.AssetUrl},
templates.OpenGraphItem{Property: "og:audio:type", Value: media.MimeType},
templates.OpenGraphItem{Name: "twitter:card", Value: "player"},
)
}
opengraph = append(opengraph, media.ExtraOpenGraphItems...)
}
baseData := getBaseData(
c,
fmt.Sprintf("Snippet by %s", snippet.OwnerName),
[]templates.Breadcrumb{{Name: snippet.OwnerName, Url: snippet.OwnerUrl}},
)
baseData.OpenGraphItems = opengraph // NOTE(asaf): We're overriding the defaults on purpose.
var res ResponseData
err = res.WriteTemplate("snippet.html", SnippetData{
BaseData: baseData,
Snippet: snippet,
}, c.Perf)
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render snippet template"))
}
return res
}