Add text preview for Facebook / Instagram

This commit is contained in:
dtonon
2024-09-12 12:30:20 +02:00
parent 7a054f9d65
commit a731bd27f5
2 changed files with 34 additions and 14 deletions

View File

@@ -107,12 +107,19 @@ func drawImage(
paddingLeft := 25 paddingLeft := 25
gradientRectHeight := 140 gradientRectHeight := 140
barHeight := 70 barHeight := 70
barScale := 1.0
switch style { switch style {
case StyleTelegram: case StyleTelegram:
paddingLeft += 10 paddingLeft += 10
width -= 10 width -= 10
case StyleTwitter: case StyleTwitter:
height = width * 268 / 512 height = width * 268 / 512
case StyleFacebook:
height = width * 355 / 680
paddingLeft = 180
barScale = 0.55
barHeight = int(float64(barHeight) * barScale)
fontSize = 18
} }
img := gg.NewContext(width, height) img := gg.NewContext(width, height)
@@ -145,7 +152,7 @@ func drawImage(
fontData, _ := fonts.ReadFile("fonts/NotoSans.ttf") fontData, _ := fonts.ReadFile("fonts/NotoSans.ttf")
ttf, _ := truetype.Parse(fontData) ttf, _ := truetype.Parse(fontData)
img.SetFontFace(truetype.NewFace(ttf, &truetype.Options{ img.SetFontFace(truetype.NewFace(ttf, &truetype.Options{
Size: 6, Size: (6 * barScale),
DPI: 260, DPI: 260,
Hinting: xfont.HintingFull, Hinting: xfont.HintingFull,
})) }))
@@ -168,46 +175,57 @@ func drawImage(
// draw author's name // draw author's name
authorTextX := paddingLeft authorTextX := paddingLeft
picHeight := barHeight - 20
if metadata.Picture != "" { if metadata.Picture != "" {
authorImage, err := fetchImageFromURL(metadata.Picture) authorImage, err := fetchImageFromURL(metadata.Picture)
if err == nil { if err == nil {
resizedAuthorImage := resize.Resize(uint(barHeight-20), uint(barHeight-20), roundImage(cropToSquare(authorImage)), resize.Lanczos3) resizedAuthorImage := resize.Resize(uint(barHeight-20), uint(picHeight), roundImage(cropToSquare(authorImage)), resize.Lanczos3)
img.DrawImage(resizedAuthorImage, paddingLeft, height-barHeight+10) img.DrawImage(resizedAuthorImage, paddingLeft, height-barHeight+10)
authorTextX += 65
} }
} }
authorTextY := height - barHeight + 15
authorMaxWidth := width/2.0 - paddingLeft*2 authorTextY := height - barHeight + (barHeight-picHeight)/2 + 4
if style == StyleFacebook {
authorTextY = height - barHeight + (barHeight-picHeight)/2 - 5
authorTextX += 25
} else {
authorTextX += 65
}
img.SetColor(color.White) img.SetColor(color.White)
textImg, _ = drawParagraphs([]string{metadata.ShortName()}, fontSize, width, barHeight) textImg, _ = drawParagraphs([]string{metadata.ShortName()}, fontSize, width, barHeight)
img.DrawImage(textImg, authorTextX, authorTextY) img.DrawImage(textImg, authorTextX, authorTextY)
// a gradient to cover too long names // a gradient to cover too long names
authorMaxWidth := width/2.0 - paddingLeft*2
img.SetColor(BAR_BACKGROUND) img.SetColor(BAR_BACKGROUND)
img.DrawRectangle(float64(authorTextX+authorMaxWidth), float64(height-barHeight), float64(width-authorTextX-authorMaxWidth), float64(barHeight)) img.DrawRectangle(float64(paddingLeft+authorTextX+authorMaxWidth), float64(height-barHeight), float64(width-authorTextX-authorMaxWidth), float64(barHeight))
gradientLength := 60 gradientLength := 60
for x := 0; x < gradientLength; x++ { for x := 0; x < gradientLength; x++ {
alpha := uint8(255 - 255*(math.Pow(float64(x)/float64(gradientLength), 2))) alpha := uint8(255 - 255*(math.Pow(float64(x)/float64(gradientLength), 2)))
img.SetRGBA255(int(BAR_BACKGROUND.R), int(BAR_BACKGROUND.G), int(BAR_BACKGROUND.B), int(alpha)) img.SetRGBA255(int(BAR_BACKGROUND.R), int(BAR_BACKGROUND.G), int(BAR_BACKGROUND.B), int(alpha))
img.DrawRectangle(float64(authorTextX+authorMaxWidth-x), float64(height-barHeight), 1, float64(barHeight)) img.DrawRectangle(float64(paddingLeft+authorTextX+authorMaxWidth-x), float64(height-barHeight), 1, float64(barHeight))
img.Fill() img.Fill()
} }
// bottom bar logo // bottom bar logo
logo, _ := static.ReadFile("static/logo.png") logo, _ := static.ReadFile("static/logo.png")
stampImg, _ := png.Decode(bytes.NewBuffer(logo)) stampImg, _ := png.Decode(bytes.NewBuffer(logo))
stampWidth := stampImg.Bounds().Dx() stampRatio := float64(stampImg.Bounds().Dx() / stampImg.Bounds().Dy())
stampHeight := stampImg.Bounds().Dy() stampHeight := float64(barHeight) * 0.45
stampX := width - stampWidth - paddingLeft stampWidth := stampHeight * stampRatio
stampY := height - stampHeight - 20 resizedStampImg := resize.Resize(uint(stampWidth), uint(stampHeight), stampImg, resize.Lanczos3)
img.DrawImage(stampImg, stampX, stampY) stampX := width - int(stampWidth) - paddingLeft
stampY := height - barHeight + (barHeight-int(stampHeight))/2
img.DrawImage(resizedStampImg, stampX, stampY)
// Draw event date // Draw event date
layout := "2006-01-02 15:04:05" layout := "2006-01-02 15:04:05"
parsedTime, _ := time.Parse(layout, date) parsedTime, _ := time.Parse(layout, date)
formattedDate := parsedTime.Format("Jan 02, 2006") formattedDate := parsedTime.Format("Jan 02, 2006")
img.SetColor(color.RGBA{160, 160, 160, 255}) img.SetColor(color.RGBA{160, 160, 160, 255})
img.DrawStringWrapped(formattedDate, float64(width-paddingLeft-stampWidth-260), float64(height-barHeight+22), 0, 0, float64(240), 1.5, gg.AlignRight) img.DrawStringWrapped(formattedDate, float64(width-paddingLeft-int(stampWidth)-250), float64(height-barHeight+(barHeight-int(stampHeight))/2)+3, 0, 0, float64(240), 1.5, gg.AlignRight)
return img.Image(), nil return img.Image(), nil
} }

View File

@@ -133,6 +133,7 @@ type Style string
const ( const (
StyleTelegram Style = "telegram" StyleTelegram Style = "telegram"
StyleTwitter = "twitter" StyleTwitter = "twitter"
StyleFacebook = "facebook" // Both Facebook and Instagram
StyleIOS = "ios" StyleIOS = "ios"
StyleAndroid = "android" StyleAndroid = "android"
StyleMattermost = "mattermost" StyleMattermost = "mattermost"
@@ -152,12 +153,13 @@ func getPreviewStyle(r *http.Request) Style {
ua := strings.ToLower(r.Header.Get("User-Agent")) ua := strings.ToLower(r.Header.Get("User-Agent"))
accept := r.Header.Get("Accept") accept := r.Header.Get("Accept")
switch { switch {
case strings.Contains(ua, "telegrambot"): case strings.Contains(ua, "telegrambot"):
return StyleTelegram return StyleTelegram
case strings.Contains(ua, "twitterbot"): case strings.Contains(ua, "twitterbot"):
return StyleTwitter return StyleTwitter
case strings.Contains(ua, "facebookexternalhit"):
return StyleFacebook
case strings.Contains(ua, "iphone"), strings.Contains(ua, "ipad"), strings.Contains(ua, "ipod"): case strings.Contains(ua, "iphone"), strings.Contains(ua, "ipad"), strings.Contains(ua, "ipod"):
return StyleIOS return StyleIOS
case strings.Contains(ua, "android"): case strings.Contains(ua, "android"):