Browse Source

Handle image search results

pull/158/head
Richard Lewis 8 years ago
parent
commit
823d3277c7
  1. 6
      config.sample.yaml
  2. 1
      src/github.com/matrix-org/go-neb/goneb.go
  3. 79
      src/github.com/matrix-org/go-neb/services/imgur/imgur.go
  4. 36
      src/github.com/matrix-org/go-neb/services/imgur/imgur_test.go

6
config.sample.yaml

@ -81,6 +81,12 @@ services:
api_key: "AIzaSyA4FD39m9"
cx: "AIASDFWSRRtrtr"
- ID: "imgur_service"
Type: "imgur"
UserID: "@imgur:localhost" # requires a Syncing client
Config:
api_key: "AIzaSyA4FD39m9"
- ID: "rss_service"
Type: "rssbot"
UserID: "@another_goneb:localhost"

1
src/github.com/matrix-org/go-neb/goneb.go

@ -24,6 +24,7 @@ import (
_ "github.com/matrix-org/go-neb/services/github"
_ "github.com/matrix-org/go-neb/services/google"
_ "github.com/matrix-org/go-neb/services/guggy"
_ "github.com/matrix-org/go-neb/services/imgur"
_ "github.com/matrix-org/go-neb/services/jira"
_ "github.com/matrix-org/go-neb/services/rssbot"
_ "github.com/matrix-org/go-neb/services/slackapi"

79
src/github.com/matrix-org/go-neb/services/imgur/imgur.go

@ -5,13 +5,13 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"math"
"net/http"
"net/url"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/matrix-org/go-neb/types"
"github.com/matrix-org/gomatrix"
)
// ServiceType of the Imgur service
@ -108,12 +108,12 @@ type Service struct {
}
// Commands supported:
// !imgur image some_search_query_without_quotes
// !imgur some_search_query_without_quotes
// Responds with a suitable image into the same room as the command.
func (s *Service) Commands(client *gomatrix.Client) []types.Command {
return []types.Command{
types.Command{
Path: []string{"imgur", "image"},
Path: []string{"imgur"},
Command: func(roomID, userID string, args []string) (interface{}, error) {
return s.cmdImgurImgSearch(client, roomID, userID, args)
},
@ -130,7 +130,7 @@ func (s *Service) Commands(client *gomatrix.Client) []types.Command {
// usageMessage returns a matrix TextMessage representation of the service usage
func usageMessage() *gomatrix.TextMessage {
return &gomatrix.TextMessage{"m.notice",
`Usage: !imgur image image_search_text`}
`Usage: !imgur image_search_text`}
}
func (s *Service) cmdImgurImgSearch(client *gomatrix.Client, roomID, userID string, args []string) (interface{}, error) {
@ -142,36 +142,49 @@ func (s *Service) cmdImgurImgSearch(client *gomatrix.Client, roomID, userID stri
// Get the query text to search for.
querySentence := strings.Join(args, " ")
searchResult, err := s.text2imgImgur(querySentence)
searchResultImage, searchResultAlbum, err := s.text2imgImgur(querySentence)
if err != nil {
return nil, err
}
var imgURL = searchResult.Link
if imgURL == "" {
// Image returned
if searchResultImage != nil {
var imgURL = searchResultImage.Link
if imgURL == "" {
return gomatrix.TextMessage{
MsgType: "m.notice",
Body: "No image found!",
}, nil
}
// FIXME -- Sometimes upload fails with a cryptic error - "msg=Upload request failed code=400"
resUpload, err := client.UploadLink(imgURL)
if err != nil {
return nil, fmt.Errorf("Failed to upload Imgur image to matrix: %s", err.Error())
}
return gomatrix.ImageMessage{
MsgType: "m.image",
Body: querySentence,
URL: resUpload.ContentURI,
Info: gomatrix.ImageInfo{
Height: uint(searchResultImage.Height),
Width: uint(searchResultImage.Width),
Mimetype: searchResultImage.Type,
},
}, nil
} else if searchResultAlbum != nil {
return gomatrix.TextMessage{
MsgType: "m.notice",
Body: "Search returned an album - Not currently supported",
}, nil
} else {
return gomatrix.TextMessage{
MsgType: "m.notice",
Body: "No image found!",
}, nil
}
// FIXME -- Sometimes upload fails with a cryptic error - "msg=Upload request failed code=400"
resUpload, err := client.UploadLink(imgURL)
if err != nil {
return nil, fmt.Errorf("Failed to upload Imgur image to matrix: %s", err.Error())
}
return gomatrix.ImageMessage{
MsgType: "m.image",
Body: querySentence,
URL: resUpload.ContentURI,
Info: gomatrix.ImageInfo{
Height: uint(math.Floor(searchResult.Height)),
Width: uint(math.Floor(searchResult.Width)),
Mimetype: searchResult.Type,
},
}, nil
}
// text2imgImgur returns info about an image or an album
@ -179,8 +192,8 @@ func (s *Service) text2imgImgur(query string) (*imgurGalleryImage, *imgurGallery
log.Info("Searching Imgur for an image of a ", query)
var base = "https://api.imgur.com/3/gallery/search/"
var sort = "time" // time | viral | top
var window = all // day | week | month | year | all
var sort = "time" // time | viral | top
var window = "all" // day | week | month | year | all
var page = 1
var urlString = fmt.Sprintf("%s/%s/%s/%d", base, sort, window, page)
@ -201,33 +214,33 @@ func (s *Service) text2imgImgur(query string) (*imgurGalleryImage, *imgurGallery
return nil, nil, fmt.Errorf("Request error: %d, %s", res.StatusCode, response2String(res))
}
var searchResults imgurSearchResults
if err := json.NewDecoder(res.Body).Decode(&searchResults); err != nil || !searchResults.data {
var searchResults imgurSearchResponse
if err := json.NewDecoder(res.Body).Decode(&searchResults); err != nil || !searchResults.Data {
return nil, nil, fmt.Errorf("No images found - %s", err.Error())
}
// Check if we have an image or a gallery
var dataInt map[string]interface{}
if err := json.Unmarshal(searchResults.Data, &dataInt); err != nil || !searchResults.data {
if err := json.Unmarshal(searchResults.Data, &dataInt); err != nil || !searchResults.Data {
return nil, nil, fmt.Errorf("Failed to parse response data - %s", err.Error())
}
// Return an album
if dataInt["is_album"].(bool) {
var album imgurGalleryAlbum
if err := json.Unmarshal(searchResults.Data, &album); err != nill {
if err := json.Unmarshal(searchResults.Data, &album); err != nil {
return nil, nil, fmt.Errorf("Failed to parse album data - %s", err.Error())
}
return nil, album, nil
return nil, &album, nil
}
// Return an image
var image imgurGalleryImage
if err := json.Unmarshal(searchResults.Data, &image); err != nill {
if err := json.Unmarshal(searchResults.Data, &image); err != nil {
return nil, nil, fmt.Errorf("Failed to parse image data - %s", err.Error())
}
return image, nil, nil
return &image, nil, nil
}
// response2String returns a string representation of an HTTP response body

36
src/github.com/matrix-org/go-neb/services/imgur/imgur_test.go

@ -20,16 +20,16 @@ import (
func TestCommand(t *testing.T) {
database.SetServiceDB(&database.NopStorage{})
apiKey := "secret"
googleImageURL := "https://www.googleapis.com/customsearch/v1"
imgurImageURL := "https://www.imgurapis.com/customsearch/v1"
// Mock the response from Google
googleTrans := testutils.NewRoundTripper(func(req *http.Request) (*http.Response, error) {
googleURL := "https://www.googleapis.com/customsearch/v1"
// Mock the response from imgur
imgurTrans := testutils.NewRoundTripper(func(req *http.Request) (*http.Response, error) {
imgurURL := "https://www.imgurapis.com/customsearch/v1"
query := req.URL.Query()
// Check the base API URL
if !strings.HasPrefix(req.URL.String(), googleURL) {
t.Fatalf("Bad URL: got %s want prefix %s", req.URL.String(), googleURL)
if !strings.HasPrefix(req.URL.String(), imgurURL) {
t.Fatalf("Bad URL: got %s want prefix %s", req.URL.String(), imgurURL)
}
// Check the request method
if req.Method != "GET" {
@ -46,12 +46,12 @@ func TestCommand(t *testing.T) {
t.Fatalf("Bad search string: got \"%s\" (%d characters) ", searchString, searchStringLength)
}
resImage := googleImage{
resImage := imgurImage{
Width: 64,
Height: 64,
}
res := googleSearchResult{
res := imgurSearchResult{
Title: "A Cat",
Link: "http://cat.com/cat.jpg",
Mime: "image/jpeg",
@ -60,29 +60,29 @@ func TestCommand(t *testing.T) {
b, err := json.Marshal(res)
if err != nil {
t.Fatalf("Failed to marshal Google response - %s", err)
t.Fatalf("Failed to marshal imgur response - %s", err)
}
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBuffer(b)),
}, nil
})
// clobber the Google service http client instance
httpClient = &http.Client{Transport: googleTrans}
// clobber the imgur service http client instance
httpClient = &http.Client{Transport: imgurTrans}
// Create the Google service
srv, err := types.CreateService("id", ServiceType, "@googlebot:hyrule", []byte(
// Create the imgur service
srv, err := types.CreateService("id", ServiceType, "@imgurbot:hyrule", []byte(
`{"api_key":"`+apiKey+`"}`,
))
if err != nil {
t.Fatal("Failed to create Google service: ", err)
t.Fatal("Failed to create imgur service: ", err)
}
google := srv.(*Service)
imgur := srv.(*Service)
// Mock the response from Matrix
matrixTrans := struct{ testutils.MockTransport }{}
matrixTrans.RT = func(req *http.Request) (*http.Response, error) {
if req.URL.String() == googleImageURL { // getting the Google image
if req.URL.String() == imgurImageURL { // getting the imgur image
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString("some image data")),
@ -95,11 +95,11 @@ func TestCommand(t *testing.T) {
}
return nil, fmt.Errorf("Unknown URL: %s", req.URL.String())
}
matrixCli, _ := gomatrix.NewClient("https://hyrule", "@googlebot:hyrule", "its_a_secret")
matrixCli, _ := gomatrix.NewClient("https://hyrule", "@imgurbot:hyrule", "its_a_secret")
matrixCli.Client = &http.Client{Transport: matrixTrans}
// Execute the matrix !command
cmds := google.Commands(matrixCli)
cmds := imgur.Commands(matrixCli)
if len(cmds) != 2 {
t.Fatalf("Unexpected number of commands: %d", len(cmds))
}

Loading…
Cancel
Save