tweetsvg/main.go

157 lines
4.0 KiB
Go
Raw Normal View History

2021-02-18 18:32:36 +00:00
package main
import (
"bytes"
"encoding/base64"
"fmt"
"html/template"
2021-02-22 19:29:31 +00:00
"io/ioutil"
2021-02-18 18:32:36 +00:00
"log"
2021-02-22 19:29:31 +00:00
"math"
2021-02-18 18:32:36 +00:00
"net/http"
"os"
"regexp"
2021-02-18 18:32:36 +00:00
"strconv"
"strings"
"time"
"github.com/ChimeraCoder/anaconda"
2021-02-22 19:29:31 +00:00
strip "github.com/grokify/html-strip-tags-go"
2021-02-18 18:55:15 +00:00
"github.com/joho/godotenv"
2021-02-18 18:32:36 +00:00
)
var (
api *anaconda.TwitterApi
tweetDateLayout = "Mon Jan 2 15:04:05 -0700 2006"
2021-02-18 18:55:15 +00:00
port string
accessToken string
accessTokenSecret string
consumerKey string
consumerSecret string
2021-02-18 18:32:36 +00:00
)
2021-02-18 18:55:15 +00:00
func init() {
godotenv.Load(os.Getenv("DOTENV_DIR") + ".env")
port = os.Getenv("PORT")
accessToken = os.Getenv("ACCESS_TOKEN")
accessTokenSecret = os.Getenv("ACCESS_TOKEN_SECRET")
consumerKey = os.Getenv("CONSUMER_KEY")
consumerSecret = os.Getenv("CONSUMER_SECRET")
}
2021-02-18 18:32:36 +00:00
func main() {
if accessToken == "" || accessTokenSecret == "" || consumerKey == "" || consumerSecret == "" {
panic("Missing Twitter credentials")
}
api = anaconda.NewTwitterApiWithCredentials(accessToken, accessTokenSecret, consumerKey, consumerSecret)
if port == "" {
port = "8080"
}
2021-02-22 19:29:31 +00:00
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if len(r.URL.Path) > 1 {
getTweet(w, r)
} else {
body, _ := ioutil.ReadFile("index.html")
w.Write(body)
}
})
2021-02-18 18:32:36 +00:00
fmt.Println("Server started at port " + port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
func getTweet(w http.ResponseWriter, r *http.Request) {
id := strings.ReplaceAll(r.URL.Path, "/", "")
i, err := strconv.ParseInt(id, 10, 64)
if err != nil {
w.WriteHeader(400)
return
}
tweet, err := api.GetTweet(i, nil)
if err != nil {
w.WriteHeader(404)
return
}
re := regexp.MustCompile(`[\x{1F300}-\x{1F6FF}]`)
emojis := re.FindAllString(tweet.FullText, -1)
emojiCount := 0
for _, emoji := range emojis {
emojiCount += len([]byte(emoji)) - 1
}
tweet.FullText = tweet.FullText[tweet.DisplayTextRange[0] : tweet.DisplayTextRange[1]+emojiCount]
for _, user := range tweet.Entities.User_mentions {
2021-02-20 16:26:08 +00:00
tweet.FullText = strings.ReplaceAll(tweet.FullText, "@"+user.Screen_name, fmt.Sprintf("<a rel=\"noopener\" target=\"_blank\" href=\"https://twitter.com/%s/\">@%s</a>", user.Screen_name, user.Screen_name))
}
for _, url := range tweet.Entities.Urls {
2021-02-20 16:26:08 +00:00
tweet.FullText = strings.ReplaceAll(tweet.FullText, url.Url, fmt.Sprintf("<a rel=\"noopener\" target=\"_blank\" href=\"https://twitter.com/%s/\">%s</a>", url.Expanded_url, url.Display_url))
}
for _, hashtag := range tweet.Entities.Hashtags {
2021-02-20 16:26:08 +00:00
tweet.FullText = strings.ReplaceAll(tweet.FullText, "#"+hashtag.Text, fmt.Sprintf("<a rel=\"noopener\" target=\"_blank\" href=\"https://twitter.com/hashtag/%s\">#%s</a>", hashtag.Text, hashtag.Text))
}
2021-02-22 19:29:31 +00:00
tweet.FullText = strings.ReplaceAll(tweet.FullText, "\n", "<br />")
2021-02-18 18:32:36 +00:00
templateFuncs := template.FuncMap{
"base64": func(url string) string {
res, err := http.Get(url)
if err != nil {
return ""
}
buf := new(bytes.Buffer)
buf.ReadFrom(res.Body)
return base64.StdEncoding.EncodeToString(buf.Bytes())
},
"isoDate": func(date string) string {
t, _ := time.Parse(tweetDateLayout, date)
return t.Format(time.RFC3339)
},
"humanDate": func(date string) string {
t, _ := time.Parse(tweetDateLayout, date)
return t.Format("3:04 PM · Jan 2, 2006")
},
"html": func(in string) template.HTML {
return template.HTML(in)
},
2021-02-22 19:29:31 +00:00
"calculateHeight": func(tweet anaconda.Tweet) string {
height := 205.0
lines := math.Floor(float64(len(strip.StripTags(tweet.FullText))) / 40)
height += lines * 20
if tweet.InReplyToScreenName != "" {
height += 45
}
height += float64(strings.Count(tweet.FullText, "<br />") * 20)
for _, pic := range tweet.ExtendedEntities.Media {
ratio := float64(pic.Sizes.Small.W) / 464
height += float64(pic.Sizes.Small.H) / ratio
}
return fmt.Sprintf("%dpx", int64(height))
},
2021-02-18 18:32:36 +00:00
}
t := template.Must(
template.New("tweet.svg.tmpl").
Funcs(templateFuncs).
ParseFiles("tweet.svg.tmpl"))
w.Header().Set("Content-type", "image/svg+xml")
err = t.Execute(w, tweet)
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
return
}
}