Current version: 0.2 Package: https://www.npmjs.com/package/xml2js Documentation: https://github.com/Leonidas-from-XIV/node-xml2js
The XML parser can be configured to do many, if not all, of the transformations needed to format the JSON response data as I'd like.
⚠️ The content below is a rough draft
DATA.GoodreadsResponse.user[0].updates[0].update is an array of objects.
Following are the user updates I am interested in for this project.
OBJECT.$.type = (string)
- review (e.g., 'gave 5 stars to...)
- userstatus (e.g., 'is on page 841 of 896...'),
- readstatus (e.g., 'is currently reading...')
These sections outline the data I intend to target. The response schema is still being determined.
type DefaultOptionalString = string | ''; // undecided if I should do this
interface Object {
type: string;
[propName: string]: any;
}
interface Actor {
name: string;
goodreadsID: number;
imageURL?: string;
link: string;
}
interface Author {
about?: string;
averageRating: number;
goodreadsID: number;
hasImage: boolean = false;
hasSmallImage: boolean = false;
imageURL: DefaultOptionalString;
link: DefaultOptionalString;
name: string;
ratingsCount: number;
smallImageURL: DefaultOptionalString;
textReviewsCount: number;
}
interface Book {
goodreadsID: number;
isbn?: string;
isbn13?: string;
title: string;
sortTitle: string;
pageCount: number;
publisher?: string;
languageCode?: string;
author: Author
}
⚠️ The types defined below will be refactored into commonupdate
types
Issued when a user completes reading a book and gives it a rating.
gave 5 stars to <a href="https://www.goodreads.com/book/show/35429993-fall-or-dodge-in-hell\">Fall, or Dodge in Hell (ebook) by <a href="https://www.goodreads.com/author/show/545.Neal_Stephenson\">Neal Stephenson
interface Update {
type: string = 'review';
actionText: string;
actor: Actor;
link?: string;
object: {
type: string = 'book';
}
}
/*
review: (if REVIEW.object[0].book exists) {
actionText: REVIEW.action_text[0] (string),
actor: REVIEW.actor[0] (actor),
link: REVIEW.link[0] (string),
object: REVIEW.object[0].book (object) {
type: 'book',
goodreadsID: BOOK.id[0],
title: BOOK.title[0],
link: BOOK.link[0],
author: BOOK.authors[0].author[] (array of object)
},
imageURL: REVIEW.image_url[0] (string),
updatedAt: REVIEW.updated_at[0] (string),
}
Issued when a user updates their pages for a book.
Example: is on page 841 of 896 of <a href="https://www.goodreads.com/book/show/35429993-fall-or-dodge-in-hell\">Fall, or Dodge in Hell
status: {
actionText: STATUS.action_text[0],
link: STATUS.link[0],
imageURL: STATUS.image_url[0],
actor: STATUS.actor[0] (actor),
updatedAt: STATUS.updated_at[0] (input: datetime, output: datetime),
object: STATUS.object[0].user_status[0] {
type: 'book',
goodreadsID: OBJECT.id[0]._ (input: string, output: integer),
userID: OBJECT.user_id[0]._ (input: string, output: integer),
page: OBJECT.page[0]._ (input: string, output: integer),
percent: OBJECT.percent[0]._ (input: string, output: integer),
createdAt: OBJECT.created_at[0]._ (input: datetime string, output: datetime),
updatedAt: OBJECT.updated_at[0]._ (input: datetime string, output: datetime),
book: OBJECT.book[0] (object) {
goodreadsID: BOOK.id[0]._ (input: string, output: integer),
isbn: BOOK.isbn[0] (string),
isbn13: BOOK.isbn13[0] (string),
title: BOOK.title[0] (string),
sortTitle: BOOK.sort_by_title[0],
pageCount: BOOK.num_pages[0]._ (input: string, output: integer),
publisher: BOOK.publisher[0],
languageCode: BOOK.lang_code[0],
author: BOOK.author[multiple or 0] (object) {
name: AUTHOR.name[0],
about: AUTHOR.about[0] (string short bio),
sortName: AUTHOR.sort_by_name[0] (string),
shelfName: AUTHOR.shelf_display_name[0],
}
}
}
}
Issued when a user begins reading a new book.
is currently reading <a only_path="false" href="https://www.goodreads.com/review/show/2847236165\">Fall, or Dodge in Hell
status: {
actionText: STATUS.action_text[0],
link: STATUS.link[0],
image_url: STATUS.image_url[0],
actor: STATUS.actor[0] (actor),
updatedAt: STATUS.updated_at[0] (datetime),
object: OBJECT[0].read_status[0] {
goodreadsID: READSTATUS.id[0]._ (input: string, output: integer),
type: 'readStatus',
status: READSTATUS.status[0] (string, example: 'currently-reading'),
updatedAt: READSTATUS.updated_at[0]._ (input: datetime string, output: datetime),
book: READSTATUS.book[0] (object) {
goodreadsID: BOOK.id[0]._ (input: string, output: integer),
isbn: BOOK.isbn[0] (string),
isbn13: BOOK.isbn13[0] (string),
title: BOOK.title[0] (string),
sortTitle: BOOK.sort_by_title[0],
pageCount: BOOK.num_pages[0]._ (input: string, output: integer),
publisher: BOOK.publisher[0],
languageCode: BOOK.lang_code[0],
author: BOOK.author[multiple or 0] (object) {
name: AUTHOR.name[0],
about: AUTHOR.about[0] (string short bio),
sortName: AUTHOR.sort_by_name[0] (string),
shelfName: AUTHOR.shelf_display_name[0],
}
}
}
}
Any data grabbed via ._ can have the type verified by checking the (optional) corresponding .$.type object.
$.type = integer
$.type = datetime
$.nil === true (means data does not exist)