diff --git a/Makefile b/Makefile index 36b7c0c..e0e45b0 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,10 @@ build-web: go test ./... go build -o bin/web main.go +build-amd64: + go build ./... + GOOS=linux GOARCH=amd64 go build -o bin/web main.go + build-cli: go build ./... go build -o bin/cli cmd/cli/main.go @@ -11,7 +15,4 @@ docker: docker build -t gunni1/lib-api:local . docker-run: - docker run -p 8080:8080 --rm --name lib-api gunni1/lib-api:local - - - + docker run -p 8080:8080 --rm --name lib-api gunni1/lib-api:local \ No newline at end of file diff --git a/library-le/client.go b/library-le/client.go index dfc2702..9b01c36 100644 --- a/library-le/client.go +++ b/library-le/client.go @@ -2,11 +2,7 @@ package libraryle import ( "errors" - "fmt" - "log" "net/http" - - "github.com/gunni1/leipzig-library-game-stock-api/domain" ) const ( @@ -52,66 +48,6 @@ type webOpacSession struct { userSessionId string } -func (libClient Client) FindAvailabelGames(branchCode int, platform string) []domain.Game { - sessionErr := libClient.openSession() - if sessionErr != nil { - fmt.Println(sessionErr) - return nil - } - request := createGameSearchRequest(branchCode, platform, libClient.session) - httpClient := http.Client{} - response, err := httpClient.Do(request) - if err != nil { - log.Println("error during search") - return nil - } - defer response.Body.Close() - - games, parseResultErr := parseGameSearchResult(response.Body) - if parseResultErr != nil { - log.Fatalln(parseResultErr) - return nil - } - return games -} - -// Search for a specific movie title in all library branches -func (libClient Client) FindMovies(title string) []domain.Movie { - sessionErr := libClient.openSession() - if sessionErr != nil { - fmt.Println(sessionErr) - return nil - } - searchRequest := createMovieSearchRequest(title, libClient.session) - httpClient := http.Client{} - searchResponse, err := httpClient.Do(searchRequest) - if err != nil { - log.Println("error during search") - return nil - } - resultTitles := parseMovieSearch(searchResponse.Body) - - movies := make([]domain.Movie, 0) - for _, resultTitle := range resultTitles { - movies = append(movies, resultTitle.loadMovieCopies(libClient.session)...) - } - //Parallel Ergebnislinks folgen und Details über Zweigstelle und Verfpgbarkeit sammeln - return movies -} - -// Load all existing copys of a result title over all library branches -func (result searchResult) loadMovieCopies(libSession webOpacSession) []domain.Movie { - request := createRequest(libSession, result.resultUrl) - - httpClient := http.Client{} - movieResponse, err := httpClient.Do(request) - if err != nil { - log.Println("error during search") - return nil - } - return parseMovieCopiesPage(result.title, movieResponse.Body) -} - func (client *Client) openSession() error { resp, err := http.Get(LIB_BASE_URL + "/webOPACClient") if err != nil { diff --git a/library-le/client_test.go b/library-le/client_test.go index c8ac1bc..924927e 100644 --- a/library-le/client_test.go +++ b/library-le/client_test.go @@ -1,7 +1,11 @@ package libraryle import ( + "bufio" + "io" + "log" "net/http" + "os" "testing" . "github.com/stretchr/testify/assert" @@ -52,20 +56,10 @@ func assertSessionCookiesExists(request *http.Request, t *testing.T) { True(t, foundUserSessionId) } -func TestMovieSearchRequestHasCookiesSet(t *testing.T) { - session := webOpacSession{jSessionId: jSessionId, userSessionId: userSessionId} - request := createMovieSearchRequest("Terminator", session) - assertSessionCookiesExists(request, t) -} - -func TestMovieSearchRequestHasQueryParamsSet(t *testing.T) { - session := webOpacSession{jSessionId: jSessionId, userSessionId: userSessionId} - request := createMovieSearchRequest("Terminator", session) - Equal(t, "submit", request.URL.Query().Get("methodToCall")) - Equal(t, "331", request.URL.Query().Get("searchCategories[0]")) - Equal(t, "500", request.URL.Query().Get("numberOfHits")) - Equal(t, "3", request.URL.Query().Get("searchRestrictionID[2]")) - Equal(t, "29", request.URL.Query().Get("searchRestrictionValue1[2]")) - Equal(t, "0", request.URL.Query().Get("selectedViewBranchlib")) - Empty(t, request.URL.Query().Get("selectedSearchBranchlib")) +func loadTestData(filePath string) io.Reader { + file, fileErr := os.Open(filePath) + if fileErr != nil { + log.Fatal(fileErr) + } + return bufio.NewReader(file) } diff --git a/library-le/game-index.go b/library-le/game-index.go new file mode 100644 index 0000000..847508c --- /dev/null +++ b/library-le/game-index.go @@ -0,0 +1,62 @@ +package libraryle + +import ( + "fmt" + "io" + "log" + "net/http" + + "github.com/PuerkitoBio/goquery" + "github.com/gunni1/leipzig-library-game-stock-api/domain" +) + +const ( + resultItemSelector string = "h2[class^=recordtitle]" + titleSelector string = "a[href^='/webOPACClient/singleHit']" + availabilitySelector string = "span[class^=textgruen]" +) + +func (libClient Client) FindAvailabelGames(branchCode int, platform string) []domain.Game { + sessionErr := libClient.openSession() + if sessionErr != nil { + fmt.Println(sessionErr) + return nil + } + request := createGameSearchRequest(branchCode, platform, libClient.session) + httpClient := http.Client{} + response, err := httpClient.Do(request) + if err != nil { + log.Println("error during search") + return nil + } + defer response.Body.Close() + + games, parseResultErr := parseGameSearchResult(response.Body) + if parseResultErr != nil { + log.Fatalln(parseResultErr) + return nil + } + return games +} + +// Takes a html as reader from a webopac search and +// try to parse it to an array of games that are listed as available. +func parseGameSearchResult(searchResult io.Reader) ([]domain.Game, error) { + doc, docErr := goquery.NewDocumentFromReader(searchResult) + if docErr != nil { + log.Println("Could not create document from response.") + return nil, docErr + } + games := make([]domain.Game, 0) + doc.Find(resultItemSelector).Each(func(i int, resultItem *goquery.Selection) { + title := resultItem.Find(titleSelector).Text() + if isGameAvailable(resultItem.Parent()) { + games = append(games, domain.Game{Title: title}) + } + }) + return games, nil +} + +func isGameAvailable(searchHitNode *goquery.Selection) bool { + return len(searchHitNode.Find(availabilitySelector).Nodes) > 0 +} diff --git a/library-le/parse_results_test.go b/library-le/game-index_test.go similarity index 50% rename from library-le/parse_results_test.go rename to library-le/game-index_test.go index 966481e..61bc492 100644 --- a/library-le/parse_results_test.go +++ b/library-le/game-index_test.go @@ -1,10 +1,6 @@ package libraryle import ( - "bufio" - "io" - "log" - "os" "testing" "github.com/gunni1/leipzig-library-game-stock-api/domain" @@ -21,28 +17,6 @@ func TestAvailability(t *testing.T) { } -func TestParseMovieCopiesResult(t *testing.T) { - testResponse := loadTestData("movie_copies_example.html") - movies := parseMovieCopiesPage("Terminator - Genesis", testResponse) - Equal(t, 6, len(movies)) - - available := 0 - for _, movie := range movies { - if movie.IsAvailable { - available++ - } - } - Equal(t, 2, available) -} - -func loadTestData(filePath string) io.Reader { - file, fileErr := os.Open(filePath) - if fileErr != nil { - log.Fatal(fileErr) - } - return bufio.NewReader(file) -} - func hasElement(games []domain.Game, title string) bool { for _, game := range games { if game.Title == title { diff --git a/library-le/parse_results.go b/library-le/search.go similarity index 56% rename from library-le/parse_results.go rename to library-le/search.go index e7c0bf6..2339f78 100644 --- a/library-le/parse_results.go +++ b/library-le/search.go @@ -1,8 +1,10 @@ package libraryle import ( + "fmt" "io" "log" + "net/http" "strings" "github.com/PuerkitoBio/goquery" @@ -10,10 +12,7 @@ import ( ) const ( - resultItemSelector string = "h2[class^=recordtitle]" - titleSelector string = "a[href^='/webOPACClient/singleHit']" - availabilitySelector string = "span[class^=textgruen]" - copiesSelector string = "#tab-content > div > div:nth-child(n+2)" + copiesSelector string = "#tab-content > div > div:nth-child(n+2)" ) type searchResult struct { @@ -21,26 +20,41 @@ type searchResult struct { resultUrl string } -// Takes a html as reader from a webopac search and -// try to parse it to an array of games that are listed as available. -func parseGameSearchResult(searchResult io.Reader) ([]domain.Game, error) { - doc, docErr := goquery.NewDocumentFromReader(searchResult) - if docErr != nil { - log.Println("Could not create document from response.") - return nil, docErr +// Search for a specific movie title in all library branches +func (libClient Client) FindMovies(title string) []domain.Movie { + sessionErr := libClient.openSession() + if sessionErr != nil { + fmt.Println(sessionErr) + return nil } - games := make([]domain.Game, 0) - doc.Find(resultItemSelector).Each(func(i int, resultItem *goquery.Selection) { - title := resultItem.Find(titleSelector).Text() - if isGameAvailable(resultItem.Parent()) { - games = append(games, domain.Game{Title: title}) - } - }) - return games, nil + searchRequest := createMovieSearchRequest(title, libClient.session) + httpClient := http.Client{} + searchResponse, err := httpClient.Do(searchRequest) + if err != nil { + log.Println("error during search") + return nil + } + resultTitles := parseMovieSearch(searchResponse.Body) + + movies := make([]domain.Movie, 0) + for _, resultTitle := range resultTitles { + movies = append(movies, resultTitle.loadMovieCopies(libClient.session)...) + } + //Parallel Ergebnislinks folgen und Details über Zweigstelle und Verfpgbarkeit sammeln + return movies } -func isGameAvailable(searchHitNode *goquery.Selection) bool { - return len(searchHitNode.Find(availabilitySelector).Nodes) > 0 +// Load all existing copys of a result title over all library branches +func (result searchResult) loadMovieCopies(libSession webOpacSession) []domain.Movie { + request := createRequest(libSession, result.resultUrl) + + httpClient := http.Client{} + movieResponse, err := httpClient.Do(request) + if err != nil { + log.Println("error during search") + return nil + } + return parseMovieCopiesPage(result.title, movieResponse.Body) } func parseMovieSearch(searchResponse io.Reader) []searchResult { diff --git a/library-le/search_test.go b/library-le/search_test.go new file mode 100644 index 0000000..dc6edd7 --- /dev/null +++ b/library-le/search_test.go @@ -0,0 +1,39 @@ +package libraryle + +import ( + "testing" + + . "github.com/stretchr/testify/assert" +) + +func TestParseMovieCopiesResult(t *testing.T) { + testResponse := loadTestData("movie_copies_example.html") + movies := parseMovieCopiesPage("Terminator - Genesis", testResponse) + Equal(t, 6, len(movies)) + + available := 0 + for _, movie := range movies { + if movie.IsAvailable { + available++ + } + } + Equal(t, 2, available) +} + +func TestMovieSearchRequestHasCookiesSet(t *testing.T) { + session := webOpacSession{jSessionId: jSessionId, userSessionId: userSessionId} + request := createMovieSearchRequest("Terminator", session) + assertSessionCookiesExists(request, t) +} + +func TestMovieSearchRequestHasQueryParamsSet(t *testing.T) { + session := webOpacSession{jSessionId: jSessionId, userSessionId: userSessionId} + request := createMovieSearchRequest("Terminator", session) + Equal(t, "submit", request.URL.Query().Get("methodToCall")) + Equal(t, "331", request.URL.Query().Get("searchCategories[0]")) + Equal(t, "500", request.URL.Query().Get("numberOfHits")) + Equal(t, "3", request.URL.Query().Get("searchRestrictionID[2]")) + Equal(t, "29", request.URL.Query().Get("searchRestrictionValue1[2]")) + Equal(t, "0", request.URL.Query().Get("selectedViewBranchlib")) + Empty(t, request.URL.Query().Get("selectedSearchBranchlib")) +}