UNPKG

node-nicovideo-api

Version:

nicovideo api (video, live, etc..) wrapper package for node.js

233 lines (195 loc) 7.16 kB
// Generated by CoffeeScript 1.10.0 (function() { var APIEndpoints, Deferred, Ent, NicoException, NicoVideoInfo, Request, _, __, cheerio, deepFreeze, sprintf; _ = require("lodash"); __ = require("lodash-deep"); Request = require("request-promise"); cheerio = require("cheerio"); sprintf = require("sprintf").sprintf; deepFreeze = require("deep-freeze"); Ent = require("ent"); Deferred = require("promise-native-deferred"); APIEndpoints = require("../APIEndpoints"); NicoException = require("../NicoException"); /** * ニコニコ動画APIの動画情報モデルクラス * * Properties * getメソッドで第1階層まで取得できます。 * Example: NicoVideoInfo.get("user").id * * * @class NicoVideoInfo * @extends EventEmitter2 */ module.exports = NicoVideoInfo = (function() { NicoVideoInfo.fetch = function(movieId, session) { var defer; defer = new Deferred; if (movieId == null) { return defer.reject("Fetch failed. Movie id not specified."); } APIEndpoints.video.getMovieInfo(session, { movieId: movieId }).then(function(res) { var info; if (res.statusCode === 503) { defer.reject("Nicovideo has in maintenance."); } info = new NicoVideoInfo(movieId, session); info._attr = deepFreeze(NicoVideoInfo.parseResponse(res.body, movieId)); return defer.resolve(info); }); return defer.promise; }; /** * @private * @param {String} resBody getThumbInfoAPIから取得したXML * @return {Object} */ NicoVideoInfo.parseResponse = function(resBody, movieId) { var $res, $resThumb, errorMessage, length; $res = cheerio.load(resBody); if ($res(":root").attr("status") !== "ok") { errorMessage = $res("error description").text(); throw new NicoException({ message: "Failed to fetch movie info (" + errorMessage + ") movie:" + movieId, code: $res("error code") }); } $resThumb = $res("thumb"); length = (function(length) { var h, m, s; length = $resThumb.find("length").text().split(":"); s = length.pop() | 0; m = length.pop() | 0; h = length.pop() | 0; return s + (m * 60) + (h * 3600); })(length); return { id: $resThumb.find("video_id").text(), title: Ent.decode($resThumb.find("title").text()), description: $resThumb.find("description").text(), length: length, movieType: $resThumb.find("movie_type").text(), thumbnail: $resThumb.find("thumbnail_url").text(), isDeleted: false, count: { view: $resThumb.find("view_counter").text() | 0, comments: $resThumb.find("comment_num").text() | 0, mylist: $resThumb.find("mylist_counter").text() | 0 }, tags: (function() { var $tag, $tags, domain, i, j, len, len1, ref, ref1, tag, tagList, tags; tagList = []; ref = $resThumb.find("tags"); for (i = 0, len = ref.length; i < len; i++) { tags = ref[i]; $tags = cheerio(tags); domain = $tags.attr("domain"); ref1 = $tags.find("tag"); for (j = 0, len1 = ref1.length; j < len1; j++) { tag = ref1[j]; $tag = cheerio(tag); tagList.push({ name: $tag.text(), isCategory: $tag.attr("category") === "1", isLocked: $tag.attr("lock") === "1", domain: domain }); } } return tagList; })(), user: { id: $resThumb.find("user_id").text() | 0, name: $resThumb.find("user_nickname").text(), icon: $resThumb.find("user_icon_url").text() } }; }; NicoVideoInfo.defaults = { title: null, description: null, length: null, movieType: null, thumbnail: null, isDeleted: false, count: { view: -1, comments: -1, mylist: -1 }, tags: [], user: { id: -1, name: null, icon: null } }; /** * @property id * @type String */ /** * @property {Object} attributes * @property {String} attributes.id 動画ID * @property {String} attributes.title 動画タイトル * @property {String} attributes.description 動画説明文 * @property {Number} attributes.length 動画の長さ(秒) * @property {String} attributes.movieType 動画ファイルの形式(mp4, flv, swf) * @property {String} attributes.thumbnail サムネイル画像のURL * @property {Boolean} attributes.isDeleted 削除されているか(現在、常にfalse) * @property {Object} attributes.stats 統計情報 * @property {Number} attributes.stats.view 再生数 * @property {Object} attributes.stats.comments コメント数 * @property {Object} attributes.stats.mylist マイリスト数 * @property {Array<Object>} attributes.tags タグ情報 * @property {String} attributes.tags[n].name タグ名 * @property {Boolean} attributes.tags[n].isCategory カテゴリタグか * @property {String} attributes.tags[n].isLocked ロックされているか * @property {String} attributes.tags[n].domain どの国のタグか(日本="jp") * @property {Object} attributes.user 投稿者情報 * @property {Number} attributes.user.id ユーザーID * @property {String} attributes.user.name ユーザー名 * @property {String} attributes.user.icon ユーザーアイコンのURL */ NicoVideoInfo.prototype._attr = {}; /** * @class NicoVideoInfo * @constructor * @param {String} movieId 動画ID * @param {NicoSession} _session セッション */ function NicoVideoInfo(movieId, _session) { this._session = _session; Object.defineProperties(this, { id: { value: movieId } }); } /** * 動画が削除されているか調べます。 * @return {Boolean} */ NicoVideoInfo.prototype.isDeleted = function() { return this.get("isDeleted"); }; /** * この動画のgetflv APIの結果を取得します。 * @return {Promise} */ NicoVideoInfo.prototype.fetchGetFlv = function() { return this._session.video.getFlv(this.id); }; /** * 属性を取得します。 * @param {String} path 属性名(Ex. "id", "title", "user.id") */ NicoVideoInfo.prototype.get = function(path) { return __.deepGet(this._attr, path); }; return NicoVideoInfo; })(); }).call(this);