FeedHandler.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. "use strict";
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = function (d, b) {
  4. extendStatics = Object.setPrototypeOf ||
  5. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  6. function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  7. return extendStatics(d, b);
  8. };
  9. return function (d, b) {
  10. if (typeof b !== "function" && b !== null)
  11. throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
  12. extendStatics(d, b);
  13. function __() { this.constructor = d; }
  14. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  15. };
  16. })();
  17. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  18. if (k2 === undefined) k2 = k;
  19. Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
  20. }) : (function(o, m, k, k2) {
  21. if (k2 === undefined) k2 = k;
  22. o[k2] = m[k];
  23. }));
  24. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  25. Object.defineProperty(o, "default", { enumerable: true, value: v });
  26. }) : function(o, v) {
  27. o["default"] = v;
  28. });
  29. var __importStar = (this && this.__importStar) || function (mod) {
  30. if (mod && mod.__esModule) return mod;
  31. var result = {};
  32. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  33. __setModuleDefault(result, mod);
  34. return result;
  35. };
  36. var __importDefault = (this && this.__importDefault) || function (mod) {
  37. return (mod && mod.__esModule) ? mod : { "default": mod };
  38. };
  39. Object.defineProperty(exports, "__esModule", { value: true });
  40. exports.parseFeed = exports.FeedHandler = void 0;
  41. var domhandler_1 = __importDefault(require("domhandler"));
  42. var DomUtils = __importStar(require("domutils"));
  43. var Parser_1 = require("./Parser");
  44. var FeedItemMediaMedium;
  45. (function (FeedItemMediaMedium) {
  46. FeedItemMediaMedium[FeedItemMediaMedium["image"] = 0] = "image";
  47. FeedItemMediaMedium[FeedItemMediaMedium["audio"] = 1] = "audio";
  48. FeedItemMediaMedium[FeedItemMediaMedium["video"] = 2] = "video";
  49. FeedItemMediaMedium[FeedItemMediaMedium["document"] = 3] = "document";
  50. FeedItemMediaMedium[FeedItemMediaMedium["executable"] = 4] = "executable";
  51. })(FeedItemMediaMedium || (FeedItemMediaMedium = {}));
  52. var FeedItemMediaExpression;
  53. (function (FeedItemMediaExpression) {
  54. FeedItemMediaExpression[FeedItemMediaExpression["sample"] = 0] = "sample";
  55. FeedItemMediaExpression[FeedItemMediaExpression["full"] = 1] = "full";
  56. FeedItemMediaExpression[FeedItemMediaExpression["nonstop"] = 2] = "nonstop";
  57. })(FeedItemMediaExpression || (FeedItemMediaExpression = {}));
  58. // TODO: Consume data as it is coming in
  59. var FeedHandler = /** @class */ (function (_super) {
  60. __extends(FeedHandler, _super);
  61. /**
  62. *
  63. * @param callback
  64. * @param options
  65. */
  66. function FeedHandler(callback, options) {
  67. var _this = this;
  68. if (typeof callback === "object") {
  69. callback = undefined;
  70. options = callback;
  71. }
  72. _this = _super.call(this, callback, options) || this;
  73. return _this;
  74. }
  75. FeedHandler.prototype.onend = function () {
  76. var _a, _b;
  77. var feedRoot = getOneElement(isValidFeed, this.dom);
  78. if (!feedRoot) {
  79. this.handleCallback(new Error("couldn't find root of feed"));
  80. return;
  81. }
  82. var feed = {};
  83. if (feedRoot.name === "feed") {
  84. var childs = feedRoot.children;
  85. feed.type = "atom";
  86. addConditionally(feed, "id", "id", childs);
  87. addConditionally(feed, "title", "title", childs);
  88. var href = getAttribute("href", getOneElement("link", childs));
  89. if (href) {
  90. feed.link = href;
  91. }
  92. addConditionally(feed, "description", "subtitle", childs);
  93. var updated = fetch("updated", childs);
  94. if (updated) {
  95. feed.updated = new Date(updated);
  96. }
  97. addConditionally(feed, "author", "email", childs, true);
  98. feed.items = getElements("entry", childs).map(function (item) {
  99. var entry = {};
  100. var children = item.children;
  101. addConditionally(entry, "id", "id", children);
  102. addConditionally(entry, "title", "title", children);
  103. var href = getAttribute("href", getOneElement("link", children));
  104. if (href) {
  105. entry.link = href;
  106. }
  107. var description = fetch("summary", children) || fetch("content", children);
  108. if (description) {
  109. entry.description = description;
  110. }
  111. var pubDate = fetch("updated", children);
  112. if (pubDate) {
  113. entry.pubDate = new Date(pubDate);
  114. }
  115. entry.media = getMediaElements(children);
  116. return entry;
  117. });
  118. }
  119. else {
  120. var childs = (_b = (_a = getOneElement("channel", feedRoot.children)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [];
  121. feed.type = feedRoot.name.substr(0, 3);
  122. feed.id = "";
  123. addConditionally(feed, "title", "title", childs);
  124. addConditionally(feed, "link", "link", childs);
  125. addConditionally(feed, "description", "description", childs);
  126. var updated = fetch("lastBuildDate", childs);
  127. if (updated) {
  128. feed.updated = new Date(updated);
  129. }
  130. addConditionally(feed, "author", "managingEditor", childs, true);
  131. feed.items = getElements("item", feedRoot.children).map(function (item) {
  132. var entry = {};
  133. var children = item.children;
  134. addConditionally(entry, "id", "guid", children);
  135. addConditionally(entry, "title", "title", children);
  136. addConditionally(entry, "link", "link", children);
  137. addConditionally(entry, "description", "description", children);
  138. var pubDate = fetch("pubDate", children);
  139. if (pubDate)
  140. entry.pubDate = new Date(pubDate);
  141. entry.media = getMediaElements(children);
  142. return entry;
  143. });
  144. }
  145. this.feed = feed;
  146. this.handleCallback(null);
  147. };
  148. return FeedHandler;
  149. }(domhandler_1.default));
  150. exports.FeedHandler = FeedHandler;
  151. function getMediaElements(where) {
  152. return getElements("media:content", where).map(function (elem) {
  153. var media = {
  154. medium: elem.attribs.medium,
  155. isDefault: !!elem.attribs.isDefault,
  156. };
  157. if (elem.attribs.url) {
  158. media.url = elem.attribs.url;
  159. }
  160. if (elem.attribs.fileSize) {
  161. media.fileSize = parseInt(elem.attribs.fileSize, 10);
  162. }
  163. if (elem.attribs.type) {
  164. media.type = elem.attribs.type;
  165. }
  166. if (elem.attribs.expression) {
  167. media.expression = elem.attribs
  168. .expression;
  169. }
  170. if (elem.attribs.bitrate) {
  171. media.bitrate = parseInt(elem.attribs.bitrate, 10);
  172. }
  173. if (elem.attribs.framerate) {
  174. media.framerate = parseInt(elem.attribs.framerate, 10);
  175. }
  176. if (elem.attribs.samplingrate) {
  177. media.samplingrate = parseInt(elem.attribs.samplingrate, 10);
  178. }
  179. if (elem.attribs.channels) {
  180. media.channels = parseInt(elem.attribs.channels, 10);
  181. }
  182. if (elem.attribs.duration) {
  183. media.duration = parseInt(elem.attribs.duration, 10);
  184. }
  185. if (elem.attribs.height) {
  186. media.height = parseInt(elem.attribs.height, 10);
  187. }
  188. if (elem.attribs.width) {
  189. media.width = parseInt(elem.attribs.width, 10);
  190. }
  191. if (elem.attribs.lang) {
  192. media.lang = elem.attribs.lang;
  193. }
  194. return media;
  195. });
  196. }
  197. function getElements(tagName, where) {
  198. return DomUtils.getElementsByTagName(tagName, where, true);
  199. }
  200. function getOneElement(tagName, node) {
  201. return DomUtils.getElementsByTagName(tagName, node, true, 1)[0];
  202. }
  203. function fetch(tagName, where, recurse) {
  204. if (recurse === void 0) { recurse = false; }
  205. return DomUtils.getText(DomUtils.getElementsByTagName(tagName, where, recurse, 1)).trim();
  206. }
  207. function getAttribute(name, elem) {
  208. if (!elem) {
  209. return null;
  210. }
  211. var attribs = elem.attribs;
  212. return attribs[name];
  213. }
  214. function addConditionally(obj, prop, what, where, recurse) {
  215. if (recurse === void 0) { recurse = false; }
  216. var tmp = fetch(what, where, recurse);
  217. if (tmp)
  218. obj[prop] = tmp;
  219. }
  220. function isValidFeed(value) {
  221. return value === "rss" || value === "feed" || value === "rdf:RDF";
  222. }
  223. /**
  224. * Parse a feed.
  225. *
  226. * @param feed The feed that should be parsed, as a string.
  227. * @param options Optionally, options for parsing. When using this option, you should set `xmlMode` to `true`.
  228. */
  229. function parseFeed(feed, options) {
  230. if (options === void 0) { options = { xmlMode: true }; }
  231. var handler = new FeedHandler(options);
  232. new Parser_1.Parser(handler, options).end(feed);
  233. return handler.feed;
  234. }
  235. exports.parseFeed = parseFeed;