// Last Change: 12-Jun-2009. Jan 2008 var PLUGIN_INFO = {NAME} Flv Downloader for Nicovideo Trapezoid 0.5 MIT License 2.0pre 2.0pre https://github.com/vimpr/vimperator-plugins/raw/master/ldrizecooperation_fetch_flv.js || Direct download flv from Nicovideo. ||< === :nicomylist === >|| Select Nicovideo Mylist of registration destination. ||< == Parts == - http://d.hatena.ne.jp/fls/20080309/p1 - Pagerization (c) id:ofk - AutoPagerize (c) id:swdyjh - JSDeferred id:cho45 == Variables == === g:nicovideo_mylist == >|| Nicovideo Mylist of registration destination. ||< ]]> ; (function () { function Deferred () this instanceof Deferred ? this.init(this) : new Deferred(); Deferred.prototype = { init : function () { this._next = null; this.callback = { ok: function (x) x, ng: function (x) { throw x } }; return this; }, next : function (fun) this._post("ok", fun), error : function (fun) this._post("ng", fun), call : function (val) this._fire("ok", val), fail : function (err) this._fire("ng", err), cancel : function () { (this.canceller || function () {})(); return this.init(); }, _post : function (okng, fun) { this._next = new Deferred(); this._next.callback[okng] = fun; return this._next; }, _fire : function (okng, value) { var self = this, next = "ok"; try { value = self.callback[okng].call(self, value); } catch (e) { next = "ng"; value = e; } if (value instanceof Deferred) { value._next = self._next; } else if (self._next) { self._next._fire(next, value); } return this; } }; Deferred.next = function (fun) { var d = new Deferred(); var id = setTimeout(function () { clearTimeout(id); d.call() }, 0); if (fun) d.callback.ok = fun; d.canceller = function () { try { clearTimeout(id) } catch (e) {} }; return d; }; Deferred.wait = function (n) { var d = new Deferred(), t = new Date(); var id = setTimeout(function () { d.call((new Date).getTime() - t.getTime()); }, n * 1000); d.canceller = function () { clearTimeout(id) }; return d; }; function http (opts) { var d = Deferred(); var req = new XMLHttpRequest(); req.open(opts.method, opts.url, true, opts.user || null, opts.password || null); if (opts.headers) { for (var k in opts.headers) if (opts.headers.hasOwnProperty(k)) { req.setRequestHeader(k, opts.headers[k]); } } req.onreadystatechange = function () { if (req.readyState == 4) d.call(req); }; req.send(opts.data || null); d.xhr = req; return d; } http.get = function (url) http({method:"get", url:url}); http.post = function (url, data) http({method:"post", url:url, data:data, headers:{"Content-Type":"application/x-www-form-urlencoded"}}); Deferred.Deferred = Deferred; Deferred.http = http; // copied from AutoPagerize (c) id:swdyh function getElementsByXPath(xpath, node){ node = node || document; var nodesSnapshot = (node.ownerDocument || node).evaluate(xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var data = []; for(var i = 0, l = nodesSnapshot.snapshotLength; i < l; data.push(nodesSnapshot.snapshotItem(i++))); return (data.length > 0) ? data : null; } function getFirstElementByXPath(xpath, node){ node = node || document; var result = (node.ownerDocument || node).evaluate(xpath, node, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); return result.singleNodeValue ? result.singleNodeValue : null; } // copied from Pagerization (c) id:ofk function parseHTML(str, ignoreTags) { var exp = "^[\\s\\S]*?]*)?>|[\\S\\s]*$"; if (ignoreTags) { if (typeof ignoreTags == "string") ignoreTags = [ignoreTags]; var stripTags = []; ignoreTags = ignoreTags.filter(function(tag) tag[tag.length - 1] == "/" || !stripTags.push(tag)) .map(function(tag) tag.replace(/\/$/, "")); if (stripTags.length > 0) { stripTags = stripTags.length > 1 ? "(?:" + stripTags.join("|") + ")" : String(stripTags); exp += "|<" + stripTags + "(?:\\s[^>]*|/)?>|"; } } str = str.replace(new RegExp(exp, "ig"), ""); var res = document.implementation.createDocument(null, "html", null); var range = document.createRange(); range.setStartAfter(window.content.document.body); res.documentElement.appendChild(res.importNode(range.createContextualFragment(str), true)); if (ignoreTags) ignoreTags.forEach(function(tag) { var elements = res.getElementsByTagName(tag); for (var i = elements.length, el; el = elements.item(--i); el.parentNode.removeChild(el)); }); return res; } var DownloadManager = Cc['@mozilla.org/download-manager;1'] .getService(Ci.nsIDownloadManager); const nicoApiEndPoint = 'http://www.nicovideo.jp/api/getflv?v='; const nicoWatchEndPoint = 'http://www.nicovideo.jp/watch/'; var groupId = liberator.globalVariables.nicovideo_mylist || ''; function NiconicoFlvHandler(url, title) { let videoId = url.match(/\w{2}\d+/)[0]; let fileName = title.replace(/[?\\*\/:<>|"]/g, '_') + '.flv'; Deferred.http.get(nicoApiEndPoint + videoId).next(function(apiResult){ let flvUrl = decodeURIComponent(apiResult.responseText.match(/url=(.*?)&/)[1]); return Deferred.http.get(nicoWatchEndPoint + videoId).next(function(watchPage){ let WebBrowserPersist = Cc['@mozilla.org/embedding/browser/nsWebBrowserPersist;1'] .createInstance(Ci.nsIWebBrowserPersist); let sourceUri = makeURI(flvUrl, null, null); let file = DownloadManager.userDownloadsDirectory; file.appendRelativePath(fileName); let fileUri = makeFileURI(file); let download = DownloadManager.addDownload( 0, sourceUri, fileUri, fileName, null, null, null, null, WebBrowserPersist ); WebBrowserPersist.progressListener = download; WebBrowserPersist.saveURI(sourceUri, null, null, null, null, file); }); }).error(function(e){ log(e); liberator.echoerr(e); }); } var count = 0; function NiconicoMylistHandler(url, title){ let videoId = url.match(/\w{2}\d+/)[0]; Deferred.wait(count++ * 5).next(function(est){ return Deferred.http.get(nicoWatchEndPoint + videoId).next(function(watchResult){ var html = parseHTML(watchResult.responseText, ['img', 'script']); var csrfToken = getElementsByXPath('//input[@name="csrf_token"]', html)[0].value; var mylists = getElementsByXPath('id("mylist_add_group_id")/option', html).map(function(element) [element.innerHTML, element.value]); var params = [['ajax', '1'], ['mylist', 'add'], ['mylist_add', '“o˜^'], ['csrf_token', csrfToken], ['group_id', groupId]].map(function(p) p[0] + "=" + encodeURIComponent(p[1])).join("&"); return Deferred.wait(count++ * 5).next(function(est){ return Deferred.http.post(nicoWatchEndPoint + videoId, params).next(function(mylistResult){ liberator.log(mylistResult.responseText); }); }); }); }).error(function(e){ log(e); liberator.echoerr(e); }); } function setupLDRizeCooperationNiconicoFlvFetcher() { let NiconicoFlvFetcher = { pattern: 'http://www.nicovideo.jp/watch/*', handler: { download: NiconicoFlvHandler, mylist: NiconicoMylistHandler }, wait: 5000, }; this.convertHandlerInfo([NiconicoFlvFetcher]); this.handlerInfo.unshift(NiconicoFlvFetcher); } if (liberator.plugins.LDRizeCooperation === undefined) { liberator.plugins.LDRizeCooperationPlugins = liberator.plugins.LDRizeCooperationPlugins || []; liberator.plugins.LDRizeCooperationPlugins.push(setupLDRizeCooperationNiconicoFlvFetcher); } else { setupLDRizeCooperationNiconicoFlvFetcher.apply(liberator.plugins.LDRizeCooperation); } function httpGET(uri, callback) { let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) callback.call(this,xhr.responseText); else throw new Error(xhr.statusText) } }; xhr.open('GET', uri, true); xhr.send(null); } liberator.modules.commands.addUserCommand( ['fetchflv'], 'Download flv file from Nicovideo', function (arg) { httpGET( arg.string || liberator.modules.buffer.URL, function (responseText) { let [, title] = responseText.match(/]*)?>([^<]*)<\/title[ \t\n\r]*>/i); liberator.log(title); NiconicoFlvHandler(arg.string || liberator.modules.buffer.URL, title); } ); }, {} ); liberator.modules.commands.addUserCommand( ['nicomylist'], 'Select Nicovideo mylist', function (arg) { groupId = arg.string; }, { completer: function(context,arg){ Deferred.http.get(nicoWatchEndPoint + "sm2757983").next(function(watchResult){ var html = parseHTML(watchResult.responseText, ['img', 'script']); var mylists = getElementsByXPath('id("mylist_add_group_id")/option', html).map(function(element) [element.value, element.innerHTML]); context.title = ['ID', 'Name']; context.advance = mylists.length; context.completions = mylists; }).error(function(e){ log(e); liberator.echoerr(e); }); } }); })(); Hk0aG9VXpvxZPPLWp8nQx'+ 'x77qH+KnflVZlzgcWrVrVvrF9rgnC0AKji5T/G9xM6Blad7zSSHFDnUfL5z9/2zfzbSKttInixjW'+ 'V6YfXsbxf/3//3f/d3Km7WyVv9H+//3/33vTUgxaNj5ZxbA+Ir136cu/rz8ueXnsCe+u/EcrX616'+ 'v+lfyR7WhPNNdU+2MKx3TV+54Oersre7fn/4v+l/5v8Vf6a9F311bPOa2BMNa57sY1g3LW3K7Luf'+ 'nf9s/PPyz+Q/LUC48k/V14DVz6KZ6k89Ocyw6lei65yMjz4f7T6afDT7aA6Elh95P85Y+z2iq+78'+ 'k9UMW8vzxTtMN0ZvrATDio05GxM3hm/cMvFrhlvno2dxDF9Nbh+9Gn/19NUzUHj66kkgPH91y1WH'+ 'O1e/yzEQjk0CAAARc29gwOvTnwAAAABJRU5ErkJggg=='; var gmailBiffIntervals = parseInt(liberator.globalVariables.gmbf_check_intervals || 30) * 1000; var gmailBiffIcon = document.createElement('statusbarpanel'); gmailBiffIcon.setAttribute('id','gmail-biff-icon'); gmailBiffIcon.setAttribute('class','statusbarpanel-iconic'); gmailBiffIcon.setAttribute('src', ICON2); gmailBiffIcon.setAttribute('tooltip', 'gmail-biff-tip'); gmailBiffIcon.addEventListener("click",function(e){ liberator.open("https://mail.google.com/", liberator.NEW_TAB); },false); var gmailBiffTip = document.createElement('tooltip'); gmailBiffTip.setAttribute('id','gmail-biff-tip'); var gmailBiffText = document.createElement('description'); gmailBiffText.setAttribute('id','gmail-biff-text'); gmailBiffTip.appendChild(gmailBiffText); document.getElementById('status-bar') .insertBefore(gmailBiffIcon,document.getElementById('security-button').nextSibling); document.getElementById('status-bar').appendChild(gmailBiffTip); setTimeout(function() { try { var form = ['https://www.google.com', 'https://www.google.com', null]; var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); var logins = passwordManager.findLogins({}, form[0], form[1], form[2]); if(logins.length) var [gmailUser, gmailPassword] = [logins[0].username, logins[0].password]; else { liberator.echoerr("Gmail Biff: account not found"); var promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"] .getService(Ci.nsIPromptService); var user = { value : null }; var pass = { value : null }; var ret = promptSvc.promptUsernameAndPassword( window, form[0], "GMail Biff Login", user, pass, null, {}); if(ret){ var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init"); [gmailUser, gmailPassword] = [user.value, pass.value]; var formLoginInfo = new nsLoginInfo( form[0], form[1], form[2], gmailUser, gmailPassword, '', ''); passwordManager.addLogin(formLoginInfo); } return; } const feed_url = 'https://mail.google.com/mail/feed/atom'; var xhr = new XMLHttpRequest(); xhr.mozBackgroundRequest = true; xhr.open("GET", feed_url, false, gmailUser, gmailPassword); xhr.send(null); var count = parseInt(xhr.responseXML.getElementsByTagName('fullcount')[0].childNodes[0].nodeValue); gmailBiffIcon.setAttribute('src', count > 0 ? ICON1 : ICON2); gmailBiffText.setAttribute('value', count > 0 ? 'You have new mail (' + count + ')' : 'No new mail'); setTimeout(arguments.callee, gmailBiffIntervals); } catch(e) { liberator.log(e); liberator.echoerr("Gmail Biff: " + e); } }, 1000); })(); // vim:sw=4 ts=4 et: