package main import ( "encoding/json" ) type book struct { ID int `json:"id"` Platform string `json:"platform"` ReaderURL string `json:"readerUrl"` Title string `json:"title"` Authors []string `json:"authors"` } type library struct { db *database } type newLibraryOptions struct { db *database } func newLibrary(options newLibraryOptions) *library { return &library{options.db} } func (lib *library) add(b book) error { authors, err := json.Marshal(b.Authors) if err != nil { return err } _, err = lib.db.Exec(` insert into books( platform_id, reader_url, title, authors) values((select id from platforms where name = $1), $2, $3, $4) on conflict(reader_url) do update set title = excluded.title, authors = excluded.authors `, b.Platform, b.ReaderURL, b.Title, authors, ) return err } func (lib *library) delete(id string) error { _, err := lib.db.Exec(`delete from books where id = $1`, id) return err } func (lib *library) get(readerURLOrBookID string) (*book, error) { row := lib.db.QueryRow(` select books.id, platforms.name, books.reader_url, books.title, books.authors from books left join platforms on books.platform_id = platforms.id where books.reader_url = $1 or books.id = $1 `, readerURLOrBookID, ) var ( b book authors []byte ) err := row.Scan( &b.ID, &b.Platform, &b.ReaderURL, &b.Title, &authors, ) if err != nil { return nil, err } err = json.Unmarshal(authors, &b.Authors) return &b, err } func (lib *library) getBooks() (*[]book, error) { rows, err := lib.db.Query(` select books.id, platforms.name, books.reader_url, books.title, books.authors from books left join platforms on books.platform_id = platforms.id `) if err != nil { return nil, err } bs := &[]book{} for rows.Next() { var ( b book authors []byte ) if err := rows.Scan( &b.ID, &b.Platform, &b.ReaderURL, &b.Title, &authors, ); err != nil { return nil, err } if err = json.Unmarshal(authors, &b.Authors); err != nil { return nil, err } *bs = append(*bs, b) } return bs, err }