118 lines
4.3 KiB
Go
118 lines
4.3 KiB
Go
|
package website
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
"strconv"
|
||
|
|
||
|
"git.handmade.network/hmn/hmn/src/db"
|
||
|
"git.handmade.network/hmn/hmn/src/models"
|
||
|
"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)
|
||
|
}
|
||
|
|
||
|
c.Perf.StartBlock("SQL", "Fetch snippet")
|
||
|
type snippetQuery struct {
|
||
|
Owner models.User `db:"owner"`
|
||
|
Snippet models.Snippet `db:"snippet"`
|
||
|
Asset *models.Asset `db:"asset"`
|
||
|
DiscordMessage *models.DiscordMessage `db:"discord_message"`
|
||
|
}
|
||
|
snippetQueryResult, err := db.QueryOne(c.Context(), c.Conn, snippetQuery{},
|
||
|
`
|
||
|
SELECT $columns
|
||
|
FROM
|
||
|
handmade_snippet AS snippet
|
||
|
INNER JOIN auth_user AS owner ON owner.id = snippet.owner_id
|
||
|
LEFT JOIN handmade_asset AS asset ON asset.id = snippet.asset_id
|
||
|
LEFT JOIN handmade_discordmessage AS discord_message ON discord_message.id = snippet.discord_message_id
|
||
|
WHERE snippet.id = $1
|
||
|
`,
|
||
|
snippetId,
|
||
|
)
|
||
|
if err != nil {
|
||
|
if errors.Is(err, db.ErrNoMatchingRows) {
|
||
|
return FourOhFour(c)
|
||
|
} else {
|
||
|
return ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch snippet"))
|
||
|
}
|
||
|
}
|
||
|
c.Perf.EndBlock()
|
||
|
|
||
|
snippetData := snippetQueryResult.(*snippetQuery)
|
||
|
|
||
|
snippet := SnippetToTimelineItem(&snippetData.Snippet, snippetData.Asset, snippetData.DiscordMessage, &snippetData.Owner, c.Theme)
|
||
|
|
||
|
opengraph := []templates.OpenGraphItem{
|
||
|
templates.OpenGraphItem{Property: "og:site_name", Value: "Handmade.Network"},
|
||
|
templates.OpenGraphItem{Property: "og:type", Value: "article"},
|
||
|
templates.OpenGraphItem{Property: "og:url", Value: snippet.Url},
|
||
|
templates.OpenGraphItem{Property: "og:title", Value: fmt.Sprintf("Snippet by %s", snippet.OwnerName)},
|
||
|
templates.OpenGraphItem{Property: "og:description", Value: string(snippet.Description)},
|
||
|
}
|
||
|
|
||
|
if snippet.Type == templates.TimelineTypeSnippetImage {
|
||
|
opengraphImage := []templates.OpenGraphItem{
|
||
|
templates.OpenGraphItem{Property: "og:image", Value: snippet.AssetUrl},
|
||
|
templates.OpenGraphItem{Property: "og:image:width", Value: strconv.Itoa(snippet.Width)},
|
||
|
templates.OpenGraphItem{Property: "og:image:height", Value: strconv.Itoa(snippet.Height)},
|
||
|
templates.OpenGraphItem{Property: "og:image:type", Value: snippet.MimeType},
|
||
|
templates.OpenGraphItem{Name: "twitter:card", Value: "summary_large_image"},
|
||
|
}
|
||
|
opengraph = append(opengraph, opengraphImage...)
|
||
|
} else if snippet.Type == templates.TimelineTypeSnippetVideo {
|
||
|
opengraphVideo := []templates.OpenGraphItem{
|
||
|
templates.OpenGraphItem{Property: "og:video", Value: snippet.AssetUrl},
|
||
|
templates.OpenGraphItem{Property: "og:video:width", Value: strconv.Itoa(snippet.Width)},
|
||
|
templates.OpenGraphItem{Property: "og:video:height", Value: strconv.Itoa(snippet.Height)},
|
||
|
templates.OpenGraphItem{Property: "og:video:type", Value: snippet.MimeType},
|
||
|
templates.OpenGraphItem{Name: "twitter:card", Value: "player"},
|
||
|
}
|
||
|
opengraph = append(opengraph, opengraphVideo...)
|
||
|
} else if snippet.Type == templates.TimelineTypeSnippetAudio {
|
||
|
opengraphAudio := []templates.OpenGraphItem{
|
||
|
templates.OpenGraphItem{Property: "og:audio", Value: snippet.AssetUrl},
|
||
|
templates.OpenGraphItem{Property: "og:audio:type", Value: snippet.MimeType},
|
||
|
templates.OpenGraphItem{Name: "twitter:card", Value: "player"},
|
||
|
}
|
||
|
opengraph = append(opengraph, opengraphAudio...)
|
||
|
} else if snippet.Type == templates.TimelineTypeSnippetYoutube {
|
||
|
opengraphYoutube := []templates.OpenGraphItem{
|
||
|
templates.OpenGraphItem{Property: "og:video", Value: fmt.Sprintf("https://youtube.com/watch?v=%s", snippet.YoutubeID)},
|
||
|
templates.OpenGraphItem{Name: "twitter:card", Value: "player"},
|
||
|
}
|
||
|
opengraph = append(opengraph, opengraphYoutube...)
|
||
|
}
|
||
|
|
||
|
baseData := getBaseData(c)
|
||
|
baseData.OpenGraphItems = opengraph
|
||
|
var res ResponseData
|
||
|
err = res.WriteTemplate("snippet.html", SnippetData{
|
||
|
BaseData: baseData,
|
||
|
Snippet: snippet,
|
||
|
}, c.Perf)
|
||
|
if err != nil {
|
||
|
return ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render snippet template"))
|
||
|
}
|
||
|
return res
|
||
|
}
|