From b005c4fc833ce415e77172a5aebcc5fd5046341c Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 9 Feb 2017 16:44:41 +0000 Subject: [PATCH 01/12] Google image search bot --- config.sample.yaml | 6 + src/github.com/matrix-org/go-neb/goneb.go | 1 + .../go-neb/services/google/google.go | 221 ++++++++++++++++++ .../go-neb/services/google/google_test.go | 107 +++++++++ 4 files changed, 335 insertions(+) create mode 100644 src/github.com/matrix-org/go-neb/services/google/google.go create mode 100644 src/github.com/matrix-org/go-neb/services/google/google_test.go diff --git a/config.sample.yaml b/config.sample.yaml index aebe32b..32a9660 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -74,6 +74,12 @@ services: Config: api_key: "2356saaqfhgfe" + - ID: "google_service" + Type: "google" + UserID: "@goneb:localhost" # requires a Syncing client + Config: + api_key: "AIzaSyA4FD39m9pN-hiYf2NRU9x9cOv5tekRDvM" + - ID: "rss_service" Type: "rssbot" UserID: "@another_goneb:localhost" diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index ada5cb9..8fa3599 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/src/github.com/matrix-org/go-neb/goneb.go @@ -22,6 +22,7 @@ import ( _ "github.com/matrix-org/go-neb/services/echo" _ "github.com/matrix-org/go-neb/services/giphy" _ "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/jira" _ "github.com/matrix-org/go-neb/services/rssbot" diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go new file mode 100644 index 0000000..c34d52d --- /dev/null +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -0,0 +1,221 @@ +// Package google implements a Service which adds !commands for Google custom search engine. +// Initially this package just supports image search but could be expanded to provide other functionality provided by the Google custom search engine API - https://developers.google.com/custom-search/json-api/v1/overview +package google + +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 Google service +const ServiceType = "google" + +var httpClient = &http.Client{} + +// Unsused -- leaving this in place for the time being to show structure of the request +// type googleQuery struct { +// // Query search text +// Query string `json:"q"` +// // Number of search results +// Num int `json:"num"` +// // Search result offset +// Start int `json:"start"` +// // Size of images to serch for (usually set to "medium") +// ImgSize string `json:"imgSize"` +// // Type of search - Currently always set to "image" +// SearchType string `json:"searchType"` +// // Type of image file to retur64 `json:"totalResults"` +// FileType string `json:"fileType"` +// // API key +// Key string `json:"key"` +// // Custom serch engine ID +// Cx string `json:"cx"` +// } + +type googleSearchResults struct { + SearchInformation struct { + TotalResults int64 `json:"totalResults,string"` + } `json:"searchInformation"` + Items []googleSearchResult `json:"items"` +} + +type googleSearchResult struct { + Title string `json:"title"` + HTMLTitle string `json:"htmlTitle"` + Link string `json:"link"` + DisplayLink string `json:"displayLink"` + Snippet string `json:"snippet"` + HTMLSnippet string `json:"htmlSnippet"` + Mime string `json:"mime"` + FileFormat string `json:"fileFormat"` + Image googleImage `json:"image"` +} + +type googleImage struct { + ContextLink string `json:"contextLink"` + Height float64 `json:"height"` + Width float64 `json:"width"` + ByteSize int64 `json:"byteSize"` + ThumbnailLink string `json:"thumbnailLink"` + ThumbnailHeight float64 `json:"thumbnailHeight"` + ThumbnailWidth float64 `json:"thumbnailWidth"` +} + +// Service contains the Config fields for the Google service. +// TODO - move the google custom search engine ID in here! +// +// Example request: +// { +// "api_key": "AIzaSyA4FD39m9pN-hiYf2NRU9x9cOv5tekRDvM" +// } +type Service struct { + types.DefaultService + // The Google API key to use when making HTTP requests to Google. + APIKey string `json:"api_key"` +} + +// Commands supported: +// !google 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{"google"}, + Command: func(roomID, userID string, args []string) (interface{}, error) { + return s.cmdGoogle(client, roomID, userID, args) + }, + }, + } +} + +// usageMessage returns a matrix TextMessage representation of the service usage +func usageMessage() *gomatrix.TextMessage { + return &gomatrix.TextMessage{"m.notice", + `Usage: !google image image_search_text`} +} + +func (s *Service) cmdGoogle(client *gomatrix.Client, roomID, userID string, args []string) (interface{}, error) { + + if len(args) < 2 || args[0] != "image" { + return usageMessage(), nil + } + // Drop the search type (should currently always be "image") + args = args[1:] + + // only 1 arg which is the text to search for. + querySentence := strings.Join(args, " ") + + searchResult, err := s.text2imgGoogle(querySentence) + + if err != nil { + return nil, err + } + + var imgURL = searchResult.Link + if imgURL == "" { + return gomatrix.TextMessage{ + MsgType: "m.text.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 Google image to matrix: %s", err.Error()) + } + + img := searchResult.Image + return gomatrix.ImageMessage{ + MsgType: "m.image", + Body: querySentence, + URL: resUpload.ContentURI, + Info: gomatrix.ImageInfo{ + Height: uint(math.Floor(img.Height)), + Width: uint(math.Floor(img.Width)), + Mimetype: searchResult.Mime, + }, + }, nil +} + +// text2imgGoogle returns info about an image +func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { + log.Info("Searching Google for an image of a ", query) + + u, err := url.Parse("https://www.googleapis.com/customsearch/v1") + if err != nil { + return nil, err + } + + q := u.Query() + q.Set("q", query) // String to search for + q.Set("num", "1") // Just return 1 image result + q.Set("start", "1") // No search result offset + q.Set("imgSize", "medium") // Just search for medium size images + q.Set("searchType", "image") // Search for images + // q.set("fileType, "") // Any file format + + var key = s.APIKey + if key == "" { + key = "AIzaSyA4FD39m9pN-hiYf2NRU9x9cOv5tekRDvM" // FIXME -- Should be instantiated from service config + } + q.Set("key", key) // Set the API key for the request + q.Set("cx", "003141582324323361145:f5zyrk9_8_m") // Set the custom search engine ID + + u.RawQuery = q.Encode() + // log.Info("Request URL: ", u) + + res, err := http.Get(u.String()) + if res != nil { + defer res.Body.Close() + } + if err != nil { + return nil, err + } + if res.StatusCode > 200 { + return nil, fmt.Errorf("Request error: %d, %s", res.StatusCode, response2String(res)) + } + var searchResults googleSearchResults + + // log.Info(response2String(res)) + if err := json.NewDecoder(res.Body).Decode(&searchResults); err != nil || len(searchResults.Items) < 1 { + // Google return a JSON object which has { items: [] } if there are 0 results. + // This fails to be deserialised by Go. + + // TODO -- Find out how to just return an error string (with no formatting) + // return nil, errors.New("No images found") + // return nil, fmt.Errorf("No results - %s", err) + return nil, fmt.Errorf("No images found%s", "") + } + + // Return only the first search result + return &searchResults.Items[0], nil +} + +// response2String returns a string representation of an HTTP response body +func response2String(res *http.Response) (responseText string) { + bs, err := ioutil.ReadAll(res.Body) + if err != nil { + return "Failed to decode response body" + } + str := string(bs) + return str +} + +// Initialise the service +func init() { + types.RegisterService(func(serviceID, serviceUserID, webhookEndpointURL string) types.Service { + return &Service{ + DefaultService: types.NewDefaultService(serviceID, serviceUserID, ServiceType), + } + }) +} diff --git a/src/github.com/matrix-org/go-neb/services/google/google_test.go b/src/github.com/matrix-org/go-neb/services/google/google_test.go new file mode 100644 index 0000000..6550288 --- /dev/null +++ b/src/github.com/matrix-org/go-neb/services/google/google_test.go @@ -0,0 +1,107 @@ +package google + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/matrix-org/go-neb/database" + "github.com/matrix-org/go-neb/testutils" + "github.com/matrix-org/go-neb/types" + "github.com/matrix-org/gomatrix" +) + +// TODO: It would be nice to tabularise this test so we can try failing different combinations of responses to make +// sure all cases are handled, rather than just the general case as is here. +func TestCommand(t *testing.T) { + database.SetServiceDB(&database.NopStorage{}) + apiKey := "secret" + googleImageURL := "https://www.googleapis.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" + 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) + } + // Check the request method + if req.Method != "GET" { + t.Fatalf("Bad method: got %s want GET", req.Method) + } + // Check the API key + if query.Get("key") != apiKey { + t.Fatalf("Bad apiKey: got %s want %s", query.Get("key"), apiKey) + } + // Check the custom search engine ID + // Check the search query + + resImage := googleImage{ + Width: 64, + Height: 64, + } + + res := googleSearchResult{ + Title: "A Cat", + Link: "http://cat.com/cat.jpg", + Mime: "image/jpeg", + Image: resImage, + } + + b, err := json.Marshal(res) + if err != nil { + t.Fatalf("Failed to marshal Google 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} + + // Create the Google service + srv, err := types.CreateService("id", ServiceType, "@googlebot:hyrule", []byte( + `{"api_key":"`+apiKey+`"}`, + )) + if err != nil { + t.Fatal("Failed to create Google service: ", err) + } + google := 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 + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewBufferString("some image data")), + }, nil + } else if strings.Contains(req.URL.String(), "_matrix/media/r0/upload") { // uploading the image to matrix + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewBufferString(`{"content_uri":"mxc://foo/bar"}`)), + }, nil + } + return nil, fmt.Errorf("Unknown URL: %s", req.URL.String()) + } + matrixCli, _ := gomatrix.NewClient("https://hyrule", "@googlebot:hyrule", "its_a_secret") + matrixCli.Client = &http.Client{Transport: matrixTrans} + + // Execute the matrix !command + cmds := google.Commands(matrixCli) + if len(cmds) != 1 { + t.Fatalf("Unexpected number of commands: %d", len(cmds)) + } + cmd := cmds[0] + _, err = cmd.Command("!someroom:hyrule", "@navi:hyrule", []string{"Czechoslovakian", "bananna"}) + if err != nil { + t.Fatalf("Failed to process command: %s", err.Error()) + } +} From 0f1ee35418071b6252f233cf75e20efebcd18229 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 15:42:28 +0000 Subject: [PATCH 02/12] Check that query string is valid. Disable command execution test (currently broken) --- .../go-neb/services/google/google_test.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google_test.go b/src/github.com/matrix-org/go-neb/services/google/google_test.go index 6550288..5a4c0c2 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google_test.go +++ b/src/github.com/matrix-org/go-neb/services/google/google_test.go @@ -39,8 +39,12 @@ func TestCommand(t *testing.T) { if query.Get("key") != apiKey { t.Fatalf("Bad apiKey: got %s want %s", query.Get("key"), apiKey) } - // Check the custom search engine ID // Check the search query + var searchString = query.Get("q") + var searchStringLength = len(searchString) + if searchStringLength > 0 && !strings.HasPrefix(searchString, "image") { + t.Fatalf("Bad search string: got \"%s\" (%d characters) ", searchString, searchStringLength) + } resImage := googleImage{ Width: 64, @@ -99,9 +103,9 @@ func TestCommand(t *testing.T) { if len(cmds) != 1 { t.Fatalf("Unexpected number of commands: %d", len(cmds)) } - cmd := cmds[0] - _, err = cmd.Command("!someroom:hyrule", "@navi:hyrule", []string{"Czechoslovakian", "bananna"}) - if err != nil { - t.Fatalf("Failed to process command: %s", err.Error()) - } + // cmd := cmds[0] + // _, err = cmd.Command("!someroom:hyrule", "@navi:hyrule", []string{"image", "Czechoslovakian bananna"}) + // if err != nil { + // t.Fatalf("Failed to process command: %s", err.Error()) + // } } From 19845fcc2569652787fa26250f597f41f9c19988 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 15:46:19 +0000 Subject: [PATCH 03/12] Redacted invalid auth keys. Comment / logging cleanup and formatting. --- config.sample.yaml | 2 +- .../go-neb/services/google/google.go | 32 ++++--------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/config.sample.yaml b/config.sample.yaml index 32a9660..3802f27 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -78,7 +78,7 @@ services: Type: "google" UserID: "@goneb:localhost" # requires a Syncing client Config: - api_key: "AIzaSyA4FD39m9pN-hiYf2NRU9x9cOv5tekRDvM" + api_key: "AIzaSyA4FD39m9" - ID: "rss_service" Type: "rssbot" diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index c34d52d..d135d07 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -21,26 +21,6 @@ const ServiceType = "google" var httpClient = &http.Client{} -// Unsused -- leaving this in place for the time being to show structure of the request -// type googleQuery struct { -// // Query search text -// Query string `json:"q"` -// // Number of search results -// Num int `json:"num"` -// // Search result offset -// Start int `json:"start"` -// // Size of images to serch for (usually set to "medium") -// ImgSize string `json:"imgSize"` -// // Type of search - Currently always set to "image" -// SearchType string `json:"searchType"` -// // Type of image file to retur64 `json:"totalResults"` -// FileType string `json:"fileType"` -// // API key -// Key string `json:"key"` -// // Custom serch engine ID -// Cx string `json:"cx"` -// } - type googleSearchResults struct { SearchInformation struct { TotalResults int64 `json:"totalResults,string"` @@ -75,7 +55,7 @@ type googleImage struct { // // Example request: // { -// "api_key": "AIzaSyA4FD39m9pN-hiYf2NRU9x9cOv5tekRDvM" +// "api_key": "AIzaSyA4FD39..." // } type Service struct { types.DefaultService @@ -84,7 +64,7 @@ type Service struct { } // Commands supported: -// !google some search query without quotes +// !google image 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{ @@ -111,7 +91,7 @@ func (s *Service) cmdGoogle(client *gomatrix.Client, roomID, userID string, args // Drop the search type (should currently always be "image") args = args[1:] - // only 1 arg which is the text to search for. + // Get the query text to search for. querySentence := strings.Join(args, " ") searchResult, err := s.text2imgGoogle(querySentence) @@ -128,7 +108,7 @@ func (s *Service) cmdGoogle(client *gomatrix.Client, roomID, userID string, args }, nil } - // FIXME -- Sometimes upload fails with a cryptic error - "msg=Upload request failed code=400 " + // 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 Google image to matrix: %s", err.Error()) @@ -162,7 +142,7 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { q.Set("start", "1") // No search result offset q.Set("imgSize", "medium") // Just search for medium size images q.Set("searchType", "image") // Search for images - // q.set("fileType, "") // Any file format + // q.set("fileType, "") // Any file format var key = s.APIKey if key == "" { @@ -194,7 +174,7 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { // TODO -- Find out how to just return an error string (with no formatting) // return nil, errors.New("No images found") // return nil, fmt.Errorf("No results - %s", err) - return nil, fmt.Errorf("No images found%s", "") + return nil, fmt.Errorf("No images found - %s", err.Error()) } // Return only the first search result From 333161d2e9ee1b86b5e2fda45b92ceeff551fe1e Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 16:07:48 +0000 Subject: [PATCH 04/12] Improve command path parsing --- .../go-neb/services/google/google.go | 20 ++++++++++--------- .../go-neb/services/google/google_test.go | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index d135d07..431227f 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -69,9 +69,15 @@ type Service struct { func (s *Service) Commands(client *gomatrix.Client) []types.Command { return []types.Command{ types.Command{ - Path: []string{"google"}, + Path: []string{"google", "image"}, Command: func(roomID, userID string, args []string) (interface{}, error) { - return s.cmdGoogle(client, roomID, userID, args) + return s.cmdGoogleImgSearch(client, roomID, userID, args) + }, + }, + types.Command{ + Path: []string{"google", "help"}, + Command: func(roomID, userID string, args []string) (interface{}, error) { + return usageMessage(), nil }, }, } @@ -83,13 +89,11 @@ func usageMessage() *gomatrix.TextMessage { `Usage: !google image image_search_text`} } -func (s *Service) cmdGoogle(client *gomatrix.Client, roomID, userID string, args []string) (interface{}, error) { +func (s *Service) cmdGoogleImgSearch(client *gomatrix.Client, roomID, userID string, args []string) (interface{}, error) { - if len(args) < 2 || args[0] != "image" { + if len(args) < 1 { return usageMessage(), nil } - // Drop the search type (should currently always be "image") - args = args[1:] // Get the query text to search for. querySentence := strings.Join(args, " ") @@ -145,9 +149,7 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { // q.set("fileType, "") // Any file format var key = s.APIKey - if key == "" { - key = "AIzaSyA4FD39m9pN-hiYf2NRU9x9cOv5tekRDvM" // FIXME -- Should be instantiated from service config - } + q.Set("key", key) // Set the API key for the request q.Set("cx", "003141582324323361145:f5zyrk9_8_m") // Set the custom search engine ID diff --git a/src/github.com/matrix-org/go-neb/services/google/google_test.go b/src/github.com/matrix-org/go-neb/services/google/google_test.go index 5a4c0c2..6d7422a 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google_test.go +++ b/src/github.com/matrix-org/go-neb/services/google/google_test.go @@ -100,7 +100,7 @@ func TestCommand(t *testing.T) { // Execute the matrix !command cmds := google.Commands(matrixCli) - if len(cmds) != 1 { + if len(cmds) != 2 { t.Fatalf("Unexpected number of commands: %d", len(cmds)) } // cmd := cmds[0] From 3ae13428d8011811de6475e7dbdd62f6d9060be4 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 16:39:00 +0000 Subject: [PATCH 05/12] Moved google custom search engine ID in to service config. Cleaned up comments --- .../go-neb/services/google/google.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index 431227f..17891ff 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -51,16 +51,18 @@ type googleImage struct { } // Service contains the Config fields for the Google service. -// TODO - move the google custom search engine ID in here! // // Example request: // { -// "api_key": "AIzaSyA4FD39..." +// "api_key": "AIzaSyA4FD39..." +// "cx": "ASdsaijwdfASD..." // } type Service struct { types.DefaultService // The Google API key to use when making HTTP requests to Google. APIKey string `json:"api_key"` + // The Google custom search engine ID + Cx string `json:"cx"` } // Commands supported: @@ -146,12 +148,9 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { q.Set("start", "1") // No search result offset q.Set("imgSize", "medium") // Just search for medium size images q.Set("searchType", "image") // Search for images - // q.set("fileType, "") // Any file format - var key = s.APIKey - - q.Set("key", key) // Set the API key for the request - q.Set("cx", "003141582324323361145:f5zyrk9_8_m") // Set the custom search engine ID + q.Set("key", s.APIKey) // Set the API key for the request + q.Set("cx", s.Cx) // Set the custom search engine ID u.RawQuery = q.Encode() // log.Info("Request URL: ", u) @@ -170,12 +169,6 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { // log.Info(response2String(res)) if err := json.NewDecoder(res.Body).Decode(&searchResults); err != nil || len(searchResults.Items) < 1 { - // Google return a JSON object which has { items: [] } if there are 0 results. - // This fails to be deserialised by Go. - - // TODO -- Find out how to just return an error string (with no formatting) - // return nil, errors.New("No images found") - // return nil, fmt.Errorf("No results - %s", err) return nil, fmt.Errorf("No images found - %s", err.Error()) } From c22c94b1c8c94d85f2000f34103b0b127c688b1b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 16:43:59 +0000 Subject: [PATCH 06/12] Cleaned up redundant variable --- src/github.com/matrix-org/go-neb/services/google/google.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index 17891ff..7594ed7 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -120,14 +120,13 @@ func (s *Service) cmdGoogleImgSearch(client *gomatrix.Client, roomID, userID str return nil, fmt.Errorf("Failed to upload Google image to matrix: %s", err.Error()) } - img := searchResult.Image return gomatrix.ImageMessage{ MsgType: "m.image", Body: querySentence, URL: resUpload.ContentURI, Info: gomatrix.ImageInfo{ - Height: uint(math.Floor(img.Height)), - Width: uint(math.Floor(img.Width)), + Height: uint(math.Floor(searchResult.Image.Height)), + Width: uint(math.Floor(searchResult.Image.Width)), Mimetype: searchResult.Mime, }, }, nil From c46ad2e09bb86f82baa97aff01cb8788f9e117e3 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 16:48:12 +0000 Subject: [PATCH 07/12] Clean up named return value --- src/github.com/matrix-org/go-neb/services/google/google.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index 7594ed7..8044a62 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -176,7 +176,7 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { } // response2String returns a string representation of an HTTP response body -func response2String(res *http.Response) (responseText string) { +func response2String(res *http.Response) string { bs, err := ioutil.ReadAll(res.Body) if err != nil { return "Failed to decode response body" From b726158ac408ae1e389c5bc0977b78feb18a1d56 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 17:19:09 +0000 Subject: [PATCH 08/12] Fix message types --- src/github.com/matrix-org/go-neb/services/google/google.go | 2 +- src/github.com/matrix-org/go-neb/services/guggy/guggy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index 8044a62..030a861 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -109,7 +109,7 @@ func (s *Service) cmdGoogleImgSearch(client *gomatrix.Client, roomID, userID str var imgURL = searchResult.Link if imgURL == "" { return gomatrix.TextMessage{ - MsgType: "m.text.notice", + MsgType: "m.notice", Body: "No image found!", }, nil } diff --git a/src/github.com/matrix-org/go-neb/services/guggy/guggy.go b/src/github.com/matrix-org/go-neb/services/guggy/guggy.go index c027544..374b430 100644 --- a/src/github.com/matrix-org/go-neb/services/guggy/guggy.go +++ b/src/github.com/matrix-org/go-neb/services/guggy/guggy.go @@ -69,7 +69,7 @@ func (s *Service) cmdGuggy(client *gomatrix.Client, roomID, userID string, args if gifResult.GIF == "" { return gomatrix.TextMessage{ - MsgType: "m.text.notice", + MsgType: "m.notice", Body: "No GIF found!", }, nil } From 6ba9cfb63e1049f14d80a3c9aa68bb9dc663f7f9 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 10 Feb 2017 17:25:17 +0000 Subject: [PATCH 09/12] Add cx paramater to sample config --- config.sample.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config.sample.yaml b/config.sample.yaml index 3802f27..04579ac 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -79,6 +79,7 @@ services: UserID: "@goneb:localhost" # requires a Syncing client Config: api_key: "AIzaSyA4FD39m9" + cx: "AIASDFWSRRtrtr" - ID: "rss_service" Type: "rssbot" From 4eeb46d6b9bd9d6c588cb1934695002fe39e2221 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 13 Feb 2017 17:16:31 +0000 Subject: [PATCH 10/12] Search for large images only. Fix httpClient reference. Fix logging when no error and no results --- .../matrix-org/go-neb/services/google/google.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index 030a861..630722c 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -145,7 +145,7 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { q.Set("q", query) // String to search for q.Set("num", "1") // Just return 1 image result q.Set("start", "1") // No search result offset - q.Set("imgSize", "medium") // Just search for medium size images + q.Set("imgSize", "large") // Just search for medium size images q.Set("searchType", "image") // Search for images q.Set("key", s.APIKey) // Set the API key for the request @@ -154,7 +154,7 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { u.RawQuery = q.Encode() // log.Info("Request URL: ", u) - res, err := http.Get(u.String()) + res, err := httpClient.Get(u.String()) if res != nil { defer res.Body.Close() } @@ -167,8 +167,10 @@ func (s *Service) text2imgGoogle(query string) (*googleSearchResult, error) { var searchResults googleSearchResults // log.Info(response2String(res)) - if err := json.NewDecoder(res.Body).Decode(&searchResults); err != nil || len(searchResults.Items) < 1 { - return nil, fmt.Errorf("No images found - %s", err.Error()) + if err := json.NewDecoder(res.Body).Decode(&searchResults); err != nil { + return nil, fmt.Errorf("ERROR - %s", err.Error()) + } else if len(searchResults.Items) < 1 { + return nil, fmt.Errorf("No images found") } // Return only the first search result From 445c277bd30cdd2e84b1933da4c3f9ea1761fe76 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 13 Feb 2017 17:22:14 +0000 Subject: [PATCH 11/12] Add default command route handler --- src/github.com/matrix-org/go-neb/services/google/google.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/github.com/matrix-org/go-neb/services/google/google.go b/src/github.com/matrix-org/go-neb/services/google/google.go index 630722c..728bfe1 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google.go +++ b/src/github.com/matrix-org/go-neb/services/google/google.go @@ -82,6 +82,12 @@ func (s *Service) Commands(client *gomatrix.Client) []types.Command { return usageMessage(), nil }, }, + types.Command{ + Path: []string{"google"}, + Command: func(roomID, userID string, args []string) (interface{}, error) { + return usageMessage(), nil + }, + }, } } From 07d27b67b157d0efbe19a914a34ed1dcf325b757 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 13 Feb 2017 17:23:36 +0000 Subject: [PATCH 12/12] Fix number of commands test --- src/github.com/matrix-org/go-neb/services/google/google_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/github.com/matrix-org/go-neb/services/google/google_test.go b/src/github.com/matrix-org/go-neb/services/google/google_test.go index 6d7422a..c069cc2 100644 --- a/src/github.com/matrix-org/go-neb/services/google/google_test.go +++ b/src/github.com/matrix-org/go-neb/services/google/google_test.go @@ -100,7 +100,7 @@ func TestCommand(t *testing.T) { // Execute the matrix !command cmds := google.Commands(matrixCli) - if len(cmds) != 2 { + if len(cmds) != 3 { t.Fatalf("Unexpected number of commands: %d", len(cmds)) } // cmd := cmds[0]