| 1 | // ==UserScript== |
|---|
| 2 | // @name ShareTwitterOnTumblr |
|---|
| 3 | // @namespace http://white.s151.xrea.com/ |
|---|
| 4 | // @description Share Twitter conversation on Tumblr as Chat |
|---|
| 5 | // @include http://twitter.com/* |
|---|
| 6 | // @include https://twitter.com/* |
|---|
| 7 | // @include http://explore.twitter.com/* |
|---|
| 8 | // @include http://m.twitter.com/* |
|---|
| 9 | // @include http://twitter.1x1.jp/search/* |
|---|
| 10 | // @include http://search.twitter.com/search* |
|---|
| 11 | // ==/UserScript== |
|---|
| 12 | |
|---|
| 13 | // this script require Minibuffer.user.js and LDRize.user.js. |
|---|
| 14 | // |
|---|
| 15 | // How to use: |
|---|
| 16 | // 1. access http://twitter.com/home |
|---|
| 17 | // 2. type 'j' or 'k' to select status |
|---|
| 18 | // 3. type 'p' to pin |
|---|
| 19 | // 4. type M-x ( this mean Alt+x ) |
|---|
| 20 | // 5. type "pinned-or-current-link | share-twitter-on-tumblr" ( not need " ) and Enter |
|---|
| 21 | // 6. access your Tumblr. status you pinned will be listed. |
|---|
| 22 | // |
|---|
| 23 | // latest version: |
|---|
| 24 | // http://coderepos.org/share/browser/lang/javascript/userscripts/sharetwitterontumblr.user.js? |
|---|
| 25 | |
|---|
| 26 | (function(){ |
|---|
| 27 | |
|---|
| 28 | // if (typeof document.documentElement.namespaceURI != "undefined" && |
|---|
| 29 | // document.documentElement.namespaceURI == "http://www.w3.org/1999/xhtml") return; |
|---|
| 30 | |
|---|
| 31 | var $X = window.Minibuffer.$X |
|---|
| 32 | var D = window.Minibuffer.D |
|---|
| 33 | var status = window.Minibuffer.status |
|---|
| 34 | var createDocumentFromString = window.Minibuffer.createDocumentFromString |
|---|
| 35 | |
|---|
| 36 | function getSource(url){with(D()){return xhttp.get(url)}} |
|---|
| 37 | function postData(url, aData){with(D()){return xhttp.post(url, aData)}} |
|---|
| 38 | |
|---|
| 39 | function isTwitterStatusURL(aURL){ |
|---|
| 40 | return new RegExp("^https?://(?:(?:explore|m)\\.)?twitter\\.com/[^/]+/status(?:es)?/\\d+").test(aURL); |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | function parseStatus(doc, aURL){ |
|---|
| 44 | function normalizeText(arr){ |
|---|
| 45 | return arr.map(function(a){return a.nodeValue.replace(/^\s+|\s+$/g,'')}).join(' ') |
|---|
| 46 | } |
|---|
| 47 | // normalize external anchor |
|---|
| 48 | var arr = $X('span[@class="entry-meta"]/a[starts-with(@href,"http")]',doc); |
|---|
| 49 | //var arr = $X('id("permalink")/div/p[1]/a[starts-with(@href,"http")]',doc); |
|---|
| 50 | //var arr = $X('span[@class="published"]/a[starts-with(@href,"http")]',doc); |
|---|
| 51 | arr.forEach(function(node){ |
|---|
| 52 | node.parentNode.replaceChild( document.createTextNode(node.getAttribute('href')),node); |
|---|
| 53 | }); |
|---|
| 54 | // normalize anchor for reply |
|---|
| 55 | var arr = $X('id("permalink")/div/p[1]/a[starts-with(@href,"/")]', doc); |
|---|
| 56 | arr.forEach(function(node){ |
|---|
| 57 | node.parentNode.replaceChild( |
|---|
| 58 | document.createTextNode(node.previousSibling.textContent +node.textContent), |
|---|
| 59 | node.previousSibling); |
|---|
| 60 | node.parentNode.removeChild(node); |
|---|
| 61 | }); |
|---|
| 62 | // scrape status |
|---|
| 63 | //var body = normalizeText($X('id("permalink")/div/p[1]//text()', doc)); |
|---|
| 64 | var body = normalizeText($X('//span[@class="entry-content"]//text()', doc)); |
|---|
| 65 | var name = aURL.match('http?://(?:(?:explore|m)\\.)?twitter\\.com/([^/]+)')[1]; |
|---|
| 66 | return encodeURIComponent(name + ":" + body + " [" + aURL + "]") |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | function parseParams(doc){ |
|---|
| 70 | var elms = $X('id("edit_post")//*[name()="input" or name()="textarea" or name()="select"]', doc); |
|---|
| 71 | var params = {}; |
|---|
| 72 | elms.forEach(function(elm){ |
|---|
| 73 | params[elm.name] = elm.value; |
|---|
| 74 | }); |
|---|
| 75 | return params; |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | function createPostData(params, body){ |
|---|
| 79 | var arr = []; |
|---|
| 80 | var param; |
|---|
| 81 | for(param in params){ |
|---|
| 82 | if(param != "preview_post"){ |
|---|
| 83 | arr.push(encodeURIComponent(param)); |
|---|
| 84 | arr.push("="); |
|---|
| 85 | arr.push((param == "post[two]") ? body.join("%0D%0A") : encodeURIComponent(params[param])) |
|---|
| 86 | arr.push("&"); |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | return arr.join('') |
|---|
| 90 | } |
|---|
| 91 | |
|---|
| 92 | function share(body){ |
|---|
| 93 | var url = "http://www.tumblr.com/new/chat"; |
|---|
| 94 | getSource(url). |
|---|
| 95 | next(function(res){ |
|---|
| 96 | return postData(url, createPostData( parseParams( createDocumentFromString(res.responseText)), body)) |
|---|
| 97 | }). |
|---|
| 98 | error(function(arg){ |
|---|
| 99 | console.log('error',arg) |
|---|
| 100 | }); |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | window.Minibuffer.addCommand({ |
|---|
| 104 | name: 'share-twitter-on-tumblr', |
|---|
| 105 | command: function(stdin){ |
|---|
| 106 | var args = this.args; |
|---|
| 107 | var urls = []; |
|---|
| 108 | if(!stdin.length){ |
|---|
| 109 | // command line is just 'share-twitter-on-tumblr' |
|---|
| 110 | urls = [window.location.href]; |
|---|
| 111 | }else if(stdin.length && stdin.every(function(a){return a.nodeName == 'A'})){ |
|---|
| 112 | // command line is 'pinned-or-current-link | share-twitter-on-tumblr' |
|---|
| 113 | urls = stdin.map(function(node){return node.href}); |
|---|
| 114 | }else{ |
|---|
| 115 | status('ShareTwitterOnTumblr'+time, 'command line error!', 1000); |
|---|
| 116 | return stdin; |
|---|
| 117 | } |
|---|
| 118 | var time = new Date().getTime(); |
|---|
| 119 | if(!urls.every(isTwitterStatusURL)){ |
|---|
| 120 | status('ShareTwitterOnTumblr'+time, 'There is invalid URL', 1000); |
|---|
| 121 | return stdin; |
|---|
| 122 | } |
|---|
| 123 | // older -> newer |
|---|
| 124 | urls.sort(function(a,b){ |
|---|
| 125 | return a.match(/\d+$/)[0] - b.match(/\d+$/)[0]; |
|---|
| 126 | }); |
|---|
| 127 | with(D()){ |
|---|
| 128 | status('ShareTwitterOnTumblr'+time, 'Share ...'); |
|---|
| 129 | parallel(urls.map(function(aURL){ |
|---|
| 130 | return getSource(aURL). |
|---|
| 131 | next(function(res){ |
|---|
| 132 | return parseStatus( createDocumentFromString(res.responseText), aURL); |
|---|
| 133 | })})). |
|---|
| 134 | next(function(arg){ |
|---|
| 135 | var i; |
|---|
| 136 | function toArray(o){var res=[];for(i in o)res[i]=o[i];return res;} |
|---|
| 137 | share(toArray(arg)); |
|---|
| 138 | }). |
|---|
| 139 | next(function(arg){ |
|---|
| 140 | status('ShareTwitterOnTumblr'+time, 'Share ... done', 100); |
|---|
| 141 | }) |
|---|
| 142 | } |
|---|
| 143 | return stdin; |
|---|
| 144 | } |
|---|
| 145 | }); |
|---|
| 146 | })(); |
|---|