-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
156 lines (120 loc) · 4.14 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package main
import (
"flag"
"fmt"
"image"
"image/color"
_ "image/jpeg"
"os"
"time"
"github.com/joho/godotenv"
)
const fontPath = "fonts/OpenSans-VariableFont_wdth,wght.ttf"
const imageDir = "images"
const fontDpi = 72.0
const fontSize = 32.0
// Overlay background RGBA values
const overlayColourRed = 150
const overlayColourGreen = 150
const overlayColourBlue = 150
const overlayOpacity = 150
// Overlay rectangle coordinates
const overlayX0 = 1082
const overlayY0 = 22
const overlayX1 = 1482
// Amount of pixels to allocate
// to each line when calculating Y1
// Should take the font size
// and padding into consideration
const lineHeight = 46
// Gap between lines
const textPadding = 10
func getBannerDrawable(consumerKey string, consumerSecret string, username string, promotionalLine string, debug bool) (*image.RGBA, error) {
overlayColour := color.RGBA{
overlayColourRed,
overlayColourBlue,
overlayColourGreen,
uint8(color.Opaque.A),
}
srcPath, err := GetJpegPathInDirectory(imageDir)
if debug {
fmt.Printf("Using base image: %s\n", srcPath)
}
if err != nil {
return image.NewRGBA(image.Rectangle{}), err
}
drawable := GetDrawableFromImagePath(srcPath)
userData, err := GetTwitterUserData(consumerKey, consumerSecret, username)
if err != nil {
return image.NewRGBA(image.Rectangle{}), err
}
lines := GetTextLines(userData, promotionalLine)
numLines := len(lines)
overlayY1 := numLines * lineHeight
overlayRectangle := image.Rect(overlayX0, overlayY0, overlayX1, overlayY1)
AddOverlayOnDrawable(drawable, overlayRectangle, &overlayColour, &color.Alpha{overlayOpacity})
font := LoadFontFromPath(fontPath)
ftContext := GetFreetypeContext(font, fontDpi, fontSize, drawable)
if debug {
fmt.Printf("Lines to print: %v\n", lines)
}
WriteLinesOnRectangle(overlayRectangle, ftContext, lines, int(fontSize), textPadding)
return drawable, nil
}
func main() {
const outPath = "out.png"
var loopDuration time.Duration
var err error
godotenv.Load()
defaultUsername := os.Getenv("TWITTER_USERNAME")
if defaultUsername == "" {
defaultUsername = "oliverradwell"
}
consumerKey := flag.String("consumer-key", os.Getenv("TWITTER_APP_CONSUMER_KEY"), "Twitter App consumer key")
consumerSecret := flag.String("consumer-secret", os.Getenv("TWITTER_APP_CONSUMER_SECRET"), "Twitter App consumer secret")
accessToken := flag.String("access-token", os.Getenv("TWITTER_ACCESS_TOKEN"), "Twitter User access token")
accessSecret := flag.String("access-secret", os.Getenv("TWITTER_ACCESS_SECRET"), "Twitter User access secret")
username := flag.String("username", defaultUsername, "Twitter username")
promotionalLine := flag.String("promotional-line", os.Getenv("PROMOTIONAL_LINE"), "Extra line to add to the bottom of the information overlay")
loopInterval := flag.String("interval", "", "Banner update interval (e.g. 5m). With empty value, program exits after updating once")
debug := flag.Bool("debug", os.Getenv("DEBUG") != "", "Print more output")
dryRun := flag.Bool("dry-run", false, "Write image to out.png instead of updating Twitter banner")
flag.Parse()
if *consumerKey == "" || *consumerSecret == "" {
panic("Twitter consumer key and consumer secret are required. Use '-h' for details")
}
if *loopInterval != "" {
loopDuration, err = time.ParseDuration(*loopInterval)
if err != nil {
panic(fmt.Sprintf("Error parsing interval: %v\n", err))
}
if *dryRun {
panic("Dry run doesn't make sense when running unattended")
}
}
for ok := true; ok; ok = (*loopInterval != "") {
drawable, err := getBannerDrawable(*consumerKey, *consumerSecret, *username, *promotionalLine, *debug)
if err != nil {
fmt.Printf("Error: %v\n", err)
continue
}
if *dryRun {
WriteToPngFile(outPath, drawable)
fmt.Printf("Please see file: %s\n", outPath)
continue
} else {
err = UpdateTwitterBanner(*consumerKey, *consumerSecret, *accessToken, *accessSecret, drawable, *debug)
if err != nil {
fmt.Printf("Error: %v\n", err)
continue
}
fmt.Println("Updated Twitter banner")
}
if *loopInterval != "" {
if *debug {
fmt.Printf("Waiting for %s\n", *loopInterval)
}
time.Sleep(loopDuration)
}
}
}