node-nicovideo-api
Version:
nicovideo api (video, live, etc..) wrapper package for node.js
233 lines (195 loc) • 7.16 kB
JavaScript
// 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);