node-nicovideo-api
Version:
nicovideo api (video, live, etc..) wrapper package for node.js
424 lines (361 loc) • 12.2 kB
JavaScript
// Generated by CoffeeScript 1.10.0
/**
* Properties
* attrメソッドを介して取得します。(とりあえずマイリストの場合、属性は一切設定されません。)
* Example: mylist.attr("id") // -> マイリストIDを取得
* - id : number -- マイリストID
* - name : string -- リスト名
* - description : string -- マイリストの説明
* - public : boolean -- 公開マイリストかどうか
* - iconId : number -- マイリストのアイコンID
* - defaultSort : number -- 標準のソート方法(?)
* - sortOrder : number -- ソート方式(?)
* - userId : number -- ユーザー番号
* - createTime : Date -- マイリストの作成日
* - updateTime : Date -- マイリストの更新日
*/
(function() {
var Deferred, Emitter, MyList, MyListItem, NicoException, NicoUrl, QueryString, Request, _, sprintf,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
_ = require("lodash");
Emitter = require("event-kit").Emitter;
Request = require("request-promise");
sprintf = require("sprintf").sprintf;
QueryString = require("querystring");
Deferred = require("promise-native-deferred");
NicoUrl = require("../NicoURL");
NicoException = require("../NicoException");
MyListItem = require("./MyListItem");
module.exports = MyList = (function(superClass) {
extend(MyList, superClass);
MyList._cache = {};
MyList._attr = {
id: -1,
name: null,
description: null,
"public": null,
iconId: -1,
defaultSort: -1,
sortOrder: -1,
userId: -1,
createTime: null,
updateTime: null
};
/**
* @param {MyListMeta} myListMeta
* @param {NicoSession} session
* @return Promise
*/
MyList.instanceById = function(myListMeta, session) {
var id, list;
id = myListMeta.id;
list = new MyList(myListMeta, session);
if (MyList._cache[id] != null) {
return Promise.resolve(MyList._cache[id]);
}
return list.fetch().then(function() {
return Promise.resolve(list);
});
};
/**
* マイリストが最新の内容に更新された時に発火します
* @event MyList#did-refresh
* @property {MyList} list
*/
/**
* マイリストから項目が削除された時に発火します
* @event MyList#did-delete-item
* @property {MyList} list
* @property {MyListItem} item
*/
/**
* @private
* @property {NicoSession} _session セッション
*/
MyList.prototype._session = null;
/**
* @private
* @property {Object} _urlSet MyList APIのurl
*/
MyList.prototype._urlSet = null;
/**
* @private
* @property {Object} _attr マイリスト情報
*/
MyList.prototype._attr = null;
/**
* @property {Array.<MyListItem>} items 登録されている動画のリスト
*/
MyList.prototype.items = null;
/*
* @param {MyListMeta} metaInfo 操作対象の MyListMetaのインスタンス。
* @param {NicoSession} session セッション
*/
function MyList(metaInfo, _session) {
this._session = _session;
this._attr = metaInfo.toJSON();
this.items = [];
Object.defineProperties(this, {
id: {
get: function() {
return metaInfo.get("id");
}
},
_urlSet: {
value: metaInfo.get("id") === "home" ? NicoUrl.MyList.DefList : NicoUrl.MyList.Normal
}
});
}
/**
* このマイリストが"とりあえずマイリスト"か調べます。
* @return {boolean} とりあえずマイリストならtrueを返します。
*/
MyList.prototype.isDefaultList = function() {
return this.id === "home";
};
/**
* マイリストに登録されている動画を取得します。
*
* @fires MyList#refreshed
* @return {Promise}
*/
MyList.prototype.fetch = function(options) {
return Request.get({
resolveWithFullResponse: true,
url: sprintf(this._urlSet.LIST, this.id),
jar: this._session.cookie
})["catch"](function(e) {
return Promise.reject(new NicoException({
message: "Failed to fetch items (Connection error: " + e.message + ")",
previous: e
}));
}).then((function(_this) {
return function(res) {
var e, error, json;
try {
json = JSON.parse(res.body);
} catch (error) {
e = error;
return Promise.reject(new NicoException({
message: "Failed to parse response",
response: res.body,
previous: e
}));
}
if (json.status !== "ok") {
return Promise.reject(new NicoException({
message: "Failed to fetch contents (unknown)",
response: res.body
}));
}
_this.items = [];
_.each(json.mylistitem.reverse(), function(item) {
var m;
m = MyListItem.fromApiResponse(item, _this);
return _this.items.push(m);
});
_this.emit("did-refresh", {
list: _this
});
};
})(this));
};
/**
* マイリストのメタ情報を取得します。
* @param {string} attr 取得する属性名
*/
MyList.prototype.attr = function(attr) {
return this._attr[attr];
};
/**
* @private
* @param {MyListItem|Array.<MyListItem>} items
*/
MyList.prototype._pickHavingItemIds = function(items) {
var havingItemIds, havingItems, validItems;
if (!Array.isArray(items)) {
items = [items];
}
validItems = _.select(items, function(item) {
return item instanceof MyListItem;
});
havingItems = _.select(items, "list", this);
return havingItemIds = _.pluck(havingItems, 'id');
};
/**
* マイリストに動画を追加します。
* @param {NicoVideoInfo|string} movie 追加する動画のNicoVideoInfoオブジェクトか動画ID
* @param {string?} desc マイリストの動画メモの内容
* @return {Promise}
*/
MyList.prototype.addMovie = function(movie, desc) {
var id, req;
if (desc == null) {
desc = "";
}
id = null;
if (!typeof movie !== "string" && (movie.id == null)) {
return Promise.reject(new TypeError("Invalid type for argument 1(movie)"));
} else {
id = _.isString(movie) ? movie : movie.id;
}
req = {
item_type: 0,
item_id: id,
token: null,
description: desc,
group_id: this.id
};
this.isDefaultList() && (delete req.group_id);
return this._session.mylist.fetchToken().then((function(_this) {
return function(token) {
req.token = token;
return Request.post({
resolveWithFullResponse: true,
url: _this._urlSet.ADD,
jar: _this._session.cookie,
form: req
});
};
})(this)).then((function(_this) {
return function(res) {
var e, error, result;
try {
result = JSON.parse(res.body);
} catch (error) {
e = error;
return Promise.reject("Mylist[%s]: Failed to add item (JSON parse error)");
}
if (result.status !== "ok") {
return Promise.reject(new NicoException({
message: result.error.description,
response: result
}));
}
return Promise.resolve({
response: result
});
};
})(this));
};
/**
* マイリストから項目を削除します。
*
* 渡されたアイテム内のこのリストの項目でないものは無視されます。
*
* @param {MyListItem|Array.<MyListItem>} items 削除する項目の配列
* @return {Promise} 成功した時に削除された項目数でresolveします。
*/
MyList.prototype.deleteItem = function(items) {
var itemIds;
itemIds = this._pickHavingItemIds(items);
if (itemIds.length === 0) {
return Promise.resolve({
response: null
});
}
return this._session.mylist.fetchToken().then((function(_this) {
return function(token) {
var req;
req = {
group_id: _this.id,
"id_list[0]": itemIds,
token: token
};
if (_this.isDefaultList()) {
delete req.group_id;
}
return Request.post({
resolveWithFullResponse: true,
url: _this._urlSet.DELETE,
jar: _this._session.cookie,
form: req
});
};
})(this)).then(function(res) {
var e, error, result;
try {
result = JSON.parse(res.body);
} catch (error) {
e = error;
return Promise.reject(new Error("Mylist[%s]: Failed to delete item (JSON parse error)"));
}
if (result.status === "ok") {
return Promise.resolve({
response: json
});
} else {
e = new Error(sprintf("MyList[%s]: Failed to delete item (reason: %s)", this.id, result.error.description));
e.response = json;
return Promise.reject(e);
}
});
};
/**
* マイリストから別のマイリストへ項目を移動します。
*
* 渡された項目内のこのリストの項目でないものは無視されます。
*
* @param {MyListItem|Array.<MyListItem>} items 移動する項目の配列
* @param {MyList} targetMyList 移動先のマイリスト
* @return {Promise}
*/
MyList.prototype.moveItem = function(items, targetMyList) {
var itemIds;
if (!(targetMyList instanceof MyList)) {
throw new TypeError("targetMyList must be instance of MyList");
}
itemIds = this._pickHavingItemIds(items);
if (itemIds.length === 0) {
return Promise.resolve({
response: null
});
}
return this._session.mylist.fetchToken().then((function(_this) {
return function(token) {
var req;
req = {
group_id: _this.id,
target_group_id: targetMyList.id,
"id_list[0]": itemIds,
token: token
};
if (_this.isDefaultList()) {
delete req.group_id;
}
return Request.post({
resolveWithFullResponse: true,
url: _this._urlSet.MOVE,
jar: _this._session.cookie,
form: req
});
};
})(this)).then(function(res) {
var e, error, result;
try {
result = JSON.parse(res.body);
} catch (error) {
e = error;
return Promise.reject("Mylist[%s]: Failed to delete item (JSON parse error)");
}
if (result.status === "ok") {
return Promise.resolve({
response: json
});
} else {
e = new Error(sprintf("MyList[%s]: Failed to delete item (reason: %s)", this.id, result.error.description));
e.response = result;
return Promise.reject(e);
}
});
};
MyList.prototype.onDidRefresh = function(listener) {
return this.on("did-refresh", listener);
};
MyList.prototype.onDidDeleteItem = function(listener) {
return this.on("did-delete-item", listener);
};
return MyList;
})(Emitter);
}).call(this);