r2-shared-js
Version:
Readium 2 'shared' for NodeJS (TypeScript)
328 lines • 15.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDivinaPublication = exports.Divinais = exports.DivinaParsePromise = void 0;
var tslib_1 = require("tslib");
var debug_ = require("debug");
var fs = require("fs");
var http = require("http");
var https = require("https");
var path = require("path");
var publication_1 = require("../models/publication");
var lcp_1 = require("r2-lcp-js/dist/es5/src/parser/epub/lcp");
var serializable_1 = require("r2-lcp-js/dist/es5/src/serializable");
var UrlUtils_1 = require("r2-utils-js/dist/es5/src/_utils/http/UrlUtils");
var JsonUtils_1 = require("r2-utils-js/dist/es5/src/_utils/JsonUtils");
var BufferUtils_1 = require("r2-utils-js/dist/es5/src/_utils/stream/BufferUtils");
var zipFactory_1 = require("r2-utils-js/dist/es5/src/_utils/zip/zipFactory");
var zipHasEntry_1 = require("../_utils/zipHasEntry");
var debug = debug_("r2:shared#parser/divina");
function absolutizeURLs(rootUrl, jsonObj) {
(0, JsonUtils_1.traverseJsonObjects)(jsonObj, function (obj) {
if (obj.href && typeof obj.href === "string"
&& !(0, UrlUtils_1.isHTTP)(obj.href)) {
obj.href = rootUrl + "/" + obj.href;
}
});
}
function DivinaParsePromise(filePath, isDivina, pubtype) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var isAnDivina, _a, publicationType, entryName, filePathToLoad, url, zip, err_1, has, zipEntries, _i, zipEntries_1, zipEntry, manifestZipStream_, err_2, manifestZipStream, manifestZipData, err_3, manifestJsonStr, manifestJson, url, publication, lcpEntryName, checkLCP, hasLCP, has, lcpZipStream_, err_4, lcpZipStream, lcpZipData, err_5, lcpJsonStr, lcpJson, lcpl;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = isDivina;
if (_a) return [3, 2];
return [4, isDivinaPublication(filePath)];
case 1:
_a = (_b.sent());
_b.label = 2;
case 2:
isAnDivina = _a;
publicationType = pubtype || (isAnDivina ? "divina" : "generic");
entryName = "manifest.json";
filePathToLoad = filePath;
if (isAnDivina === Divinais.LocalExploded) {
filePathToLoad = path.dirname(filePathToLoad) + "/";
}
else if (isAnDivina === Divinais.RemoteExploded) {
url = new URL(filePathToLoad);
entryName = path.basename(url.pathname);
url.pathname = path.dirname(url.pathname) + "/";
filePathToLoad = url.toString();
}
_b.label = 3;
case 3:
_b.trys.push([3, 5, , 6]);
return [4, (0, zipFactory_1.zipLoadPromise)(filePathToLoad)];
case 4:
zip = _b.sent();
return [3, 6];
case 5:
err_1 = _b.sent();
return [2, Promise.reject(err_1)];
case 6:
if (!zip.hasEntries()) {
return [2, Promise.reject("Divina zip empty")];
}
if (!(isAnDivina === Divinais.LocalExploded ||
isAnDivina === Divinais.LocalPacked)) return [3, 9];
return [4, (0, zipHasEntry_1.zipHasEntry)(zip, entryName, undefined)];
case 7:
has = _b.sent();
if (!!has) return [3, 9];
return [4, zip.getEntries()];
case 8:
zipEntries = _b.sent();
for (_i = 0, zipEntries_1 = zipEntries; _i < zipEntries_1.length; _i++) {
zipEntry = zipEntries_1[_i];
if (zipEntry.startsWith("__MACOSX/")) {
continue;
}
debug(zipEntry);
}
return [2, Promise.reject("Divina no manifest?!")];
case 9:
_b.trys.push([9, 11, , 12]);
return [4, zip.entryStreamPromise(entryName)];
case 10:
manifestZipStream_ = _b.sent();
return [3, 12];
case 11:
err_2 = _b.sent();
debug(err_2);
return [2, Promise.reject("Problem streaming Divina zip entry?! ".concat(entryName))];
case 12:
manifestZipStream = manifestZipStream_.stream;
_b.label = 13;
case 13:
_b.trys.push([13, 15, , 16]);
return [4, (0, BufferUtils_1.streamToBufferPromise)(manifestZipStream)];
case 14:
manifestZipData = _b.sent();
return [3, 16];
case 15:
err_3 = _b.sent();
debug(err_3);
return [2, Promise.reject("Problem buffering Divina zip entry?! ".concat(entryName))];
case 16:
manifestJsonStr = manifestZipData.toString("utf8");
manifestJson = JSON.parse(manifestJsonStr);
if (isAnDivina === Divinais.RemoteExploded) {
url = new URL(filePath);
url.pathname = path.dirname(url.pathname);
absolutizeURLs(url.toString(), manifestJson);
}
publication = (0, serializable_1.TaJsonDeserialize)(manifestJson, publication_1.Publication);
publication.AddToInternal("type", publicationType);
publication.AddToInternal("zip", zip);
lcpEntryName = "license.lcpl";
checkLCP = true;
hasLCP = false;
if (!(isAnDivina === Divinais.LocalExploded ||
isAnDivina === Divinais.LocalPacked)) return [3, 18];
return [4, (0, zipHasEntry_1.zipHasEntry)(zip, lcpEntryName, undefined)];
case 17:
has = _b.sent();
if (!has) {
checkLCP = false;
}
else {
hasLCP = true;
}
_b.label = 18;
case 18:
if (!checkLCP) return [3, 27];
lcpZipStream_ = void 0;
_b.label = 19;
case 19:
_b.trys.push([19, 21, , 22]);
return [4, zip.entryStreamPromise(lcpEntryName)];
case 20:
lcpZipStream_ = _b.sent();
return [3, 22];
case 21:
err_4 = _b.sent();
if (hasLCP) {
debug(err_4);
return [2, Promise.reject("Problem streaming Divina LCP zip entry?! ".concat(entryName))];
}
else {
debug("Divina no LCP.");
}
checkLCP = false;
return [3, 22];
case 22:
if (!(checkLCP && lcpZipStream_)) return [3, 27];
lcpZipStream = lcpZipStream_.stream;
lcpZipData = void 0;
_b.label = 23;
case 23:
_b.trys.push([23, 25, , 26]);
return [4, (0, BufferUtils_1.streamToBufferPromise)(lcpZipStream)];
case 24:
lcpZipData = _b.sent();
return [3, 26];
case 25:
err_5 = _b.sent();
debug(err_5);
return [2, Promise.reject("Problem buffering Divina LCP zip entry?! ".concat(entryName))];
case 26:
lcpJsonStr = lcpZipData.toString("utf8");
lcpJson = JSON.parse(lcpJsonStr);
lcpl = (0, serializable_1.TaJsonDeserialize)(lcpJson, lcp_1.LCP);
lcpl.ZipPath = lcpEntryName;
lcpl.JsonSource = lcpJsonStr;
lcpl.init();
publication.LCP = lcpl;
_b.label = 27;
case 27: return [2, Promise.resolve(publication)];
}
});
});
}
exports.DivinaParsePromise = DivinaParsePromise;
var Divinais;
(function (Divinais) {
Divinais["LocalExploded"] = "LocalExploded";
Divinais["LocalPacked"] = "LocalPacked";
Divinais["RemoteExploded"] = "RemoteExploded";
Divinais["RemotePacked"] = "RemotePacked";
})(Divinais = exports.Divinais || (exports.Divinais = {}));
function doRequest(u) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _this = this;
return tslib_1.__generator(this, function (_a) {
return [2, new Promise(function (resolve, _reject) {
var url = new URL(u);
var secure = url.protocol === "https:";
var options = {
headers: {
"Accept": "*/*,application/divina+json",
"Accept-Language": "en-UK,en-US;q=0.7,en;q=0.5",
"Host": url.host,
"User-Agent": "Readium2-Divinas",
},
host: url.host,
method: "GET",
path: url.pathname + url.search,
port: secure ? 443 : 80,
protocol: url.protocol,
};
debug(JSON.stringify(options));
(secure ? https : http).request(options, function (res) {
if (!res) {
resolve(undefined);
return;
}
debug(res.statusCode);
debug(JSON.stringify(res.headers));
if (res.statusCode && (res.statusCode >= 300 && res.statusCode < 400)) {
var loc = res.headers.Location || res.headers.location;
if (loc && loc.length) {
var l_1 = Array.isArray(loc) ? loc[0] : loc;
process.nextTick(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var redirectRes, _err_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4, doRequest(l_1)];
case 1:
redirectRes = _a.sent();
resolve(redirectRes);
return [3, 3];
case 2:
_err_1 = _a.sent();
resolve(undefined);
return [3, 3];
case 3: return [2];
}
});
}); });
}
else {
resolve(undefined);
}
return;
}
var type = res.headers["Content-Type"] || res.headers["content-type"];
if (type) {
if (type.includes("application/divina+json")) {
resolve(Divinais.RemoteExploded);
return;
}
if (type.includes("application/json")) {
res.setEncoding("utf8");
var responseBody_1 = "";
res.on("data", function (chunk) {
responseBody_1 += chunk;
});
res.on("end", function () {
try {
var manJson = JSON.parse(responseBody_1);
if (manJson.metadata && manJson.metadata["@type"] &&
(/https?:\/\/schema\.org\/VisualArtwork$/.test(manJson.metadata["@type"]) ||
/https?:\/\/schema\.org\/ComicStory$/.test(manJson.metadata["@type"]))) {
resolve(Divinais.RemoteExploded);
return;
}
else {
resolve(undefined);
}
}
catch (ex) {
debug(ex);
resolve(undefined);
}
});
return;
}
}
resolve(undefined);
}).on("error", function (err) {
debug(err);
resolve(undefined);
}).end();
})];
});
});
}
function isDivinaPublication(urlOrPath) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var p, isHttp, url, fileName, ext, dnva, dnvaLcp, manStr, manJson;
return tslib_1.__generator(this, function (_a) {
p = urlOrPath;
isHttp = (0, UrlUtils_1.isHTTP)(urlOrPath);
if (isHttp) {
url = new URL(urlOrPath);
p = url.pathname;
}
fileName = path.basename(p);
ext = path.extname(fileName);
dnva = /\.divina$/i.test(ext);
dnvaLcp = /\.lcpdivina$/i.test(ext);
if (dnva || dnvaLcp) {
if (!isHttp) {
return [2, Divinais.LocalPacked];
}
}
if (!isHttp && fileName === "manifest.json") {
if (fs.existsSync(p)) {
manStr = fs.readFileSync(p, { encoding: "utf8" });
manJson = JSON.parse(manStr);
if (manJson.metadata && manJson.metadata["@type"] &&
(/https?:\/\/schema\.org\/VisualArtwork$/.test(manJson.metadata["@type"]) ||
/https?:\/\/schema\.org\/ComicStory$/.test(manJson.metadata["@type"]))) {
return [2, Divinais.LocalExploded];
}
}
}
if (isHttp) {
return [2, doRequest(urlOrPath)];
}
return [2, Promise.resolve(undefined)];
});
});
}
exports.isDivinaPublication = isDivinaPublication;
//# sourceMappingURL=divina.js.map
;