linkinfo/imgur.go

141 lines
2.5 KiB
Go

package linkinfo
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"path/filepath"
"regexp"
"strings"
)
const imgurApiUrl = "https://api.imgur.com/3/%s/%s.json"
var (
imgurHosts = []string{"imgur.com", "i.imgur.com"}
imgurAlbumRegexp = regexp.MustCompile("^/(a|gallery)/")
)
type ImgurOptions struct {
Option
ClientId string
}
type ImgurInfoApi struct {
api *LinkInfoApi
opts *ImgurOptions
}
type imgurResponse struct {
Success bool `json:"success"`
Data imgurData `json:"data"`
}
type imgurData struct {
Type string `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Width int `json:"width"`
Height int `json:"height"`
Animated bool `json:"animated"`
Nsfw bool `json:"nsfw"`
}
func (i *ImgurInfoApi) Handler(link string) (*LinkInfo, error) {
if i.opts.ClientId == "" {
return nil, errors.New("invalid client id")
}
u, err := url.Parse(link)
if err != nil {
return nil, err
}
id := filepath.Base(u.Path)
extension := filepath.Ext(id)
if extension != "" {
id = id[0 : len(id)-len(extension)]
}
imageType := "image"
if imgurAlbumRegexp.MatchString(link) {
imageType = "album"
}
req, err := http.NewRequest("GET", fmt.Sprintf(imgurApiUrl, imageType, id), nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Client-ID "+i.opts.ClientId)
res, err := i.api.Client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var response imgurResponse
if err := json.NewDecoder(res.Body).Decode(&response); err != nil {
return nil, err
}
if !response.Success {
return nil, errors.New("imgur api returned success=false")
}
var title string
if response.Data.Title != "" {
title = "Imgur - " + response.Data.Title
} else {
title = "Imgur - " + id
switch response.Data.Type {
case "image/jpeg":
title += ".jpg"
case "image/png":
title += ".png"
case "image/gif":
title += ".gif"
}
}
attribs := make([]string, 0)
if imageType == "album" {
attribs = append(attribs, "Album")
} else {
attribs = append(attribs, fmt.Sprintf("%dx%d", response.Data.Width, response.Data.Height))
if response.Data.Animated {
attribs = append(attribs, "Animated")
}
}
title += " (" + strings.Join(attribs, ", ") + ")"
if response.Data.Nsfw {
attribs = append(attribs, "NSFW")
}
info := &LinkInfo{
Title: title,
Description: response.Data.Description,
}
return info, nil
}