diff --git a/config.sample.yaml b/config.sample.yaml index 04579ac..91186e4 100644 --- a/config.sample.yaml +++ b/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" diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index 8fa3599..ee7f2cc 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/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" diff --git a/src/github.com/matrix-org/go-neb/services/imgur/imgur.go b/src/github.com/matrix-org/go-neb/services/imgur/imgur.go index d367b20..a9ce597 100644 --- a/src/github.com/matrix-org/go-neb/services/imgur/imgur.go +++ b/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 diff --git a/src/github.com/matrix-org/go-neb/services/imgur/imgur_test.go b/src/github.com/matrix-org/go-neb/services/imgur/imgur_test.go index c4bccb5..53e86ab 100644 --- a/src/github.com/matrix-org/go-neb/services/imgur/imgur_test.go +++ b/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)) }