func queryImgur(query, clientID string) ([]byte, error) {
	query = url.QueryEscape(query)
	var sort = "time"   
	var window = "all"  
	var page = 1
	var urlString = fmt.Sprintf("https://api.imgur.com/3/gallery/search/%s/%s/%d?q=%s", sort, window, page, query)
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("GET", u.String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Authorization", "Client-ID "+clientID)
	res, err := httpClient.Do(req)
	if res != nil {
		defer res.Body.Close()
	}
	if err != nil {
		return nil, err
	}
	if res.StatusCode < 200 || res.StatusCode >= 300 {
		return nil, fmt.Errorf("Request error: %d, %s", res.StatusCode, response2String(res))
	}
	bytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	return bytes, nil
}
Query imgur and return HTTP response or error
package imgur
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
	"github.com/matrix-org/go-neb/types"
	log "github.com/sirupsen/logrus"
	mevt "maunium.net/go/mautrix/event"
	"maunium.net/go/mautrix/id"
)
const ServiceType = "imgur"
var httpClient = &http.Client{}
type imgurGalleryImage struct {
	ID          string `json:"id"`           
	Title       string `json:"title"`        
	Description string `json:"description"`  
	DateTime    int64  `json:"datetime"`     
	Type        string `json:"type"`         
	Animated    *bool  `json:"animated"`     
	Width       int    `json:"width"`        
	Height      int    `json:"height"`       
	Size        int64  `json:"size"`         
	Views       int64  `json:"views"`        
	Link        string `json:"link"`         
	Gifv        string `json:"gifv"`         
	MP4         string `json:"mp4"`          
	MP4Size     int64  `json:"mp4_size"`     
	Looping     *bool  `json:"looping"`      
	NSFW        *bool  `json:"nsfw"`         
	Topic       string `json:"topic"`        
	Section     string `json:"section"`      
	IsAlbum     *bool  `json:"is_album"`     
}
type imgurGalleryAlbum struct {
	ID          string              `json:"id"`            
	Title       string              `json:"title"`         
	Description string              `json:"description"`   
	DateTime    int64               `json:"datetime"`      
	Views       int64               `json:"views"`         
	Link        string              `json:"link"`          
	NSFW        *bool               `json:"nsfw"`          
	Topic       string              `json:"topic"`         
	IsAlbum     *bool               `json:"is_album"`      
	Cover       string              `json:"cover"`         
	CoverWidth  int                 `json:"cover_width"`   
	CoverHeight int                 `json:"cover_height"`  
	ImagesCount int                 `json:"images_count"`  
	Images      []imgurGalleryImage `json:"images"`        
}
type imgurSearchResponse struct {
	Data    []json.RawMessage `json:"data"`     
	Success *bool             `json:"success"`  
	Status  int               `json:"status"`   
}
type Service struct {
	types.DefaultService
	ClientID string `json:"client_id"`
	ClientSecret string `json:"client_secret"`
}
func (s *Service) Commands(client types.MatrixClient) []types.Command {
	return []types.Command{
		{
			Path: []string{"imgur", "help"},
			Command: func(roomID id.RoomID, userID id.UserID, args []string) (interface{}, error) {
				return usageMessage(), nil
			},
		},
		{
			Path: []string{"imgur"},
			Command: func(roomID id.RoomID, userID id.UserID, args []string) (interface{}, error) {
				return s.cmdImgSearch(client, roomID, userID, args)
			},
		},
	}
}
func usageMessage() *mevt.MessageEventContent {
	return &mevt.MessageEventContent{
		MsgType: mevt.MsgNotice,
		Body:    "Usage: !imgur image_search_text",
	}
}
func (s *Service) cmdImgSearch(client types.MatrixClient, roomID id.RoomID, userID id.UserID, args []string) (interface{}, error) {
	if len(args) < 1 {
		return usageMessage(), nil
	}
	querySentence := strings.Join(args, " ")
	searchResultImage, searchResultAlbum, err := s.text2img(querySentence)
	if err != nil {
		return nil, err
	}
	if searchResultImage != nil {
		var imgURL = searchResultImage.Link
		if imgURL == "" {
			return mevt.MessageEventContent{
				MsgType: mevt.MsgNotice,
				Body:    "No image found!",
			}, nil
		}
		resUpload, err := client.UploadLink(imgURL)
		if err != nil {
			return nil, fmt.Errorf("Failed to upload Imgur image (%s) to matrix: %s", imgURL, err.Error())
		}
		return mevt.MessageEventContent{
			MsgType: "m.image",
			Body:    querySentence,
			URL:     resUpload.ContentURI.CUString(),
			Info: &mevt.FileInfo{
				Height:   searchResultImage.Height,
				Width:    searchResultImage.Width,
				MimeType: searchResultImage.Type,
			},
		}, nil
	} else if searchResultAlbum != nil {
		return mevt.MessageEventContent{
			MsgType: mevt.MsgNotice,
			Body:    "Search returned an album - Not currently supported",
		}, nil
	} else {
		return mevt.MessageEventContent{
			MsgType: mevt.MsgNotice,
			Body:    "No image found!",
		}, nil
	}
}
func (s *Service) text2img(query string) (*imgurGalleryImage, *imgurGalleryAlbum, error) {
	log.Info("Searching Imgur for an image of a ", query)
	bytes, err := queryImgur(query, s.ClientID)
	if err != nil {
		return nil, nil, err
	}
	var searchResults imgurSearchResponse
	if err := json.Unmarshal(bytes, &searchResults); err != nil {
		return nil, nil, fmt.Errorf("No images found - %s", err.Error())
	} else if len(searchResults.Data) < 1 {
		return nil, nil, fmt.Errorf("No images found")
	}
	log.Printf("%d results were returned from Imgur", len(searchResults.Data))
	var images []imgurGalleryImage
	for i := 0; i < len(searchResults.Data); i++ {
		var image imgurGalleryImage
		if err := json.Unmarshal(searchResults.Data[i], &image); err == nil && !*(image.IsAlbum) {
			images = append(images, image)
		}
	}
	if len(images) > 0 {
		var r = 0
		if len(images) > 1 {
			r = rand.Intn(len(images) - 1)
		}
		return &images[r], nil, nil
	}
	return nil, nil, fmt.Errorf("No images found")
}