69 lines
1.9 KiB
Go
69 lines
1.9 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/szabadpalya/api/internal/hu"
|
|
"github.com/szabadpalya/api/internal/ogimage"
|
|
"github.com/szabadpalya/api/internal/store"
|
|
)
|
|
|
|
// ogImage serves the per-campaign share card. A crawler fetches this once per
|
|
// share and caches it for a long time, so an hour of staleness is fine and the
|
|
// header keeps us from redrawing on every Facebook refresh.
|
|
func (s *Server) ogImage(c *gin.Context) {
|
|
campaign, err := s.store.GetCampaignBySlug(c.Request.Context(), c.Param("slug"))
|
|
if errors.Is(err, store.ErrNotFound) {
|
|
png, err := ogimage.Fallback()
|
|
if err != nil {
|
|
s.fail(c, err)
|
|
return
|
|
}
|
|
c.Header("Cache-Control", "public, max-age=300")
|
|
c.Data(http.StatusOK, "image/png", png)
|
|
return
|
|
}
|
|
if err != nil {
|
|
s.fail(c, err)
|
|
return
|
|
}
|
|
|
|
pct := hu.ProgressPct(campaign.Raised, campaign.Goal)
|
|
// The bar is scaled so an overfunded campaign still shows its 100% mark
|
|
// rather than a bar that is simply full.
|
|
scale := max(100, pct)
|
|
card := ogimage.Card{
|
|
Title: campaign.Title,
|
|
Category: campaign.Category,
|
|
Creator: campaign.Creator.Name + " · " + campaign.Creator.Location,
|
|
Raised: hu.FormatHUF(campaign.Raised),
|
|
GoalNote: fmt.Sprintf("a %s-os célból", hu.FormatHUF(campaign.Goal)),
|
|
Percent: fmt.Sprintf("%d%%", pct),
|
|
Fraction: float64(min(pct, 100)) / float64(scale),
|
|
Backers: hu.FormatNumber(campaign.Backers) + " támogató",
|
|
Deadline: deadlineLabel(campaign, s.store.Budapest),
|
|
}
|
|
if pct > 100 {
|
|
card.Over = float64(pct-100) / float64(scale)
|
|
}
|
|
|
|
png, err := ogimage.Render(card)
|
|
if err != nil {
|
|
s.fail(c, err)
|
|
return
|
|
}
|
|
c.Header("Cache-Control", "public, max-age=3600")
|
|
c.Data(http.StatusOK, "image/png", png)
|
|
}
|
|
|
|
func deadlineLabel(campaign *store.Campaign, loc *time.Location) string {
|
|
if campaign.Status == "lezart" {
|
|
return "lezárult"
|
|
}
|
|
return fmt.Sprintf("%d nap van hátra", hu.DaysLeft(campaign.EndsAt, loc, time.Now()))
|
|
}
|