From 57ccea02d7d4a8dbaee3447a0e3733e473273255 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 14 Jun 2016 19:55:32 +0530 Subject: [PATCH 1/8] Fixed: Removed executable permissions from files --- LICENSE | 0 README.md | 0 gomdb.go | 0 gomdb_test.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 LICENSE mode change 100755 => 100644 README.md mode change 100755 => 100644 gomdb.go mode change 100755 => 100644 gomdb_test.go diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/gomdb.go b/gomdb.go old mode 100755 new mode 100644 diff --git a/gomdb_test.go b/gomdb_test.go old mode 100755 new mode 100644 From e749b6a774c1620a1e9d036b48863d383a817b8c Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 14 Jun 2016 20:36:35 +0530 Subject: [PATCH 2/8] General code cleanup --- gomdb.go | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/gomdb.go b/gomdb.go index 36d924c..e15ad58 100644 --- a/gomdb.go +++ b/gomdb.go @@ -1,19 +1,4 @@ -/* -Copyright 2014 Kaissersoft Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - +// Package gomdb is a golang implementation of the OMDB API. package gomdb import ( @@ -24,21 +9,11 @@ import ( "net/url" ) -//======================================================================= -// Const -//======================================================================= - -const baseURL string = "http://www.omdbapi.com/?" -const plot string = "full" -const tomatoes string = "true" - -//======================================================================= -// Global vars -//======================================================================= - -//======================================================================= -// Structs -//======================================================================= +const ( + baseURL = "http://www.omdbapi.com/?" + plot = "full" + tomatoes = "true" +) //SearchResult is the type for the search results type SearchResult struct { From 683c3c5411cb9a5d4fef5f4d6eb8628af9e1ea85 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 14 Jun 2016 22:22:21 +0530 Subject: [PATCH 3/8] Cleanup: Made the search API more elegant - Correcting the tests (They were missing return statements) --- gomdb.go | 62 ++++++++++++++++++++++++++------------------------- gomdb_test.go | 15 ++++++++----- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/gomdb.go b/gomdb.go index e15ad58..fce1038 100644 --- a/gomdb.go +++ b/gomdb.go @@ -15,6 +15,13 @@ const ( tomatoes = "true" ) +type QueryData struct { + Title string + Year string + ImdbId string + Type string +} + //SearchResult is the type for the search results type SearchResult struct { Title string @@ -25,9 +32,10 @@ type SearchResult struct { //SearchResponse is the struct of the response in a search type SearchResponse struct { - Search []SearchResult - Response string - Error string + Search []SearchResult + Response string + Error string + totalResults int } //MovieResult is the result struct of an specific movie search @@ -70,13 +78,9 @@ type MovieResult struct { Error string } -//======================================================================= -// Funcs -//======================================================================= - -//Search search for movies given a Title and year, Year is optional you can pass nil -func Search(title string, year string) (*SearchResponse, error) { - resp, err := requestAPI(title, "", "", year) +//Search for movies given a Title and year, Year is optional you can pass nil +func Search(query *QueryData) (*SearchResponse, error) { + resp, err := requestAPI("search", query.Title, query.Year) if err != nil { return nil, err } @@ -96,8 +100,8 @@ func Search(title string, year string) (*SearchResponse, error) { } //MovieByTitle returns a MovieResult given Title -func MovieByTitle(title string, year string) (*MovieResult, error) { - resp, err := requestAPI("", "", title, year) +func MovieByTitle(query *QueryData) (*MovieResult, error) { + resp, err := requestAPI("title", query.Title, query.Year) if err != nil { return nil, err } @@ -117,7 +121,7 @@ func MovieByTitle(title string, year string) (*MovieResult, error) { //MovieByImdbID returns a MovieResult given a ImdbID ex:"tt2015381" func MovieByImdbID(id string) (*MovieResult, error) { - resp, err := requestAPI("", id, "", "") + resp, err := requestAPI("id", id) if err != nil { return nil, err } @@ -135,13 +139,11 @@ func MovieByImdbID(id string) (*MovieResult, error) { return r, nil } -func requestAPI(s string, i string, t string, y string) (resp *http.Response, err error) { - //s = Search Parameter, if this is != nil then its a searchMovies - //i = Id Parameter, if this is != nil then its a getMovieByImdbID - //t = Title Parameter, if this is != nil then its a getMovieByTitle - //y = Year Parameter, Optional data for s and t search - //var res http.Response - +// helper function to call the API +// param: apiCategory refers to which API we are calling. Can be "search", "title" or "id" +// Depending on that value, we will search by "t" or "s" or "i" +// param: params are the variadic list of params passed for that category +func requestAPI(apiCategory string, params ...string) (resp *http.Response, err error) { var URL *url.URL URL, err = url.Parse(baseURL) @@ -150,21 +152,21 @@ func requestAPI(s string, i string, t string, y string) (resp *http.Response, er } URL.Path += "/" parameters := url.Values{} - if len(s) > 0 { - parameters.Add("s", s) - parameters.Add("y", y) - } else if len(i) > 0 { - parameters.Add("i", i) + switch apiCategory { + case "search": + parameters.Add("s", params[0]) + parameters.Add("y", params[1]) + case "title": + parameters.Add("t", params[0]) + parameters.Add("y", params[1]) parameters.Add("plot", plot) parameters.Add("tomatoes", tomatoes) - } else if len(t) > 0 { - parameters.Add("t", t) + case "id": + parameters.Add("i", params[0]) parameters.Add("plot", plot) parameters.Add("tomatoes", tomatoes) - parameters.Add("y", y) - } else { - return nil, errors.New("Invalid Request") } + URL.RawQuery = parameters.Encode() res, err := http.Get(URL.String()) err = checkErr(res.StatusCode) diff --git a/gomdb_test.go b/gomdb_test.go index 240b4a8..30ca70a 100644 --- a/gomdb_test.go +++ b/gomdb_test.go @@ -3,9 +3,11 @@ package gomdb import "testing" func TestImdbSearchMovies(t *testing.T) { - resp, err := Search("Fight Club", "1999") + query := &QueryData{Title: "Fight Club", Year: "1999"} + resp, err := Search(query) if err != nil { - t.Error("Failed Search Movies") + t.Error(err) + return } if resp.Search[0].Title != "Fight Club" { t.Error("Wrong Movie") @@ -13,9 +15,11 @@ func TestImdbSearchMovies(t *testing.T) { } func TestImdbGetMovieByTitle(t *testing.T) { - resp, err := MovieByTitle("Fight Club", "1999") + query := &QueryData{Title: "Fight Club", Year: "1999"} + resp, err := MovieByTitle(query) if err != nil { - t.Error("Failed GetMovieByTitle") + t.Error(err) + return } if resp.Title != "Fight Club" { t.Error("Wrong Movie") @@ -25,7 +29,8 @@ func TestImdbGetMovieByTitle(t *testing.T) { func TestImdbGetMovieByImdbID(t *testing.T) { resp, err := MovieByImdbID("tt0137523") if err != nil { - t.Error("Failed GetMovieByImdbID") + t.Error(err) + return } if resp.Title != "Fight Club" { t.Error("Wrong Movie") From 58cb9dcc45cb63d23237ed0bcbab5f73448541c5 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 14 Jun 2016 22:42:01 +0530 Subject: [PATCH 4/8] Added search by type --- gomdb.go | 18 ++++++++++++------ gomdb_test.go | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/gomdb.go b/gomdb.go index fce1038..a8ff877 100644 --- a/gomdb.go +++ b/gomdb.go @@ -13,13 +13,17 @@ const ( baseURL = "http://www.omdbapi.com/?" plot = "full" tomatoes = "true" + + MovieSearch = "movie" + SeriesSearch = "series" + EpisodeSearch = "episode" ) type QueryData struct { - Title string - Year string - ImdbId string - Type string + Title string + Year string + ImdbId string + SearchType string } //SearchResult is the type for the search results @@ -80,7 +84,7 @@ type MovieResult struct { //Search for movies given a Title and year, Year is optional you can pass nil func Search(query *QueryData) (*SearchResponse, error) { - resp, err := requestAPI("search", query.Title, query.Year) + resp, err := requestAPI("search", query.Title, query.Year, query.SearchType) if err != nil { return nil, err } @@ -101,7 +105,7 @@ func Search(query *QueryData) (*SearchResponse, error) { //MovieByTitle returns a MovieResult given Title func MovieByTitle(query *QueryData) (*MovieResult, error) { - resp, err := requestAPI("title", query.Title, query.Year) + resp, err := requestAPI("title", query.Title, query.Year, query.SearchType) if err != nil { return nil, err } @@ -156,6 +160,8 @@ func requestAPI(apiCategory string, params ...string) (resp *http.Response, err case "search": parameters.Add("s", params[0]) parameters.Add("y", params[1]) + // TODO: validate params to only the right options + parameters.Add("type", params[2]) case "title": parameters.Add("t", params[0]) parameters.Add("y", params[1]) diff --git a/gomdb_test.go b/gomdb_test.go index 30ca70a..09226f4 100644 --- a/gomdb_test.go +++ b/gomdb_test.go @@ -3,7 +3,7 @@ package gomdb import "testing" func TestImdbSearchMovies(t *testing.T) { - query := &QueryData{Title: "Fight Club", Year: "1999"} + query := &QueryData{Title: "Fight Club", Year: "1999", SearchType: MovieSearch} resp, err := Search(query) if err != nil { t.Error(err) From 0658b245d2006dfda9c68bc892700e5ef7eec048 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Wed, 15 Jun 2016 12:18:48 +0530 Subject: [PATCH 5/8] Strengthening unit tests --- gomdb.go | 3 +- gomdb_test.go | 147 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 126 insertions(+), 24 deletions(-) diff --git a/gomdb.go b/gomdb.go index a8ff877..4a72693 100644 --- a/gomdb.go +++ b/gomdb.go @@ -19,6 +19,7 @@ const ( EpisodeSearch = "episode" ) +// QueryData is the type to create the search query type QueryData struct { Title string Year string @@ -160,11 +161,11 @@ func requestAPI(apiCategory string, params ...string) (resp *http.Response, err case "search": parameters.Add("s", params[0]) parameters.Add("y", params[1]) - // TODO: validate params to only the right options parameters.Add("type", params[2]) case "title": parameters.Add("t", params[0]) parameters.Add("y", params[1]) + parameters.Add("type", params[2]) parameters.Add("plot", plot) parameters.Add("tomatoes", tomatoes) case "id": diff --git a/gomdb_test.go b/gomdb_test.go index 09226f4..42a53fd 100644 --- a/gomdb_test.go +++ b/gomdb_test.go @@ -2,37 +2,138 @@ package gomdb import "testing" -func TestImdbSearchMovies(t *testing.T) { - query := &QueryData{Title: "Fight Club", Year: "1999", SearchType: MovieSearch} - resp, err := Search(query) - if err != nil { - t.Error(err) - return +func TestSearch(t *testing.T) { + tests := []struct { + query *QueryData + title string + year string + }{ + {&QueryData{Title: "Fight Club", Year: "1999", SearchType: MovieSearch}, + "Fight Club", + "1999", + }, + {&QueryData{Title: "Her"}, + "Her", + "2013", + }, + {&QueryData{Title: "Macbeth", Year: "2015"}, + "Macbeth", + "2015", + }, } - if resp.Search[0].Title != "Fight Club" { - t.Error("Wrong Movie") + + for i, item := range tests { + resp, err := Search(item.query) + if err != nil { + t.Errorf("Test[%d]: %s", i, err) + continue + } + if resp.Search[0].Title != item.title { + t.Errorf("Test[%d]: Expected- %s, Got- %s", i, item.title, resp.Search[0].Title) + continue + } + if resp.Search[0].Year != item.year { + t.Errorf("Test[%d]: Expected- %s, Got- %s", i, item.year, resp.Search[0].Year) + continue + } } } -func TestImdbGetMovieByTitle(t *testing.T) { - query := &QueryData{Title: "Fight Club", Year: "1999"} - resp, err := MovieByTitle(query) - if err != nil { - t.Error(err) - return +func TestFailSearch(t *testing.T) { + tests := []struct { + query *QueryData + }{ + {&QueryData{Title: "Game of Thrones", Year: "2001"}}, + {&QueryData{Title: "Dexter", SearchType: EpisodeSearch}}, } - if resp.Title != "Fight Club" { - t.Error("Wrong Movie") + + for i, item := range tests { + _, err := Search(item.query) + if err == nil { + t.Errorf("Test[%d]: Got nil error", i) + continue + } + // Checking for strings is bad. But the API might change. + if err.Error() != "Movie not found!" { + t.Errorf("Test[%d]: Unexpected value- %s, Got- %s", i, err) + continue + } } } -func TestImdbGetMovieByImdbID(t *testing.T) { - resp, err := MovieByImdbID("tt0137523") - if err != nil { - t.Error(err) - return +func TestMovieByTitle(t *testing.T) { + tests := []struct { + query *QueryData + title string + year string + }{ + {&QueryData{Title: "Fight Club", Year: "1999", SearchType: MovieSearch}, + "Fight Club", + "1999", + }, + {&QueryData{Title: "Her"}, + "Her", + "2013", + }, + {&QueryData{Title: "Macbeth", Year: "2015"}, + "Macbeth", + "2015", + }, } - if resp.Title != "Fight Club" { - t.Error("Wrong Movie") + + for i, item := range tests { + resp, err := MovieByTitle(item.query) + if err != nil { + t.Errorf("Test[%d]: %s", i, err) + continue + } + if resp.Title != item.title { + t.Errorf("Test[%d]: Expected- %s, Got- %s", i, item.title, resp.Title) + continue + } + if resp.Year != item.year { + t.Errorf("Test[%d]: Expected- %s, Got- %s", i, item.year, resp.Year) + continue + } + } +} + +func TestMovieByImdbID(t *testing.T) { + tests := []struct { + id string + title string + year string + }{ + { + "tt0137523", + "Fight Club", + "1999", + }, + { + "tt1798709", + "Her", + "2013", + }, + { + "tt2884018", + "Macbeth", + "2015", + }, + } + + for i, item := range tests { + resp, err := MovieByImdbID(item.id) + if err != nil { + t.Errorf("Test[%d]: %s", i, err) + continue + } + if resp.Title != item.title { + t.Errorf("Test[%d]: Expected- %s, Got- %s", i, item.title, resp.Title) + continue + } + if resp.Year != item.year { + t.Errorf("Test[%d]: Expected- %s, Got- %s", i, item.year, resp.Year) + continue + } } } From 44efcabb0683bdf39f2045a9c7af0af9b915f99d Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Wed, 15 Jun 2016 12:29:01 +0530 Subject: [PATCH 6/8] Checking for invalid category --- gomdb.go | 10 +++++++++- gomdb_test.go | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/gomdb.go b/gomdb.go index 4a72693..564d522 100644 --- a/gomdb.go +++ b/gomdb.go @@ -151,10 +151,18 @@ func MovieByImdbID(id string) (*MovieResult, error) { func requestAPI(apiCategory string, params ...string) (resp *http.Response, err error) { var URL *url.URL URL, err = url.Parse(baseURL) - if err != nil { return nil, err } + + // Checking for invalid category + if len(params) > 1 && params[2] != "" { + if params[2] != MovieSearch && + params[2] != SeriesSearch && + params[2] != EpisodeSearch { + return nil, errors.New("Invalid search category- " + params[2]) + } + } URL.Path += "/" parameters := url.Values{} switch apiCategory { diff --git a/gomdb_test.go b/gomdb_test.go index 42a53fd..4a26515 100644 --- a/gomdb_test.go +++ b/gomdb_test.go @@ -61,6 +61,28 @@ func TestFailSearch(t *testing.T) { } } +func TestInvalidCategory(t *testing.T) { + tests := []struct { + query *QueryData + }{ + {&QueryData{Title: "Game of Thrones", Year: "2001", SearchType: "bad"}}, + {&QueryData{Title: "Dexter", SearchType: "bad"}}, + } + + for i, item := range tests { + _, err := Search(item.query) + if err == nil { + t.Errorf("Test[%d]: Got nil error", i) + continue + } + // Checking for strings is bad. But the error type is formatted + if err.Error() != "Invalid search category- bad" { + t.Errorf("Test[%d]: Unexpected value- %s, Got- %s", i, err) + continue + } + } +} + func TestMovieByTitle(t *testing.T) { tests := []struct { query *QueryData From 783cdb77f5723262e5f64eba58f246c073f1ab6b Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Wed, 15 Jun 2016 12:37:45 +0530 Subject: [PATCH 7/8] Update README --- README.md | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1449bab..1e5b09a 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,42 @@ I *strongly* encourage you to check it out and contribute to keep it growing. *** Project Usage ------------- -The API usage is very simple. Just import the go-imdb package +The API usage is very simple. - import ( - imdb "github.com/eefret/go-imdb" - ) +```go +package main -And use any of the methods +import ( + "fmt" + "github.com/efret/gomdb" +) + +func main() { + query := &gomdb.QueryData{Title: "Macbeth", SearchType: gomdb.MovieSearch} + res, err := gomdb.Search(query) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(res.Search) + + query = &gomdb.QueryData{Title: "Macbeth", Year: "2015"} + res2, err := gomdb.MovieByTitle(query) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(res2) + + res3, err := gomdb.MovieByImdbID("tt2884018") + if err != nil { + fmt.Println(err) + return + } + fmt.Println(res3) +} +``` - res, err := imdb.Search("The fifth element", "") - res2, err := imdb.MovieByTitle("True Grit", "1969") - res3, err := imdb.MovieByImdbID("tt2015381") See the project documentation to see the Response Objects and stuff From 696886438c8ffb9a7c0f5d85a64ce625c2f7ea04 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Mon, 20 Jun 2016 20:10:17 +0530 Subject: [PATCH 8/8] Fixing import library name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e5b09a..ca96eb9 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ package main import ( "fmt" - "github.com/efret/gomdb" + "github.com/eefret/gomdb" ) func main() {