diff --git a/front/src/BookListElement.vue b/front/src/BookListElement.vue
index f853e8e..df01e8c 100644
--- a/front/src/BookListElement.vue
+++ b/front/src/BookListElement.vue
@@ -31,7 +31,7 @@ function openBook() {
if (props.id != 0) {
router.push(`/book/${props.id}`);
} else {
- console.log("Open Library Id : " + props.openlibraryid);
+ router.push(`/importopenlibrary/${props.openlibraryid}`)
}
}
diff --git a/front/src/OpenLibraryImport.vue b/front/src/OpenLibraryImport.vue
new file mode 100644
index 0000000..83afd25
--- /dev/null
+++ b/front/src/OpenLibraryImport.vue
@@ -0,0 +1,32 @@
+
+
+
+ Importing {{props.openlibraryid}}...
+ Importing {{props.openlibraryid}}...
+
+
+
diff --git a/front/src/api.js b/front/src/api.js
index 6f072df..937a9ef 100644
--- a/front/src/api.js
+++ b/front/src/api.js
@@ -62,6 +62,10 @@ export function postBook(book) {
return genericPayloadCall('/book', book.value, 'POST')
}
+export async function postImportBook(id) {
+ return genericPayloadCall('/importbook', {openlibraryid: id}, 'POST');
+}
+
export async function putReadBook(bookId) {
return genericPayloadCall('/book/' + bookId + "/read", {read: true}, 'PUT')
}
diff --git a/front/src/router.js b/front/src/router.js
index 33a9d02..c7262f6 100644
--- a/front/src/router.js
+++ b/front/src/router.js
@@ -8,12 +8,14 @@ import SignUp from './SignUp.vue'
import LogIn from './LogIn.vue'
import Home from './Home.vue'
import SearchBook from './SearchBook.vue'
+import OpenLibraryImport from './OpenLibraryImport.vue'
import { useAuthStore } from './auth.store'
const routes = [
{ path: '/', component: Home },
{ path: '/books', component: BooksBrowser },
{ path: '/book/:id', component: BookForm, props: true },
+ { path: '/importopenlibrary/:openlibraryid', component: OpenLibraryImport, props: true },
{ path: '/author/:id', component: AuthorForm, props: true },
{ path: '/search/:searchterm', component: SearchBook, props: true },
{ path: '/add', component: AddBook },
diff --git a/internal/apitest/get_book_test.go b/internal/apitest/get_book_test.go
index 40ed96f..e8238a4 100644
--- a/internal/apitest/get_book_test.go
+++ b/internal/apitest/get_book_test.go
@@ -15,6 +15,7 @@ type fetchedBook struct {
Title string `json:"title" binding:"required,max=300"`
Author string `json:"author" binding:"max=100"`
ISBN string `json:"isbn"`
+ OpenLibraryId string `json:"openlibraryid"`
Summary string `json:"summary"`
Rating int `json:"rating"`
Read bool `json:"read"`
diff --git a/internal/apitest/post_importbook_test.go b/internal/apitest/post_importbook_test.go
new file mode 100644
index 0000000..a41e7bf
--- /dev/null
+++ b/internal/apitest/post_importbook_test.go
@@ -0,0 +1,66 @@
+package apitest
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "strconv"
+ "strings"
+ "testing"
+
+ "git.artlef.fr/PersonalLibraryManager/internal/testutils"
+ "github.com/stretchr/testify/assert"
+)
+
+type hasId struct {
+ ID uint `json:"id"`
+}
+
+func TestPostImportBookHandler_Ok(t *testing.T) {
+ id := testPostImportBookHandler(t, "OL21177W", http.StatusOK)
+ book := testGetBook(t, strconv.FormatUint(uint64(id), 10), 200)
+ assert.Equal(t, "Wuthering Heights", book.Title)
+ assert.Equal(t, "Emily Brontë", book.Author)
+ assert.Equal(t, "OL21177W", book.OpenLibraryId)
+}
+
+func TestPostImportBookHandler_OkAuthorKey(t *testing.T) {
+ id := testPostImportBookHandler(t, "OL7525169M", http.StatusOK)
+ book := testGetBook(t, strconv.FormatUint(uint64(id), 10), 200)
+ assert.Equal(t, "Dr. Bloodmoney, or How We Got Along After the Bomb", book.Title)
+ assert.Equal(t, "Philip K. Dick", book.Author)
+ assert.Equal(t, "OL7525169M", book.OpenLibraryId)
+}
+
+func TestPostImportBookHandler_NoOLID(t *testing.T) {
+ testPostImportBookHandler(t, "", http.StatusBadRequest)
+}
+
+func testPostImportBookHandler(t *testing.T, openlibraryid string, expectedCode int) uint {
+ router := testutils.TestSetup()
+ w := httptest.NewRecorder()
+
+ token := testutils.ConnectDemoUser(router)
+ queryJson := `{
+ "openlibraryid":"%s"
+ }`
+ queryJson = fmt.Sprintf(queryJson, openlibraryid)
+ req, _ := http.NewRequest("POST", "/importbook",
+ strings.NewReader(string(queryJson)))
+ req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
+ router.ServeHTTP(w, req)
+
+ assert.Equal(t, expectedCode, w.Code)
+
+ if w.Code == 200 {
+ var parsedId hasId
+ err := json.Unmarshal(w.Body.Bytes(), &parsedId)
+ if err != nil {
+ t.Error(err)
+ }
+ return parsedId.ID
+ } else {
+ return 0
+ }
+}
diff --git a/internal/model/author.go b/internal/model/author.go
index 2df7e0a..d56a646 100644
--- a/internal/model/author.go
+++ b/internal/model/author.go
@@ -4,6 +4,7 @@ import "gorm.io/gorm"
type Author struct {
gorm.Model
- Name string
- Description string
+ Name string
+ Description string
+ OpenLibraryId string
}
diff --git a/internal/openlibrary/openlibrary.go b/internal/openlibrary/openlibrary.go
index 17cdca7..b55f3d0 100644
--- a/internal/openlibrary/openlibrary.go
+++ b/internal/openlibrary/openlibrary.go
@@ -2,61 +2,44 @@ package openlibrary
import (
"encoding/json"
- "io"
"net/http"
"net/url"
"strconv"
- "strings"
)
-type OpenLibraryQueryResult struct {
- Books []OpenLibraryBook `json:"docs"`
- NumFound int `json:"numFound"`
-}
-
-type OpenLibraryBook struct {
- Title string `json:"title"`
- Authors []string `json:"author_name"`
- OpenLibraryId string `json:"cover_edition_key"`
-}
-
-func CallOpenLibrary(searchterm string, limit int, offset int) (OpenLibraryQueryResult, error) {
- var queryResult OpenLibraryQueryResult
+func computeOpenLibraryUrl(paths ...string) (*url.URL, error) {
baseUrl := "https://openlibrary.org"
- booksApiUrl := "search.json"
u, err := url.Parse(baseUrl)
if err != nil {
- return queryResult, err
+ return nil, err
}
- u = u.JoinPath(booksApiUrl)
- if limit != 0 {
- addQueryParamInt(u, "limit", limit)
+ for _, p := range paths {
+ u = u.JoinPath(p)
}
- if offset != 0 {
- addQueryParamInt(u, "offset", offset)
- }
- addQueryParam(u, "q", searchterm)
- client := &http.Client{}
- req, err := http.NewRequest("GET", u.String(), nil)
+ return u, nil
+}
+
+func fetchAndParseResult[T any](u *url.URL, queryResult *T) error {
+ resp, err := doOpenLibraryQuery(u)
if err != nil {
- return queryResult, err
- }
- req.Header.Add("Accept", "application/json")
- req.Header.Add("User-Agent", "PersonalLibraryManager/0.1 (artlef@protonmail.com)")
- resp, err := client.Do(req)
- if err != nil {
- return queryResult, err
+ return err
}
defer resp.Body.Close()
- bodyBytes, err := io.ReadAll(resp.Body)
+ decoder := json.NewDecoder(resp.Body)
+ err = decoder.Decode(queryResult)
+ return err
+}
+
+func doOpenLibraryQuery(u *url.URL) (*http.Response, error) {
+ client := &http.Client{}
+ req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
- return queryResult, err
+ return nil, err
}
- bodyString := string(bodyBytes)
- decoder := json.NewDecoder(strings.NewReader(bodyString))
- err = decoder.Decode(&queryResult)
- return queryResult, err
+ req.Header.Add("Accept", "application/json")
+ req.Header.Add("User-Agent", "PersonalLibraryManager/0.1 (artlef@protonmail.com)")
+ return client.Do(req)
}
func addQueryParamInt(u *url.URL, paramName string, paramValue int) {
diff --git a/internal/openlibrary/openlibrary_test.go b/internal/openlibrary/openlibrary_test.go
index 1424fdd..bf45e0f 100644
--- a/internal/openlibrary/openlibrary_test.go
+++ b/internal/openlibrary/openlibrary_test.go
@@ -7,21 +7,61 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestCallOpenLibrary(t *testing.T) {
- result, err := openlibrary.CallOpenLibrary("man in high castle", 0, 0)
+func TestCallOpenLibrarySearch(t *testing.T) {
+ result, err := openlibrary.CallOpenLibrarySearch("man in high castle", 0, 0)
assert.Nil(t, err)
- assert.Equal(t, result.NumFound, 25)
- assert.Equal(t, len(result.Books), 25)
+ assert.Equal(t, 25, result.NumFound)
+ assert.Equal(t, 25, len(result.Books))
}
-func TestCallOpenLibraryLimit(t *testing.T) {
- result, err := openlibrary.CallOpenLibrary("man in high castle", 10, 0)
+func TestCallOpenLibrarySearchLimit(t *testing.T) {
+ result, err := openlibrary.CallOpenLibrarySearch("man in high castle", 10, 0)
assert.Nil(t, err)
- assert.Equal(t, len(result.Books), 10)
+ assert.Equal(t, 10, len(result.Books))
}
-func TestCallOpenLibraryOffset(t *testing.T) {
- result, err := openlibrary.CallOpenLibrary("man in high castle", 0, 10)
+func TestCallOpenLibrarySearchOffset(t *testing.T) {
+ result, err := openlibrary.CallOpenLibrarySearch("man in high castle", 0, 10)
assert.Nil(t, err)
- assert.Equal(t, len(result.Books), 15)
+ assert.Equal(t, 15, len(result.Books))
+}
+
+func TestCallOpenLibraryBook_FirstAuthorFormat(t *testing.T) {
+ result, err := openlibrary.CallOpenLibraryBook("OL21177W")
+ assert.Nil(t, err)
+ assert.Equal(t, openlibrary.OpenLibraryBookResult{
+ Title: "Wuthering Heights",
+ Description: "Wuthering Heights is an 1847 novel by Emily Brontë, initially published under the pseudonym Ellis Bell. It concerns two families of the landed gentry living on the West Yorkshire moors, the Earnshaws and the Lintons, and their turbulent relationships with Earnshaw's adopted son, Heathcliff. The novel was influenced by Romanticism and Gothic fiction.",
+ AuthorID: "OL24529A",
+ }, result)
+}
+
+func TestCallOpenLibraryBook_SecondAuthorFormat(t *testing.T) {
+ result, err := openlibrary.CallOpenLibraryBook("OL18388220M")
+ assert.Nil(t, err)
+ assert.Equal(t, openlibrary.OpenLibraryBookResult{
+ Title: "Dr Bloodmoney",
+ Description: "",
+ AuthorID: "OL274606A",
+ }, result)
+}
+
+func TestCallOpenLibraryAuthor_SimpleBioFormat(t *testing.T) {
+ result, err := openlibrary.CallOpenLibraryAuthor("OL24529A")
+ assert.Nil(t, err)
+ expectedAuthorBio := "Emily Jane Brontë was an English novelist and poet, now best remembered for her novel [Wuthering Heights][1], a classic of English literature. Emily was the second eldest of the three surviving Brontë sisters, between Charlotte and Anne. She published under the androgynous pen name Ellis Bell. ([Source][2].)\r\n\r\n\r\n [1]: http://upstream.openlibrary.org/works/OL10427528W/Wuthering_Heights\r\n [2]: http://en.wikipedia.org/wiki/Emily_Bronte"
+ assert.Equal(t, openlibrary.OpenLibraryAuthorResult{
+ Name: "Emily Brontë",
+ Description: expectedAuthorBio,
+ }, result)
+}
+
+func TestCallOpenLibraryAuthor_OtherBioFormat(t *testing.T) {
+ result, err := openlibrary.CallOpenLibraryAuthor("OL274606A")
+ assert.Nil(t, err)
+ expectedAuthorBio := "Philip Kindred Dick was an American novelist, short story writer, and essayist whose published work during his lifetime was almost entirely in the science fiction genre. Dick explored sociological, political and metaphysical themes in novels dominated by monopolistic corporations, authoritarian governments, and altered states. In his later works, Dick's thematic focus strongly reflected his personal interest in metaphysics and theology. He often drew upon his own life experiences and addressed the nature of drug abuse, paranoia and schizophrenia, and transcendental experiences in novels such as A Scanner Darkly and VALIS.\r\n\r\nSource and more information: [Wikipedia (EN)](http://en.wikipedia.org/wiki/Philip_K._Dick)"
+ assert.Equal(t, openlibrary.OpenLibraryAuthorResult{
+ Name: "Philip K. Dick",
+ Description: expectedAuthorBio,
+ }, result)
}
diff --git a/internal/openlibrary/openlibraryauthor.go b/internal/openlibrary/openlibraryauthor.go
new file mode 100644
index 0000000..ba1a061
--- /dev/null
+++ b/internal/openlibrary/openlibraryauthor.go
@@ -0,0 +1,58 @@
+package openlibrary
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type OpenLibraryAuthorResult struct {
+ Name string
+ Description string
+}
+
+type openLibraryParsedAuthor struct {
+ Name string `json:"name" binding:"required"`
+ Description openLibraryAuthorBio `json:"bio"`
+}
+
+type openLibraryAuthorBio struct {
+ Value string
+}
+
+func (b *openLibraryAuthorBio) UnmarshalJSON(data []byte) error {
+ var possibleFormat struct {
+ Type string `json:"type"`
+ Value string `json:"value"`
+ }
+ err := json.Unmarshal(data, &possibleFormat)
+ if err != nil {
+ //if unmarshalling failed, try to decode as string
+ var value string
+ err = json.Unmarshal(data, &value)
+ if err != nil {
+ return err
+ }
+ b.Value = value
+ } else {
+ b.Value = possibleFormat.Value
+ }
+ return nil
+}
+
+func CallOpenLibraryAuthor(openLibraryId string) (OpenLibraryAuthorResult, error) {
+ var response OpenLibraryAuthorResult
+ u, err := computeOpenLibraryUrl("authors", fmt.Sprintf("%s.json", openLibraryId))
+ if err != nil {
+ return response, err
+ }
+ var queryResult openLibraryParsedAuthor
+ err = fetchAndParseResult(u, &queryResult)
+ if err != nil {
+ return response, err
+ }
+ response = OpenLibraryAuthorResult{
+ Name: queryResult.Name,
+ Description: queryResult.Description.Value,
+ }
+ return response, err
+}
diff --git a/internal/openlibrary/openlibrarybook.go b/internal/openlibrary/openlibrarybook.go
new file mode 100644
index 0000000..ab51d66
--- /dev/null
+++ b/internal/openlibrary/openlibrarybook.go
@@ -0,0 +1,93 @@
+package openlibrary
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type OpenLibraryBookResult struct {
+ Title string `json:"title"`
+ Description string `json:"description"`
+ AuthorID string `json:"author_id"`
+}
+
+type openLibraryParsedBook struct {
+ Title string `json:"title"`
+ Description string `json:"description"`
+ AuthorInfo []openLibraryBookAuthorResult `json:"authors"`
+}
+
+type openLibraryBookAuthorResult struct {
+ AuthorOLID string
+ Type string
+ Key string
+}
+
+type keyContainer struct {
+ Key string `json:"key"`
+}
+
+func (r *openLibraryBookAuthorResult) UnmarshalJSON(data []byte) error {
+
+ var parentAuthor struct {
+ AuthorKey keyContainer `json:"author"`
+ TypeKey keyContainer `json:"type"`
+ Key string `json:"key"`
+ }
+
+ if err := json.Unmarshal(data, &parentAuthor); err != nil {
+ return err
+ }
+ r.AuthorOLID = parseUrlPathToField(parentAuthor.AuthorKey.Key)
+ r.Type = parseUrlPathToField(parentAuthor.TypeKey.Key)
+ r.Key = parseUrlPathToField(parentAuthor.Key)
+ return nil
+}
+
+// some fields follow this format "/authors/OL274606A"
+// this method extracts the last part "OL274606A"
+func parseUrlPathToField(urlpath string) string {
+ splittedPath := strings.Split(urlpath, "/")
+ if len(splittedPath) > 2 {
+ return splittedPath[2]
+ } else {
+ return urlpath
+ }
+}
+
+func CallOpenLibraryBook(openLibraryId string) (OpenLibraryBookResult, error) {
+ var response OpenLibraryBookResult
+ u, err := computeOpenLibraryUrl("works", fmt.Sprintf("%s.json", openLibraryId))
+ if err != nil {
+ return response, err
+ }
+ var queryResult openLibraryParsedBook
+ err = fetchAndParseResult(u, &queryResult)
+ if err != nil {
+ return response, err
+ }
+ author := computeAuthorFromParsedBook(&queryResult)
+ response = OpenLibraryBookResult{
+ Title: queryResult.Title,
+ Description: queryResult.Description,
+ AuthorID: author,
+ }
+ return response, err
+}
+
+func computeAuthorFromParsedBook(parsedBook *openLibraryParsedBook) string {
+ authors := parsedBook.AuthorInfo
+ for _, author := range authors {
+ if author.Key != "" {
+ return author.Key
+ }
+ if author.Type == "author_role" {
+ return author.AuthorOLID
+ }
+ }
+ if len(authors) > 0 {
+ return authors[0].AuthorOLID
+ }
+ return ""
+}
diff --git a/internal/openlibrary/openlibrarysearch.go b/internal/openlibrary/openlibrarysearch.go
new file mode 100644
index 0000000..b8a76cb
--- /dev/null
+++ b/internal/openlibrary/openlibrarysearch.go
@@ -0,0 +1,29 @@
+package openlibrary
+
+type OpenLibrarySearchResult struct {
+ Books []OpenLibrarySearchBook `json:"docs"`
+ NumFound int `json:"numFound"`
+}
+
+type OpenLibrarySearchBook struct {
+ Title string `json:"title"`
+ Authors []string `json:"author_name"`
+ OpenLibraryId string `json:"cover_edition_key"`
+}
+
+func CallOpenLibrarySearch(searchterm string, limit int, offset int) (OpenLibrarySearchResult, error) {
+ var queryResult OpenLibrarySearchResult
+ u, err := computeOpenLibraryUrl("search.json")
+ if err != nil {
+ return queryResult, err
+ }
+ if limit != 0 {
+ addQueryParamInt(u, "limit", limit)
+ }
+ if offset != 0 {
+ addQueryParamInt(u, "offset", offset)
+ }
+ addQueryParam(u, "q", searchterm)
+ err = fetchAndParseResult(u, &queryResult)
+ return queryResult, err
+}
diff --git a/internal/query/query.go b/internal/query/query.go
index 1095683..c18f82a 100644
--- a/internal/query/query.go
+++ b/internal/query/query.go
@@ -10,6 +10,7 @@ type BookGet struct {
Title string `json:"title" binding:"required,max=300"`
Author string `json:"author" binding:"max=100"`
ISBN string `json:"isbn"`
+ OpenLibraryId string `json:"openlibraryid"`
Summary string `json:"summary"`
Rating int `json:"rating"`
Read bool `json:"read"`
@@ -22,7 +23,7 @@ type BookGet struct {
func FetchBookGet(db *gorm.DB, userId uint, bookId uint64) (BookGet, error) {
var book BookGet
query := db.Model(&model.Book{})
- selectQueryString := "books.title, authors.name as author, books.isbn, books.summary, " +
+ selectQueryString := "books.title, authors.name as author, books.isbn, books.open_library_id, books.summary, " +
"user_books.rating, user_books.read, user_books.want_read, " +
"DATE(user_books.start_read_date) as start_read_date, " +
"DATE(user_books.end_read_date) AS end_read_date, " +
diff --git a/internal/routes/bookpostcreate.go b/internal/routes/bookpostcreate.go
index 97e13da..65bd777 100644
--- a/internal/routes/bookpostcreate.go
+++ b/internal/routes/bookpostcreate.go
@@ -59,7 +59,7 @@ func saveBookToDb(ac appcontext.AppContext, b bookPostCreate, user *model.User)
func fetchOrCreateAuthor(ac appcontext.AppContext, name string) (*model.Author, error) {
var author model.Author
- res := ac.Db.Where("name = ?", name)
+ res := ac.Db.Where("name = ?", name).First(&author)
err := res.Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
diff --git a/internal/routes/bookpostimport.go b/internal/routes/bookpostimport.go
new file mode 100644
index 0000000..130cf9e
--- /dev/null
+++ b/internal/routes/bookpostimport.go
@@ -0,0 +1,107 @@
+package routes
+
+import (
+ "errors"
+
+ "git.artlef.fr/PersonalLibraryManager/internal/appcontext"
+ "git.artlef.fr/PersonalLibraryManager/internal/model"
+ "git.artlef.fr/PersonalLibraryManager/internal/myvalidator"
+ "git.artlef.fr/PersonalLibraryManager/internal/openlibrary"
+ "github.com/gin-gonic/gin"
+ "gorm.io/gorm"
+)
+
+type bookPostImport struct {
+ OpenLibraryId string `json:"openlibraryid" binding:"required,max=50"`
+}
+
+func PostImportBookHandler(ac appcontext.AppContext) {
+ var request bookPostImport
+ err := ac.C.ShouldBindJSON(&request)
+ if err != nil {
+ myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
+ return
+ }
+
+ user, fetchUserErr := ac.GetAuthenticatedUser()
+ if fetchUserErr != nil {
+ myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
+ return
+ }
+ openLibraryBook, err := openlibrary.CallOpenLibraryBook(request.OpenLibraryId)
+ if err != nil {
+ myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
+ return
+ }
+ book, err := saveOpenLibraryBookToDb(ac, request.OpenLibraryId, openLibraryBook, &user)
+ if err != nil {
+ myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
+ return
+ }
+ ac.C.JSON(200, gin.H{"id": book.ID})
+}
+
+func saveOpenLibraryBookToDb(ac appcontext.AppContext, openLibraryId string, openLibraryBook openlibrary.OpenLibraryBookResult, user *model.User) (*model.Book, error) {
+ author, err := fetchOrCreateOpenLibraryAuthor(ac, openLibraryBook.AuthorID)
+ if err != nil {
+ return nil, err
+ }
+ book := model.Book{
+ Title: openLibraryBook.Title,
+ Summary: openLibraryBook.Description,
+ OpenLibraryId: openLibraryId,
+ Author: *author,
+ AddedBy: *user,
+ }
+ err = ac.Db.Save(&book).Error
+ return &book, err
+}
+
+func fetchOrCreateOpenLibraryAuthor(ac appcontext.AppContext, openlibraryAuthorId string) (*model.Author, error) {
+ var author model.Author
+ res := ac.Db.Where("open_library_id = ?", openlibraryAuthorId).First(&author)
+ err := res.Error
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ newAuthor, err := createAuthorFromOpenLibrary(ac, openlibraryAuthorId)
+ if err != nil {
+ return &author, err
+ }
+ return newAuthor, nil
+ } else {
+ return &author, err
+ }
+ } else {
+ return &author, nil
+ }
+}
+
+func createAuthorFromOpenLibrary(ac appcontext.AppContext, openlibraryAuthorId string) (*model.Author, error) {
+ authorFromOL, err := openlibrary.CallOpenLibraryAuthor(openlibraryAuthorId)
+ if err != nil {
+ return nil, err
+ }
+
+ var author model.Author
+ res := ac.Db.Where("name = ?", authorFromOL.Name).First(&author)
+ err = res.Error
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ author = model.Author{
+ Name: authorFromOL.Name,
+ Description: authorFromOL.Description,
+ OpenLibraryId: openlibraryAuthorId,
+ }
+ err = ac.Db.Save(&author).Error
+ return &author, err
+ } else {
+ return nil, err
+ }
+ } else {
+ //if the author already exists, only fill the open library id
+ author.OpenLibraryId = openlibraryAuthorId
+ ac.Db.Save(&author)
+ }
+
+ return &author, err
+}
diff --git a/internal/routes/booksearchget.go b/internal/routes/booksearchget.go
index 3e3d96e..3550382 100644
--- a/internal/routes/booksearchget.go
+++ b/internal/routes/booksearchget.go
@@ -38,7 +38,7 @@ func GetSearchBooksHandler(ac appcontext.AppContext) {
if len(books) > 0 {
returnedBooks = books
} else {
- queryResult, err := openlibrary.CallOpenLibrary(searchterm, limit, offset)
+ queryResult, err := openlibrary.CallOpenLibrarySearch(searchterm, limit, offset)
if err != nil {
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
return
@@ -48,7 +48,7 @@ func GetSearchBooksHandler(ac appcontext.AppContext) {
ac.C.JSON(http.StatusOK, returnedBooks)
}
-func OpenLibraryBooksToBookSearchGet(OLbooks []openlibrary.OpenLibraryBook) []query.BookSearchGet {
+func OpenLibraryBooksToBookSearchGet(OLbooks []openlibrary.OpenLibrarySearchBook) []query.BookSearchGet {
var books []query.BookSearchGet
for _, b := range OLbooks {
bookSearchGet := query.BookSearchGet{
@@ -83,7 +83,7 @@ func GetSearchBooksCountHandler(ac appcontext.AppContext) {
if count > 0 {
finalCount = count
} else {
- queryResult, err := openlibrary.CallOpenLibrary(searchterm, 0, 0)
+ queryResult, err := openlibrary.CallOpenLibrarySearch(searchterm, 0, 0)
if err != nil {
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
return
diff --git a/internal/setup/setup.go b/internal/setup/setup.go
index edb1707..f04da82 100644
--- a/internal/setup/setup.go
+++ b/internal/setup/setup.go
@@ -66,6 +66,9 @@ func Setup(config *config.Config) *gin.Engine {
r.POST("/book", func(c *gin.Context) {
routes.PostBookHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
})
+ r.POST("/importbook", func(c *gin.Context) {
+ routes.PostImportBookHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
+ })
r.GET("/author/:id", func(c *gin.Context) {
routes.GetAuthorHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
})