Avatar downloader

This commit is contained in:
Eduard Urbach 2017-06-12 20:06:31 +02:00
parent 72857972fe
commit 586befcb1a
9 changed files with 185 additions and 6 deletions

2
images/avatars/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="50" height="50">
<circle cx="25" cy="19" r="10" fill="rgb(60, 60, 60)" />
<circle cx="25" cy="50" r="20" fill="rgb(60, 60, 60)" />
</svg>

After

Width:  |  Height:  |  Size: 201 B

122
jobs/avatars/avatars.go Normal file
View File

@ -0,0 +1,122 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"runtime"
"time"
"github.com/animenotifier/arn"
"github.com/fatih/color"
"github.com/parnurzeal/gorequest"
gravatar "github.com/ungerik/go-gravatar"
)
func main() {
users, _ := arn.AllUsers()
usersQueue := make(chan *arn.User)
rateLimiter := time.NewTicker(100 * time.Millisecond)
defer rateLimiter.Stop()
for w := 0; w < runtime.NumCPU(); w++ {
go func(workerID int) {
for user := range usersQueue {
<-rateLimiter.C
os.Stdout.WriteString("[" + fmt.Sprint(workerID) + "] ")
downloadAvatar(user)
makeWebPAvatar(user)
}
}(w)
}
for user := range users {
usersQueue <- user
}
}
func findAvatar(user *arn.User, dir string) string {
testExtensions := []string{"", ".jpg", ".png", ".gif", ".webp"}
for _, testExt := range testExtensions {
if _, err := os.Stat(dir + user.ID + testExt); !os.IsNotExist(err) {
return user.ID + testExt
}
}
return ""
}
func makeWebPAvatar(user *arn.User) {
baseName := findAvatar(user, "../../images/avatars/original/")
if baseName == "" {
return
}
original := "../../images/avatars/original/" + baseName
outFile := "../../images/avatars/webp/" + user.ID + ".webp"
err := convertFileToWebP(original, outFile, 80)
if err != nil {
color.Red("[WebP] " + original + " -> " + outFile)
} else {
color.Green("[WebP] " + original + " -> " + outFile)
}
}
func downloadAvatar(user *arn.User) {
if user.Email == "" {
return
}
directory := "../../images/avatars/original/"
fileName := directory + user.ID
// Build URL
url := gravatar.Url(user.Email) + "?s=560&d=404&r=pg"
// Skip existing avatars
if findAvatar(user, directory) != "" {
color.Yellow(url)
return
}
// Download
response, data, err := gorequest.New().Get(url).EndBytes()
if err != nil {
color.Red(url)
return
}
contentType := response.Header.Get("content-type")
if response.StatusCode != 200 {
color.Red(url)
return
}
color.Green(url)
// Determine file extension
extension := ""
switch contentType {
case "image/jpeg":
extension = ".jpg"
case "image/png":
extension = ".png"
case "image/gif":
extension = ".gif"
case "image/webp":
extension = ".webp"
}
fileName += extension
// Write to disk
ioutil.WriteFile(fileName, data, 0644)
}

40
jobs/avatars/webp.go Normal file
View File

@ -0,0 +1,40 @@
package main
import (
"fmt"
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"os"
"github.com/chai2010/webp"
)
func convertFileToWebP(in string, out string, quality float32) error {
f, openErr := os.Open(in)
if openErr != nil {
return openErr
}
img, format, decodeErr := image.Decode(f)
if decodeErr != nil {
return decodeErr
}
fmt.Println(format, img.Bounds().Dx(), img.Bounds().Dy())
fileOut, writeErr := os.Create(out)
if writeErr != nil {
return writeErr
}
encodeErr := webp.Encode(fileOut, img, &webp.Options{
Quality: quality,
})
return encodeErr
}

View File

@ -76,6 +76,10 @@ func main() {
return ctx.File("images/cover/" + ctx.Get("file") + format)
})
app.Get("/images/elements/:file", func(ctx *aero.Context) string {
return ctx.File("images/elements/" + ctx.Get("file"))
})
// For benchmarks
app.Get("/hello", func(ctx *aero.Context) string {
return ctx.Text("Hello World")

View File

@ -1,5 +1,7 @@
component ProfileImage(user *arn.User)
if user.Avatar != ""
img.profile-image(src=user.Avatar + "?s=500&r=x&d=mm", alt="Profile image")
img.profile-image(src=user.Avatar + "?s=560&r=x&d=mm", alt="Profile image")
else
img.profile-image(src="/images/elements/no-gravatar.svg", alt="Profile image")
svg.profile-image(width=280, height=280, viewBox="0 0 50 50", alt="Profile image")
circle.head(cx="25", cy="19", r="10")
circle.body(cx="25", cy="50", r="20")

View File

@ -66,8 +66,8 @@ animation cover-animation
.image-container
flex 1
max-width 275px
max-height 275px
max-width 280px
max-height 280px
border-radius 3px
overflow hidden

View File

@ -8,8 +8,8 @@ import (
func main() {
color.Yellow("Updating user references")
arn.Truncate("NickToUser")
arn.Truncate("EmailToUser")
arn.DB.DeleteTable("NickToUser")
arn.DB.DeleteTable("EmailToUser")
// Get a stream of all anime
allUsers, err := arn.AllUsers()

5
styles/svg.scarlet Normal file
View File

@ -0,0 +1,5 @@
.head
fill text-color
.body
fill text-color