Implement Imgur info
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
27e7dab209
commit
137e18e6c1
|
@ -6,4 +6,7 @@ steps:
|
|||
- name: test
|
||||
image: golang
|
||||
commands:
|
||||
- go test
|
||||
- go test
|
||||
environment:
|
||||
IMGUR_CLIENT_ID:
|
||||
from_secret: imgur_client_id
|
135
imgur.go
135
imgur.go
|
@ -1,9 +1,140 @@
|
|||
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)/")
|
||||
)
|
||||
|
||||
func (i *LinkInfoApi) ImgurLinkHandler(link string) (*LinkInfo, error) {
|
||||
return nil, nil
|
||||
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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package linkinfo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestImgurInfoApi_Handler(t *testing.T) {
|
||||
api := New(&ImgurOptions{
|
||||
ClientId: os.Getenv("IMGUR_CLIENT_ID"),
|
||||
})
|
||||
|
||||
info, err := api.Imgur.Handler("https://i.imgur.com/1GKJg79.gifv")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal("Error getting imgur info:", err)
|
||||
}
|
||||
|
||||
if info.Title != "Imgur - Approaching the weekend like (720x404, Animated)" {
|
||||
t.Fatal("Unexpected title", info.Title)
|
||||
}
|
||||
}
|
27
linkinfo.go
27
linkinfo.go
|
@ -12,7 +12,9 @@ type LinkHandler struct {
|
|||
}
|
||||
|
||||
type LinkInfoApi struct {
|
||||
Client *http.Client
|
||||
Client *http.Client
|
||||
|
||||
Imgur *ImgurInfoApi
|
||||
linkHandlers []*LinkHandler
|
||||
}
|
||||
|
||||
|
@ -25,26 +27,45 @@ type LinkInfo struct {
|
|||
Redirects []string `json:"redirects,omitempty"`
|
||||
}
|
||||
|
||||
func New() *LinkInfoApi {
|
||||
func New(opts ...Option) *LinkInfoApi {
|
||||
api := &LinkInfoApi{
|
||||
Client: &http.Client{
|
||||
Timeout: 60 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
switch opt.(type) {
|
||||
case *ImgurOptions:
|
||||
api.Imgur = &ImgurInfoApi{api, opt.(*ImgurOptions)}
|
||||
}
|
||||
}
|
||||
|
||||
api.registerDefaultHandlers()
|
||||
|
||||
return api
|
||||
}
|
||||
|
||||
func (i *LinkInfoApi) registerDefaultHandlers() {
|
||||
i.linkHandlers = make([]*LinkHandler, 0)
|
||||
|
||||
if i.Imgur != nil {
|
||||
i.linkHandlers = append(i.linkHandlers, &LinkHandler{
|
||||
Hosts: imgurHosts,
|
||||
Handler: i.Imgur.Handler,
|
||||
})
|
||||
}
|
||||
|
||||
i.linkHandlers = []*LinkHandler{
|
||||
{Hosts: youtubeHosts, Handler: i.YoutubeLinkHandler},
|
||||
{Hosts: imgurHosts, Handler: i.ImgurLinkHandler},
|
||||
{Hosts: twitterHosts, Handler: i.TwitterLinkHandler},
|
||||
}
|
||||
}
|
||||
|
||||
func (i *LinkInfoApi) AddHandler(handler *LinkHandler) {
|
||||
i.linkHandlers = append(i.linkHandlers, handler)
|
||||
}
|
||||
|
||||
func (i *LinkInfoApi) Retrieve(link string) (*LinkInfo, error) {
|
||||
u, err := url.Parse(link)
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package linkinfo
|
||||
|
||||
type Option interface {
|
||||
}
|
Loading…
Reference in New Issue