From 3bd4861d4da5152ccc6e50f02f206d95cd46fe6a Mon Sep 17 00:00:00 2001 From: anekos Date: Fri, 30 Jul 2010 14:27:18 +0000 Subject: ChirpUserStream 対応した趣を感じる事が、君は出来るか! git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@38058 d0d07461-0603-4401-acd4-de1884942a52 --- twittperator.js | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 206 insertions(+), 16 deletions(-) diff --git a/twittperator.js b/twittperator.js index 3924e9b..cf43f88 100755 --- a/twittperator.js +++ b/twittperator.js @@ -984,6 +984,20 @@ TwitterOauth.prototype = (function() { }; xmlhttpRequest(options); // 送信 }, + getUrl: function (api) { + var message = { + method: "GET", + action: api, + parameters: { + oauth_signature_method: "HMAC-SHA1", + oauth_consumer_key: this.accessor.get("consumerKey",""),// queryの構築 + oauth_token: this.accessor.get("token","") // Access Token + } + }; + OAuth.setTimestampAndNonce(message); + OAuth.SignatureMethod.sign(message, this.getAccessor()); + return OAuth.addToURL(message.action, message.parameters); + }, // utility関数 // http://kevin.vanzonneveld.net urlEncode : function(str) { @@ -1053,6 +1067,138 @@ TwitterOauth.prototype = (function() { })(); // }}} +// ChirpUserStream +let ChirpUserStream = (function () { + + const JSON = Cc['@mozilla.org/dom/json;1'].getService(Ci.nsIJSON); + + function getUserInfo () { + let host = ['http://twitter.com', 'https://twitter.com']; + let loginManager = Cc['@mozilla.org/login-manager;1'].getService(Ci.nsILoginManager); + let login = loginManager.findLogins({}, host[0], host[1], null)[0]; + return login; + } + + + function extractURL (s) + let (m = s.match(/https?:\/\/[\S]+/)) + (m && m[0]); + + + function start () { + stop(); + + let host = 'chirpstream.twitter.com'; + let path = '/2b/user.json'; + + if (0) { + host = 'api.twitter.com'; + host = '/1/statuses/mentions.json'; + } + + let {username, password} = getUserInfo(); + let socketService = + let (stsvc = Cc['@mozilla.org/network/socket-transport-service;1']) + let (svc = stsvc.getService()) + svc.QueryInterface(Ci['nsISocketTransportService']); + + let transport = socketService.createTransport(null, 0, host, 80, null); + let os = transport.openOutputStream(0, 0, 0); + let is = transport.openInputStream(0, 0, 0); + let sis = Cc['@mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream); + let sos = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream); + + sis.init(is); + sos.setOutputStream(os); + + let params = ['Authorization: Basic ' + btoa(username + ':' + password)]; + if (0) { + let param = tw.getUrl('http://' + host + path); + let params = param.split(/\?/)[1].split(/&/).map(function (it) + let ([n, v] = it.split(/=/)) + n + ': ' + decodeURIComponent(v) + ); + } + + let get = [ + 'GET ' + path + ' HTTP/1.1', + 'Host: ' + host, + params.join('\n'), + '' + ].join('\n'); + get += '\n\n'; + + sos.write(get, get.length); + + let buf = ''; + let interval = setInterval(function () { + let len = sis.available(); + if (len <= 0) + return; + let data = sis.read(len); + liberator.log(data); + let lines = data.split(/\n/); + if (lines.length > 2) { + lines[0] = buf + lines[0]; + for (let [, line] in Iterator(lines.slice(0, -1))) { + try { + onMsg(JSON.decode(line), line); + } catch (e) {} + } + buf = lines.slice(-1)[0]; + } else { + buf += data; + } + }, 500); + + __context__.prev = { + sos: sos, + sis: sis, + interval: interval, + }; + } + + + function stop () { + let prev = __context__.prev; + + if (!prev) + return; + + clearInterval(prev.interval); + prev.sos.close(); + prev.sis.close(); + + delete __context__.prev; + } + + + function onMsg (msg, raw) { + if (msg.text) { + let talk = msg.user.screen_name + ': ' + msg.text; + + liberator.echo(talk, commandline.FORCE_SINGLELINE); + liberator.log(talk); + + history.unshift(msg); + if (history.length > 1000) + history = history.slice(0, 1000); + + if (plugins.namakubi) + plugins.namakubi.talk(talk); + } else { + let s = []; + for (let [n, v] in Iterator(msg)) + s.push(n + ': ' + (n == 'user' ? v.screen_name : v)); + liberator.log(s.join('\n')); + } + } + + return { + start: start, + stop: stop + }; +})(); // Twittperator function xmlhttpRequest(options) { // {{{ @@ -1071,10 +1217,18 @@ let accessor = storage.newMap("twittperator", { store: true }); accessor.set("clientName", "Twittperator"); accessor.set("consumerKey", "GQWob4E5tCHVQnEVPvmorQ"); accessor.set("consumerSecret","gVwj45GaW6Sp7gdua6UFyiF910ffIety0sD1dv36Cz8"); + +let history; +if (__context__.hasOwnProperty('history')) { + history = __context__.history; + liberator.registerObserver('exit', function () accessor.set("history", history)); +} else { + history = __context__.history = accessor.get("history", []); +} + let tw = new TwitterOauth(accessor); plugins.twittperator = tw; -let statuses = []; let expiredStatus = false; let autoStatusUpdate = !!parseInt(liberator.globalVariables.twittperator_auto_status_update || 0); let statusValidDuration = parseInt(liberator.globalVariables.twitperator_status_valid_duration || 90); @@ -1139,6 +1293,18 @@ function showTwitterSearchResult(word) { // {{{ }); } // }}} function getFollowersStatus(target, force, onload) { // {{{ + if (target) { + api = "http://api.twitter.com/1/statuses/user_timeline.json"; + query.screen_name = target; + tw.get(api, query, function(text){ + onload(JSON.parse(text)); + }); + } else { + onload(history); + } + return; + + // TODO 両対応に function setRefresher(){ expiredStatus = false; if (statusRefreshTimer) @@ -1158,7 +1324,7 @@ function getFollowersStatus(target, force, onload) { // {{{ } tw.get(api, query, function(text) { setRefresher(); - statuses = JSON.parse(text); + history = JSON.parse(text); onload(); }); } @@ -1244,22 +1410,43 @@ function setup() { // {{{ bang: true, literal: 0, completer: let (getting, targetContext) function(context, args) { - function compl() { + function filter (item) + let (desc = item.description) + (this.match(desc.user.screen_name) || this.match(desc.text)); + + function compl(){ + targetContext.createRow = function (item, highlightGroup) { + let desc = item[1] || this.process[1].call(this, item, item.description); + + if (desc && desc.user) { + return