An unofficial API for royalroad.com.
npm i -s @fsoc/royalroadl-api
This is an attempt to write a predictable and consistent wrapper around the mess that is RR. Since no official public API is exposed, this module scrapes all data straight from the HTML, which makes it very prone to spontaneous and horrible death.
Barebones documentation generated from TypeDoc can be found on fs-c.github.io/royalroad-api/. You can also build these docs yourself by running npm run docs in the root of the project.
For more examples check out the /examples directory, see also the tests in /test .
import { RoyalRoadAPI } from '@fsoc/royalroadl-api' ;
const api = new RoyalRoadAPI ( ) ;
const { data } = await api . fictions . getPopular ( ) ;
const titles = data . slice ( 10 ) . map ( ( fic ) => fic . title ) ;
console . log ( `The top 10 popular fictions are: ${ titles . join ( ', ' ) } ` ) ; The module itself exports only a RoyalRoadAPI class which, by itself, has no methods. All functionality is delegated to service classes which are properties of the RoyalRoadAPI instance.
All responses and errors are either an instance of a RoyalResponse or a RoyalError , which extends RoyalResponse . This is done to easily allow for meta information to be tacked onto responses, and to have a consistent interface between user and module. Note that the RoyalError acts similarly to the NodeJS Error object, in that it captures and returns a short stack trace.
For example, a call to RoyalRoadAPI#fiction.getFiction() might yield the following response on success:
RoyalResponse {
data :
{ type : 'Original' ,
tags : [ 'Action' , 'Adventure' , 'Sci-fi' , ... 3 more items ] ,
stats :
{ pages : 766 ,
ratings : 719 ,
followers : 2991 ,
favorites : 690 ,
views : [ Object ] ,
score : [ Object ] } ,
title : 'Paladin' ,
image :
'https://www.royalroadcdn.com/(...)' ,
status : 'HIATUS' ,
author :
{ name : 'Komikhan' ,
title : '' ,
avatar :
'https://www.royalroadcdn.com/(...)' ,
id : 66486 } ,
warnings : [ 'Gore' , 'Profanity' ] ,
chapters : [ [ Object ] , [ Object ] , [ Object ] , ... 71 more items ] ,
description :
'When the first derelict alien spacecraft fell to Earth, (...)' } ,
success : true ,
timestamp : 1528119296799 }...or on error:
RoyalError {
data :
{ message : 'Page Not Found' ,
stack :
[ 'Error' ,
' at new RoyalError' , ... 8 more items ] } ,
success : false ,
timestamp : 1528119381034 } Todas las clases de servicio utilizan la misma instancia del Requester , la clase responsable de realizar solicitudes HTTP y devolver sus respuestas. Por defecto, lanzará un RoyalError si encuentra un código de estado que no sea 200 (esto se puede deshabilitar con la opción ignoreStatus ).
Since RR likes to return 200 even when the actual response should be a 404 or 304, the Requester will parse the HTML it has gotten (if it got any), and try to read an error from it. Si encuentra señales de que la solicitud ha fallado, lanzará: esto se puede deshabilitar con la opción ignoreParser .
The Requester s main goal is to keep track of cookies and to automatically fetch a __ResponseVerificationToken often needed for POST requests as a part of anti CSRF measures. Esta obtención de tokens está deshabilitada de forma predeterminada y se puede habilitar con la opción fetchToken .
All services are structured in a very similar way: with a <Type>Service exposing all relevant methods, and a <Type>Parser , which usually exposes a number of static methods used to parse HTML responses.
Una conclusión rápida de todos los servicios existentes es:
ChapterService , contains methods for fetching and publishing chapters and chapter comments.FictionService , fetching fiction data and reviews.FictionsService , methods for fetching all types of fiction lists RRL offers, with their respective levels of per fiction detail.ProfileService , handling profiles, returns parsed user profiles.UserService , actions related to the logged-in user like logon, getting the users' fictions, bookmarks, or notifications.Esto usa Cheerio para analizar HTML, que es un analizador muy indulgente. This means that even if RRL were to make minor changes to their page layouts, large parts of the API (even those parts responsible for changed areas) would still remain functional.
Por lo tanto, espere que las propiedades estén vacías o null , y sepa que no se lanzará un error solo porque algunos valores no podrían analizarse.