| 1 | // Vimperator plugin: "Update Twitter" |
|---|
| 2 | // Last Change: 21-Jan-2009. Jan 2008 |
|---|
| 3 | // License: Creative Commons |
|---|
| 4 | // Maintainer: Trapezoid <trapezoid.g@gmail.com> - http://unsigned.g.hatena.ne.jp/Trapezoid |
|---|
| 5 | // |
|---|
| 6 | // The script allows you to update Twitter status from Vimperator 0.6.*. |
|---|
| 7 | // |
|---|
| 8 | // Commands: |
|---|
| 9 | // :twitter some thing text |
|---|
| 10 | // post "some thing text" to Twitter. |
|---|
| 11 | // :twitter! someone |
|---|
| 12 | // show someone's statuses. |
|---|
| 13 | // :twitter!? someword |
|---|
| 14 | // show search result of 'someword' from "http://search.twitter.com/". |
|---|
| 15 | // :twitter!@ |
|---|
| 16 | // show mentions. |
|---|
| 17 | // :twitter!+ someone |
|---|
| 18 | // fav someone's last status.. |
|---|
| 19 | // :twitter!- someone |
|---|
| 20 | // un-fav someone's last status.. |
|---|
| 21 | |
|---|
| 22 | (function(){ |
|---|
| 23 | var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); |
|---|
| 24 | var evalFunc = window.eval; |
|---|
| 25 | try { |
|---|
| 26 | var sandbox = new Components.utils.Sandbox(window); |
|---|
| 27 | if (Components.utils.evalInSandbox("true", sandbox) === true){ |
|---|
| 28 | evalFunc = function(text){ |
|---|
| 29 | return Components.utils.evalInSandbox(text, sandbox); |
|---|
| 30 | }; |
|---|
| 31 | } |
|---|
| 32 | } catch (e){ liberator.log("warning: twitter.js is working with unsafe sandbox."); } |
|---|
| 33 | |
|---|
| 34 | function sprintf(format){ |
|---|
| 35 | var i = 1, re = /%s/, result = "" + format; |
|---|
| 36 | while (re.test(result) && i < arguments.length) result = result.replace(re, arguments[i++]); |
|---|
| 37 | return result; |
|---|
| 38 | } |
|---|
| 39 | function getElementsByXPath(xpath, node){ |
|---|
| 40 | node = node || document; |
|---|
| 41 | var nodesSnapshot = (node.ownerDocument || node).evaluate(xpath, node, null, |
|---|
| 42 | XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); |
|---|
| 43 | var data = []; |
|---|
| 44 | for(var i = 0, l = nodesSnapshot.snapshotLength; i < l; |
|---|
| 45 | data.push(nodesSnapshot.snapshotItem(i++))); |
|---|
| 46 | return (data.length > 0) ? data : null; |
|---|
| 47 | } |
|---|
| 48 | function getFirstElementByXPath(xpath, node){ |
|---|
| 49 | node = node || document; |
|---|
| 50 | var doc = node.ownerDocument; |
|---|
| 51 | var result = (node.ownerDocument || node).evaluate(xpath, node, null, |
|---|
| 52 | XPathResult.FIRST_ORDERED_NODE_TYPE, null); |
|---|
| 53 | return result.singleNodeValue ? result.singleNodeValue : null; |
|---|
| 54 | } |
|---|
| 55 | function sayTwitter(username, password, stat){ |
|---|
| 56 | var xhr = new XMLHttpRequest(); |
|---|
| 57 | xhr.open("POST", "https://twitter.com/statuses/update.json", false, username, password); |
|---|
| 58 | xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); |
|---|
| 59 | xhr.send("status=" + encodeURIComponent(stat) + "&source=Vimperator"); |
|---|
| 60 | liberator.echo("[Twitter] Your post " + '"' + stat + '" (' + stat.length + " characters) was sent. " ); |
|---|
| 61 | } |
|---|
| 62 | function favTwitter(username, password, user){ |
|---|
| 63 | var xhr = new XMLHttpRequest(); |
|---|
| 64 | xhr.open("GET", "https://twitter.com/statuses/user_timeline/" + user + ".json?count=1", false, username, password); |
|---|
| 65 | xhr.send(null); |
|---|
| 66 | xhr.open("POST", "https://twitter.com/favourings/create/" + window.eval(xhr.responseText)[0].id + ".json", false, username, password); |
|---|
| 67 | xhr.send(null); |
|---|
| 68 | } |
|---|
| 69 | function unfavTwitter(username, password, user){ |
|---|
| 70 | var xhr = new XMLHttpRequest(); |
|---|
| 71 | xhr.open("GET", "https://twitter.com/statuses/user_timeline/" + user + ".json?count=1", false, username, password); |
|---|
| 72 | xhr.send(null); |
|---|
| 73 | xhr.open("DELETE", "https://twitter.com/favourings/destroy/" + window.eval(xhr.responseText)[0].id + ".json", false, username, password); |
|---|
| 74 | xhr.send(null); |
|---|
| 75 | } |
|---|
| 76 | function showTwitterMentions(username, password){ |
|---|
| 77 | var xhr = new XMLHttpRequest(); |
|---|
| 78 | xhr.open("GET", "https://twitter.com/statuses/mentions.json", false, username, password); |
|---|
| 79 | xhr.send(null); |
|---|
| 80 | var statuses = evalFunc(xhr.responseText); |
|---|
| 81 | |
|---|
| 82 | var html = <style type="text/css"><![CDATA[ |
|---|
| 83 | span.twitter.entry-content a { text-decoration: none; } |
|---|
| 84 | img.twitter.photo { border; 0px; width: 16px; height: 16px; vertical-align: baseline; } |
|---|
| 85 | ]]></style>.toSource() |
|---|
| 86 | .replace(/(?:\r\n|[\r\n])[ \t]*/g, " ") + |
|---|
| 87 | statuses.map(function(status) |
|---|
| 88 | <> |
|---|
| 89 | <img src={status.user.profile_image_url} |
|---|
| 90 | alt={status.user.screen_name} |
|---|
| 91 | title={status.user.screen_name} |
|---|
| 92 | class="twitter photo"/> |
|---|
| 93 | <strong>{status.user.name}‬</strong> |
|---|
| 94 | </>.toSource() |
|---|
| 95 | .replace(/(?:\r\n|[\r\n])[ \t]*/g, " ") + |
|---|
| 96 | sprintf(': <span class="twitter entry-content">%s‬</span>', status.text)) |
|---|
| 97 | .join("<br/>"); |
|---|
| 98 | |
|---|
| 99 | liberator.echo(html, true); |
|---|
| 100 | } |
|---|
| 101 | function showFollowersStatus(username, password, target){ |
|---|
| 102 | var xhr = new XMLHttpRequest(); |
|---|
| 103 | var endPoint = target ? "https://twitter.com/statuses/user_timeline/" + target + ".json" |
|---|
| 104 | : "https://twitter.com/statuses/friends_timeline.json"; |
|---|
| 105 | xhr.open("GET", endPoint, false, username, password); |
|---|
| 106 | xhr.send(null); |
|---|
| 107 | var statuses = evalFunc(xhr.responseText) || []; |
|---|
| 108 | |
|---|
| 109 | var html = <style type="text/css"><![CDATA[ |
|---|
| 110 | span.twitter.entry-content a { text-decoration: none; } |
|---|
| 111 | img.twitter.photo { border; 0px; width: 16px; height: 16px; vertical-align: baseline; margin: 1px; } |
|---|
| 112 | ]]></style>.toSource() |
|---|
| 113 | .replace(/(?:\r\n|[\r\n])[ \t]*/g, " ") + |
|---|
| 114 | statuses.map(function(status) |
|---|
| 115 | <> |
|---|
| 116 | <img src={status.user.profile_image_url} |
|---|
| 117 | alt={status.user.screen_name} |
|---|
| 118 | title={status.user.screen_name} |
|---|
| 119 | class="twitter photo"/> |
|---|
| 120 | <strong>{status.user.name}‬</strong> |
|---|
| 121 | : <span class="twitter entry-content">{status.text}</span> |
|---|
| 122 | </>.toSource() |
|---|
| 123 | .replace(/(?:\r\n|[\r\n])[ \t]*/g, " ")) |
|---|
| 124 | .join("<br/>"); |
|---|
| 125 | |
|---|
| 126 | liberator.echo(html, true); |
|---|
| 127 | } |
|---|
| 128 | function showTwitterSearchResult(word){ |
|---|
| 129 | var xhr = new XMLHttpRequest(); |
|---|
| 130 | xhr.open("GET", "http://search.twitter.com/search.json?q=" + encodeURIComponent(word), false); |
|---|
| 131 | xhr.send(null); |
|---|
| 132 | var results = (evalFunc("("+xhr.responseText+")") || {"results":[]}).results; |
|---|
| 133 | |
|---|
| 134 | var html = <style type="text/css"><![CDATA[ |
|---|
| 135 | span.twitter.entry-content a { text-decoration: none; } |
|---|
| 136 | img.twitter.photo { border; 0px; width: 16px; height: 16px; vertical-align: baseline; margin: 1px; } |
|---|
| 137 | ]]></style>.toSource() |
|---|
| 138 | .replace(/(?:\r\n|[\r\n])[ \t]*/g, " ") + |
|---|
| 139 | results.map(function(result) |
|---|
| 140 | <> |
|---|
| 141 | <img src={result.profile_image_url} |
|---|
| 142 | alt={result.from_user} |
|---|
| 143 | title={result.from_user} |
|---|
| 144 | class="twitter photo"/> |
|---|
| 145 | <strong>{result.from_user}‬</strong> |
|---|
| 146 | : <span class="twitter entry-content">{result.text}</span> |
|---|
| 147 | </>.toSource() |
|---|
| 148 | .replace(/(?:\r\n|[\r\n])[ \t]*/g, " ")) |
|---|
| 149 | .join("<br/>"); |
|---|
| 150 | |
|---|
| 151 | liberator.echo(html, true); |
|---|
| 152 | } |
|---|
| 153 | liberator.modules.commands.addUserCommand(["twitter"], "Change Twitter status", |
|---|
| 154 | function(arg, special){ |
|---|
| 155 | var password; |
|---|
| 156 | var username; |
|---|
| 157 | try { |
|---|
| 158 | var logins = passwordManager.findLogins({}, "http://twitter.com", "https://twitter.com", null); |
|---|
| 159 | if (logins.length) |
|---|
| 160 | [username, password] = [logins[0].username, logins[0].password]; |
|---|
| 161 | else |
|---|
| 162 | throw "Twitter: account not found"; |
|---|
| 163 | } |
|---|
| 164 | catch (ex){ |
|---|
| 165 | liberator.echoerr(ex); |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | arg = arg.string.replace(/%URL%/g, liberator.modules.buffer.URL) |
|---|
| 169 | .replace(/%TITLE%/g, liberator.modules.buffer.title); |
|---|
| 170 | |
|---|
| 171 | if (special && arg.match(/^\?\s*(.*)/)) |
|---|
| 172 | showTwitterSearchResult(RegExp.$1); |
|---|
| 173 | else |
|---|
| 174 | if (special && arg.match(/^\+\s*(.*)/)) |
|---|
| 175 | favTwitter(username, password, RegExp.$1); |
|---|
| 176 | else |
|---|
| 177 | if (special && arg.match(/^-\s*(.*)/)) |
|---|
| 178 | unfavTwitter(username, password, RegExp.$1); |
|---|
| 179 | else |
|---|
| 180 | if (special && arg.match(/^@/)) |
|---|
| 181 | showTwitterMentions(username, password); |
|---|
| 182 | else |
|---|
| 183 | if (special || arg.length == 0) |
|---|
| 184 | showFollowersStatus(username, password, arg); |
|---|
| 185 | else |
|---|
| 186 | sayTwitter(username, password, arg); |
|---|
| 187 | },{ |
|---|
| 188 | bang: true, |
|---|
| 189 | literal: 0 |
|---|
| 190 | } |
|---|
| 191 | ); |
|---|
| 192 | })(); |
|---|
| 193 | // vim:sw=4 ts=4 et: |
|---|