|
(function() { |
|
if ('nicotag_getTagsInfo' in window) |
|
return; |
|
|
|
const parseISO8601 = (function() { |
|
const regexp = new RegExp( |
|
"^([0-9]{4})(?:-([0-9]{2})(?:-([0-9]{2})" + |
|
"(?:T([0-9]{2}):([0-9]{2})(?::([0-9]{2})(?:\.([0-9]+))?)?" + |
|
"(?:Z|(?:([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$"); |
|
return function (string) { |
|
var d = string.match(regexp); |
|
if(d == null) return null; |
|
var offset = 0; |
|
var date = new Date(d[1], 0, 1); |
|
|
|
if (d[2]) { date.setMonth(d[2] - 1); } |
|
if (d[3]) { date.setDate(d[3]); } |
|
if (d[4]) { date.setHours(d[4]); } |
|
if (d[5]) { date.setMinutes(d[5]); } |
|
if (d[6]) { date.setSeconds(d[6]); } |
|
if (d[7]) { date.setMilliseconds(Number("0." + d[7]) * 1000); } |
|
if (d[8]) { |
|
offset = (Number(d[9]) * 60) + Number(d[10]); |
|
offset *= ((d[8] == '-') ? 1 : -1); |
|
} |
|
|
|
offset -= date.getTimezoneOffset(); |
|
var time = (Number(date) + (offset * 60 * 1000)); |
|
date.setTime(Number(time)); |
|
return date; |
|
}; |
|
})(); |
|
|
|
const Getter = function(videoID) { |
|
this._videoID = videoID; |
|
this._callbacks = []; |
|
}; |
|
|
|
Getter.prototype = { |
|
_callbacks: null, _lock: false, |
|
_cache: null, |
|
get: function(callback, forceUpdate) { |
|
if (this._cache !== null && !forceUpdate) { |
|
if (typeof callback === 'function') |
|
callback(true, this._cache); |
|
return; |
|
} |
|
|
|
if (typeof callback === 'function') |
|
this._callbacks.push(callback); |
|
|
|
if (this._lock) return; |
|
this._lock = true; |
|
|
|
let self = this; |
|
function finish(isSuccess, data) { |
|
if (isSuccess) |
|
self._cache = data; |
|
self._callbacks.forEach(function(f) f(isSuccess, data)); |
|
self._callbacks.length = 0; |
|
self._lock = false; |
|
} |
|
|
|
let url = 'http://www.nicotag.jp/api/' |
|
+ (forceUpdate ? 'updtagsinfo' : 'gettagsinfo') + '/' + this._videoID; |
|
GM_xmlhttpRequest({ |
|
method: 'GET', |
|
url: url, |
|
headers: { 'User-Agent': 'Mozilla/5.0 Greasemonkey; NicoTag Tab' }, |
|
onload: function(response) { |
|
if (response.status === 200) |
|
finish(true, self._parse(response.responseText)); |
|
else |
|
finish(false, response); |
|
}, |
|
onerror: function(response) finish(false, response) |
|
}); |
|
}, |
|
_parse: function(text) { |
|
let parser = new DOMParser(); |
|
let xml = parser.parseFromString(text, 'application/xml'); |
|
|
|
function get(elem, attr) elem.getElementsByTagName(attr)[0].textContent; |
|
let tags = this._parseTags(xml, get); |
|
|
|
return { |
|
count: get(xml, 'keep_count'), |
|
first: parseISO8601(get(xml, 'first_keep')), |
|
last: parseISO8601(get(xml, 'last_keep')), |
|
tags: tags |
|
}; |
|
}, |
|
_parseTags: function(xml, get) { |
|
let tags = Array.map( |
|
xml.getElementsByTagName('tag'), |
|
function(tag) { |
|
let obj = { |
|
id: tag.getAttribute('id'), |
|
name: get(tag, 'name'), |
|
first: parseISO8601(get(tag, 'first_added')), |
|
last: parseISO8601(get(tag, 'last_added')), |
|
good: parseInt(get(tag, 'good'), 10), |
|
bad: parseInt(get(tag, 'bad'), 10), |
|
rank: parseInt(get(tag, 'rank'), 10) |
|
}; |
|
return obj; |
|
}); |
|
|
|
return tags; |
|
} |
|
}; |
|
|
|
let getters = {}; |
|
getters.__proto__ = null; |
|
window.nicotag_getTagsInfo = function(videoID, callback, forceUpdate) { |
|
let getter = null; |
|
if (videoID in getters) { |
|
getter = getters[videoID]; |
|
} else { |
|
getter = new Getter(videoID); |
|
getters[videoID] = getter; |
|
} |
|
getter.get(callback, forceUpdate); |
|
}; |
|
})(); |