Switch from open library API to Inventaire API
This commit is contained in:
@@ -107,6 +107,7 @@
|
||||
<h3 class="subtitle">{{data.author}}</h3>
|
||||
<p>{{data.summary}}</p>
|
||||
<div class="my-5" v-if="data.isbn">ISBN: {{data.isbn}}</div>
|
||||
<div class="my-5" v-if="data.inventaireid">Inventaire ID: {{data.inventaireid}}</div>
|
||||
<div class="my-5" v-if="data.openlibraryid">OLID: {{data.openlibraryid}}</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
const props = defineProps({
|
||||
id: Number,
|
||||
openlibraryid: String,
|
||||
inventaireid: String,
|
||||
title: String,
|
||||
author: String,
|
||||
rating: Number,
|
||||
@@ -31,7 +31,7 @@ function openBook() {
|
||||
if (props.id != 0) {
|
||||
router.push(`/book/${props.id}`);
|
||||
} else {
|
||||
router.push(`/importopenlibrary/${props.openlibraryid}`)
|
||||
router.push(`/importinventaire/${props.inventaireid}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
const router = useRouter();
|
||||
|
||||
const props = defineProps({
|
||||
openlibraryid: String
|
||||
inventaireid: String
|
||||
});
|
||||
const error = ref(null);
|
||||
const data = ref(null);
|
||||
|
||||
async function importOpenLibraryId() {
|
||||
const res = await postImportBook(props.openlibraryid);
|
||||
async function importInventaireId() {
|
||||
const res = await postImportBook(props.inventaireid, navigator.language.substring(0,2));
|
||||
const json = await res.json();
|
||||
if (res.ok) {
|
||||
router.push(`/book/${json.id}`);
|
||||
@@ -21,12 +21,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
importOpenLibraryId();
|
||||
importInventaireId();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="error">Importing {{props.openlibraryid}}...</div>
|
||||
<div v-else-if="!data">Importing {{props.openlibraryid}}...</div>
|
||||
<div v-if="error">{{error}}</div>
|
||||
<div v-else-if="!data">Importing {{props.inventaireid}}...</div>
|
||||
</template>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if (typeof searchterm.value === "undefined" || searchterm.value === "") {
|
||||
return
|
||||
}
|
||||
router.push('/search/' + encodeURIComponent(searchterm.value));
|
||||
router.push('/search/' + searchterm.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ export function postBook(book) {
|
||||
return genericPayloadCall('/book', book.value, 'POST')
|
||||
}
|
||||
|
||||
export async function postImportBook(id) {
|
||||
return genericPayloadCall('/importbook', {openlibraryid: id}, 'POST');
|
||||
export async function postImportBook(id, language) {
|
||||
return genericPayloadCall('/importbook', {inventaireid: id, lang: language}, 'POST');
|
||||
}
|
||||
|
||||
export async function putReadBook(bookId) {
|
||||
|
||||
@@ -8,14 +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 InventaireImport from './InventaireImport.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: '/importinventaire/:inventaireid', component: InventaireImport, props: true },
|
||||
{ path: '/author/:id', component: AuthorForm, props: true },
|
||||
{ path: '/search/:searchterm', component: SearchBook, props: true },
|
||||
{ path: '/add', component: AddBook },
|
||||
|
||||
@@ -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"`
|
||||
InventaireID string `json:"inventaireid"`
|
||||
OpenLibraryId string `json:"openlibraryid"`
|
||||
Summary string `json:"summary"`
|
||||
Rating int `json:"rating"`
|
||||
|
||||
@@ -18,19 +18,19 @@ type hasId struct {
|
||||
}
|
||||
|
||||
func TestPostImportBookHandler_Ok(t *testing.T) {
|
||||
id := testPostImportBookHandler(t, "OL21177W", http.StatusOK)
|
||||
id := testPostImportBookHandler(t, "Q202975", 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)
|
||||
assert.Equal(t, "Les Hauts de Hurlevent", book.Title)
|
||||
assert.Equal(t, "Emily Brontë", book.Author)
|
||||
assert.Equal(t, "Q202975", book.InventaireID)
|
||||
}
|
||||
|
||||
func TestPostImportBookHandler_OkAuthorKey(t *testing.T) {
|
||||
id := testPostImportBookHandler(t, "OL7525169M", http.StatusOK)
|
||||
id := testPostImportBookHandler(t, "Q1317915", 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, "Dr Bloodmoney", book.Title)
|
||||
assert.Equal(t, "Philip K. Dick", book.Author)
|
||||
assert.Equal(t, "OL7525169M", book.OpenLibraryId)
|
||||
assert.Equal(t, "Q1317915", book.InventaireID)
|
||||
}
|
||||
|
||||
func TestPostImportBookHandler_NoOLID(t *testing.T) {
|
||||
@@ -43,7 +43,8 @@ func testPostImportBookHandler(t *testing.T, openlibraryid string, expectedCode
|
||||
|
||||
token := testutils.ConnectDemoUser(router)
|
||||
queryJson := `{
|
||||
"openlibraryid":"%s"
|
||||
"inventaireid":"%s",
|
||||
"lang":"fr"
|
||||
}`
|
||||
queryJson = fmt.Sprintf(queryJson, openlibraryid)
|
||||
req, _ := http.NewRequest("POST", "/importbook",
|
||||
|
||||
66
internal/callapiutils/callapiutils.go
Normal file
66
internal/callapiutils/callapiutils.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package callapiutils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func AddQueryParamInt(u *url.URL, paramName string, paramValue int) {
|
||||
AddQueryParam(u, paramName, strconv.Itoa(paramValue))
|
||||
}
|
||||
|
||||
func AddQueryParam(u *url.URL, paramName string, paramValue string) {
|
||||
q := u.Query()
|
||||
q.Set(paramName, paramValue)
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
func FetchAndParseResult[T any](u *url.URL, queryResult *T) error {
|
||||
resp, err := DoApiQuery(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
bodyError, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Call to %s returned code %d:\n%s", u.String(), resp.StatusCode, string(bodyError))
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
err = decoder.Decode(queryResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func DoApiQuery(u *url.URL) (*http.Response, error) {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("User-Agent", "PersonalLibraryManager/0.1 (artlef@protonmail.com)")
|
||||
return client.Do(req)
|
||||
}
|
||||
|
||||
func ComputeUrl(baseUrl string, paths ...string) (*url.URL, error) {
|
||||
u, err := url.Parse(baseUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, p := range paths {
|
||||
u = u.JoinPath(p)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
41
internal/inventaire/inventaire.go
Normal file
41
internal/inventaire/inventaire.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package inventaire
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/callapiutils"
|
||||
)
|
||||
|
||||
type InventaireSearchResult struct {
|
||||
Results []InventaireSearchBook `json:"results"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type InventaireSearchBook struct {
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func computeInventaireUrl(paths ...string) (*url.URL, error) {
|
||||
baseUrl := "https://inventaire.io/api"
|
||||
return callapiutils.ComputeUrl(baseUrl, paths...)
|
||||
}
|
||||
|
||||
func CallInventaireSearch(searchterm string, limit int, offset int) (InventaireSearchResult, error) {
|
||||
var queryResult InventaireSearchResult
|
||||
u, err := computeInventaireUrl("search")
|
||||
if err != nil {
|
||||
return queryResult, err
|
||||
}
|
||||
if limit != 0 {
|
||||
callapiutils.AddQueryParamInt(u, "limit", limit)
|
||||
}
|
||||
if offset != 0 {
|
||||
callapiutils.AddQueryParamInt(u, "offset", offset)
|
||||
}
|
||||
callapiutils.AddQueryParam(u, "types", "works")
|
||||
callapiutils.AddQueryParam(u, "search", searchterm)
|
||||
err = callapiutils.FetchAndParseResult(u, &queryResult)
|
||||
return queryResult, err
|
||||
}
|
||||
46
internal/inventaire/inventaire_test.go
Normal file
46
internal/inventaire/inventaire_test.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package inventaire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCallInventaireSearch_NoLimit(t *testing.T) {
|
||||
result, err := CallInventaireSearch("salammbo", 0, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, 17, result.Total)
|
||||
assert.Equal(t, 10, len(result.Results))
|
||||
}
|
||||
|
||||
func TestCallInventaireSearch_Limit(t *testing.T) {
|
||||
result, err := CallInventaireSearch("salammbo", 5, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, 17, result.Total)
|
||||
assert.Equal(t, 5, len(result.Results))
|
||||
}
|
||||
|
||||
func TestCallInventaireSearch_Offset(t *testing.T) {
|
||||
result, err := CallInventaireSearch("salammbo", 0, 15)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, 17, result.Total)
|
||||
assert.Equal(t, 2, len(result.Results))
|
||||
}
|
||||
|
||||
func TestCallInventaireBook_BraveNewWorld(t *testing.T) {
|
||||
result, err := CallInventaireBook("Q191949", "fr")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, "Le Meilleur des mondes", result.Title)
|
||||
assert.Equal(t, "roman de Aldous Huxley", result.Description)
|
||||
assert.Equal(t, "Q81447", result.Author.ID)
|
||||
assert.Equal(t, "Aldous Huxley", result.Author.Name)
|
||||
assert.Equal(t, "écrivain, romancier et philosophe britannique (1894–1963)", result.Author.Description)
|
||||
}
|
||||
102
internal/inventaire/inventairebook.go
Normal file
102
internal/inventaire/inventairebook.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package inventaire
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/callapiutils"
|
||||
)
|
||||
|
||||
type InventaireBookResult struct {
|
||||
ID string
|
||||
Lang string
|
||||
Title string
|
||||
Description string
|
||||
Author *InventaireAuthorResult
|
||||
}
|
||||
|
||||
type InventaireAuthorResult struct {
|
||||
ID string
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
func (i *InventaireBookResult) UnmarshalJSON(b []byte) error {
|
||||
var parsed struct {
|
||||
Entities map[string]json.RawMessage
|
||||
}
|
||||
err := json.Unmarshal(b, &parsed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entity := range parsed.Entities {
|
||||
|
||||
var inventaireEntity struct {
|
||||
WdId string `json:"wdId"`
|
||||
Type string `json:"type"`
|
||||
Labels map[string]json.RawMessage `json:"labels"`
|
||||
Descriptions map[string]json.RawMessage `json:"descriptions"`
|
||||
}
|
||||
|
||||
err := json.Unmarshal(entity, &inventaireEntity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if inventaireEntity.WdId == i.ID {
|
||||
title, err := findLangageField(inventaireEntity.Labels, i.Lang)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Title = title
|
||||
description, err := findLangageField(inventaireEntity.Descriptions, i.Lang)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Description = description
|
||||
} else if inventaireEntity.Type == "human" {
|
||||
a := InventaireAuthorResult{ID: inventaireEntity.WdId}
|
||||
name, err := findLangageField(inventaireEntity.Labels, i.Lang)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Name = name
|
||||
desc, err := findLangageField(inventaireEntity.Descriptions, i.Lang)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Description = desc
|
||||
i.Author = &a
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func findLangageField(multipleMessageFields map[string]json.RawMessage, lang string) (string, error) {
|
||||
fieldToParse, ok := multipleMessageFields[lang]
|
||||
if ok {
|
||||
var parsedField string
|
||||
err := json.Unmarshal(fieldToParse, &parsedField)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return parsedField, err
|
||||
} else {
|
||||
return "", errors.New("multi lang field could not be parsed")
|
||||
}
|
||||
}
|
||||
|
||||
func CallInventaireBook(inventaireId string, lang string) (InventaireBookResult, error) {
|
||||
queryResult := InventaireBookResult{ID: inventaireId, Lang: lang}
|
||||
u, err := computeInventaireUrl("entities")
|
||||
if err != nil {
|
||||
return queryResult, err
|
||||
}
|
||||
callapiutils.AddQueryParam(u, "action", "by-uris")
|
||||
callapiutils.AddQueryParam(u, "relatives", "wdt:P50")
|
||||
callapiutils.AddQueryParam(u, "lang", lang)
|
||||
callapiutils.AddQueryParam(u, "uris", "wd:"+inventaireId)
|
||||
|
||||
err = callapiutils.FetchAndParseResult(u, &queryResult)
|
||||
return queryResult, err
|
||||
}
|
||||
@@ -6,5 +6,6 @@ type Author struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
Description string
|
||||
InventaireID string
|
||||
OpenLibraryId string
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ type Book struct {
|
||||
gorm.Model
|
||||
Title string `json:"title" gorm:"not null"`
|
||||
ISBN string `json:"isbn"`
|
||||
InventaireID string `json:"inventaireid"`
|
||||
OpenLibraryId string `json:"openlibraryid"`
|
||||
Summary string `json:"summary"`
|
||||
Author Author
|
||||
|
||||
@@ -1,53 +1,12 @@
|
||||
package openlibrary
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/callapiutils"
|
||||
)
|
||||
|
||||
func computeOpenLibraryUrl(paths ...string) (*url.URL, error) {
|
||||
baseUrl := "https://openlibrary.org"
|
||||
u, err := url.Parse(baseUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, p := range paths {
|
||||
u = u.JoinPath(p)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func fetchAndParseResult[T any](u *url.URL, queryResult *T) error {
|
||||
resp, err := doOpenLibraryQuery(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
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 nil, 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) {
|
||||
addQueryParam(u, paramName, strconv.Itoa(paramValue))
|
||||
}
|
||||
|
||||
func addQueryParam(u *url.URL, paramName string, paramValue string) {
|
||||
q := u.Query()
|
||||
q.Set(paramName, paramValue)
|
||||
u.RawQuery = q.Encode()
|
||||
return callapiutils.ComputeUrl(baseUrl, paths...)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package openlibrary
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/callapiutils"
|
||||
)
|
||||
|
||||
type OpenLibraryAuthorResult struct {
|
||||
@@ -46,7 +48,7 @@ func CallOpenLibraryAuthor(openLibraryId string) (OpenLibraryAuthorResult, error
|
||||
return response, err
|
||||
}
|
||||
var queryResult openLibraryParsedAuthor
|
||||
err = fetchAndParseResult(u, &queryResult)
|
||||
err = callapiutils.FetchAndParseResult(u, &queryResult)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/callapiutils"
|
||||
)
|
||||
|
||||
type OpenLibraryBookResult struct {
|
||||
@@ -63,7 +65,7 @@ func CallOpenLibraryBook(openLibraryId string) (OpenLibraryBookResult, error) {
|
||||
return response, err
|
||||
}
|
||||
var queryResult openLibraryParsedBook
|
||||
err = fetchAndParseResult(u, &queryResult)
|
||||
err = callapiutils.FetchAndParseResult(u, &queryResult)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package openlibrary
|
||||
|
||||
import "git.artlef.fr/PersonalLibraryManager/internal/callapiutils"
|
||||
|
||||
type OpenLibrarySearchResult struct {
|
||||
Books []OpenLibrarySearchBook `json:"docs"`
|
||||
NumFound int `json:"numFound"`
|
||||
@@ -18,12 +20,12 @@ func CallOpenLibrarySearch(searchterm string, limit int, offset int) (OpenLibrar
|
||||
return queryResult, err
|
||||
}
|
||||
if limit != 0 {
|
||||
addQueryParamInt(u, "limit", limit)
|
||||
callapiutils.AddQueryParamInt(u, "limit", limit)
|
||||
}
|
||||
if offset != 0 {
|
||||
addQueryParamInt(u, "offset", offset)
|
||||
callapiutils.AddQueryParamInt(u, "offset", offset)
|
||||
}
|
||||
addQueryParam(u, "q", searchterm)
|
||||
err = fetchAndParseResult(u, &queryResult)
|
||||
callapiutils.AddQueryParam(u, "q", searchterm)
|
||||
err = callapiutils.FetchAndParseResult(u, &queryResult)
|
||||
return queryResult, err
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
InventaireId string `json:"inventaireid"`
|
||||
OpenLibraryId string `json:"openlibraryid"`
|
||||
Summary string `json:"summary"`
|
||||
Rating int `json:"rating"`
|
||||
@@ -23,7 +24,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.open_library_id, books.summary, " +
|
||||
selectQueryString := "books.title, authors.name as author, books.isbn, books.inventaire_id, 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, " +
|
||||
|
||||
@@ -12,7 +12,7 @@ type BookSearchGet struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title" binding:"required,max=300"`
|
||||
Author string `json:"author" binding:"max=100"`
|
||||
OpenLibraryId string `json:"openlibraryid"`
|
||||
InventaireID string `json:"inventaireid"`
|
||||
Rating int `json:"rating"`
|
||||
Read bool `json:"read"`
|
||||
WantRead bool `json:"wantread"`
|
||||
@@ -70,7 +70,7 @@ func fetchBookSearchQuery(db *gorm.DB, userId uint, searchterm string) *gorm.DB
|
||||
|
||||
func fetchBookSearchQueryBuilder(db *gorm.DB, userId uint) *gorm.DB {
|
||||
query := db.Model(&model.Book{})
|
||||
query = query.Select("books.id, books.title, authors.name as author, books.open_library_id, user_books.rating, user_books.read, user_books.want_read, " + selectStaticFilesPath())
|
||||
query = query.Select("books.id, books.title, authors.name as author, books.inventaire_id, user_books.rating, user_books.read, user_books.want_read, " + selectStaticFilesPath())
|
||||
query = joinAuthors(query)
|
||||
query = query.Joins("left join user_books on (user_books.book_id = books.id and user_books.user_id = ?)", userId)
|
||||
query = joinStaticFiles(query)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/appcontext"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/inventaire"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/model"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/myvalidator"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/openlibrary"
|
||||
@@ -12,7 +13,8 @@ import (
|
||||
)
|
||||
|
||||
type bookPostImport struct {
|
||||
OpenLibraryId string `json:"openlibraryid" binding:"required,max=50"`
|
||||
InventaireID string `json:"inventaireid" binding:"required,max=50"`
|
||||
Lang string `json:"lang" binding:"required,max=5"`
|
||||
}
|
||||
|
||||
func PostImportBookHandler(ac appcontext.AppContext) {
|
||||
@@ -28,12 +30,12 @@ func PostImportBookHandler(ac appcontext.AppContext) {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
return
|
||||
}
|
||||
openLibraryBook, err := openlibrary.CallOpenLibraryBook(request.OpenLibraryId)
|
||||
inventaireBook, err := inventaire.CallInventaireBook(request.InventaireID, request.Lang)
|
||||
if err != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
return
|
||||
}
|
||||
book, err := saveOpenLibraryBookToDb(ac, request.OpenLibraryId, openLibraryBook, &user)
|
||||
book, err := saveInventaireBookToDb(ac, inventaireBook, &user)
|
||||
if err != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
return
|
||||
@@ -41,15 +43,15 @@ func PostImportBookHandler(ac appcontext.AppContext) {
|
||||
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)
|
||||
func saveInventaireBookToDb(ac appcontext.AppContext, inventaireBook inventaire.InventaireBookResult, user *model.User) (*model.Book, error) {
|
||||
author, err := fetchOrCreateInventaireAuthor(ac, inventaireBook.Author)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
book := model.Book{
|
||||
Title: openLibraryBook.Title,
|
||||
Summary: openLibraryBook.Description,
|
||||
OpenLibraryId: openLibraryId,
|
||||
Title: inventaireBook.Title,
|
||||
Summary: inventaireBook.Description,
|
||||
InventaireID: inventaireBook.ID,
|
||||
Author: *author,
|
||||
AddedBy: *user,
|
||||
}
|
||||
@@ -57,17 +59,18 @@ func saveOpenLibraryBookToDb(ac appcontext.AppContext, openLibraryId string, ope
|
||||
return &book, err
|
||||
}
|
||||
|
||||
func fetchOrCreateOpenLibraryAuthor(ac appcontext.AppContext, openlibraryAuthorId string) (*model.Author, error) {
|
||||
func fetchOrCreateInventaireAuthor(ac appcontext.AppContext, inventaireAuthor *inventaire.InventaireAuthorResult) (*model.Author, error) {
|
||||
var author model.Author
|
||||
res := ac.Db.Where("open_library_id = ?", openlibraryAuthorId).First(&author)
|
||||
res := ac.Db.Where("inventaire_id = ?", inventaireAuthor.ID).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
|
||||
newAuthor := model.Author{
|
||||
Name: inventaireAuthor.Name,
|
||||
Description: inventaireAuthor.Description,
|
||||
InventaireID: inventaireAuthor.ID,
|
||||
}
|
||||
return newAuthor, nil
|
||||
return &newAuthor, nil
|
||||
} else {
|
||||
return &author, err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/appcontext"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/inventaire"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/myvalidator"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/openlibrary"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/query"
|
||||
@@ -38,24 +39,24 @@ func GetSearchBooksHandler(ac appcontext.AppContext) {
|
||||
if len(books) > 0 {
|
||||
returnedBooks = books
|
||||
} else {
|
||||
queryResult, err := openlibrary.CallOpenLibrarySearch(searchterm, limit, offset)
|
||||
queryResult, err := inventaire.CallInventaireSearch(searchterm, limit, offset)
|
||||
if err != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
return
|
||||
}
|
||||
returnedBooks = OpenLibraryBooksToBookSearchGet(queryResult.Books)
|
||||
returnedBooks = OpenLibraryBooksToBookSearchGet(queryResult.Results)
|
||||
}
|
||||
ac.C.JSON(http.StatusOK, returnedBooks)
|
||||
}
|
||||
|
||||
func OpenLibraryBooksToBookSearchGet(OLbooks []openlibrary.OpenLibrarySearchBook) []query.BookSearchGet {
|
||||
func OpenLibraryBooksToBookSearchGet(OLbooks []inventaire.InventaireSearchBook) []query.BookSearchGet {
|
||||
var books []query.BookSearchGet
|
||||
for _, b := range OLbooks {
|
||||
bookSearchGet := query.BookSearchGet{
|
||||
ID: 0,
|
||||
Title: b.Title,
|
||||
Author: b.Authors[0],
|
||||
OpenLibraryId: b.OpenLibraryId,
|
||||
Title: b.Label,
|
||||
Author: "",
|
||||
InventaireID: b.ID,
|
||||
Rating: 0,
|
||||
Read: false,
|
||||
WantRead: false,
|
||||
|
||||
Reference in New Issue
Block a user