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 }