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 }