Created
August 19, 2009 06:28
-
-
Save Constellation/170204 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name ReTweetCommand | |
// @namespace http://d.hatena.ne.jp/Constellation/ | |
// @description ReTweet Command for LDRize | |
// @include http://twitter.com/* | |
// @include https://twitter.com/* | |
// ==/UserScript== | |
function boot(ev){ | |
if(ev) window.removeEventListener('GM_MinibufferLoaded', boot, false); | |
var win = unsafeWindow; | |
var Minibuffer = window.Minibuffer; | |
var $X = Minibuffer.$X; | |
var D = Minibuffer.D; | |
var DC = D(); | |
function $A(arr){ | |
return Array.slice.call(arr); | |
} | |
function parseText(text, url){ | |
// RT Template | |
// RT @username: tweet | |
var dom = HTMLStringToDOM(text); | |
var account = url.match('http://twitter\\.com/([^/]+)')[1]; | |
var res = $X('descendant::span[contains(concat(" ",normalize-space(@class)," ")," entry-content ")]', dom).map(function(node){ return node.textContent }).join(""); | |
return "RT @" + account + ": " + res; | |
} | |
// inspired from Mochikit.DOM.formContents | |
// MIT License | |
// はじめはTreeWalkerをつかってやろうと意気込みましたが, | |
// GMContextで使えずlocation='javascript:~をする必要があるのか, | |
// DOMからつくったのがわるいのかだめだったので, 安易なwalkerに変更 | |
function walker(element, func){ | |
(function loop(elm){ | |
var res = func(elm); | |
if(res){ | |
$A(res).forEach(function(node){ | |
loop(node); | |
}); | |
} | |
})(element); | |
} | |
function formContents(form){ | |
var hash = {}; | |
walker(form, function(node){ | |
try{ | |
var name = node.getAttribute('name'); | |
} catch(e){ | |
return node.childNodes; | |
} | |
if(name){ | |
var tag = node.tagName.toLowerCase(); | |
if(tag === 'input' && (node.type === 'radio' || node.type === 'checkbox') && !node.checked){ | |
return null; | |
} else if(tag === 'form' || tag === 'p' || tag === "span" || tag === 'div'){ | |
return node.childNodes; | |
} else if(tag === 'select'){ | |
if(node.type === 'select-one'){ | |
if(node.selectedIndex >= 0){ | |
hash[name] = node.options[node.selectedIndex].value; | |
return null; | |
} else { | |
hash[name] = ''; | |
return null; | |
} | |
} else { | |
var opts = $A(node.options); | |
if(!opts.length){ | |
hash[name] = ""; | |
return null; | |
} else { | |
opts.forEach(function(opt, index){ | |
if(opt.selected){ | |
hash[name] = opt.value; | |
} | |
}); | |
return null; | |
} | |
} | |
} | |
hash[name] = node.value || ''; | |
return node.childNodes; | |
} else { | |
return node.childNodes; | |
} | |
}); | |
return hash; | |
} | |
function hashToData(hash){ | |
var list = []; | |
for(key in hash) list.push(encodeURIComponent(key)+'='+encodeURIComponent(hash[key])); | |
return list.join('&'); | |
} | |
function twit(stat){ | |
var action = 'http://twitter.com/status/update'; | |
var page = 'http://twitter.com/home'; | |
with(DC){ | |
return xhttp.get(page).next(function(res){ | |
var text = res.responseText; | |
var dom = HTMLStringToDOM(text); | |
var form = $X('id("status_update_form")', dom)[0].wrappedJSObject; | |
var hash = formContents(form); | |
hash['status'] = stat; | |
var data = hashToData(hash); | |
return xhttp.post(action, data); | |
}); | |
} | |
} | |
// from http://gist.github.com/164430 | |
// thanks id:snaka and id:os0x | |
function HTMLStringToDOM(str){ | |
var html = String(str).replace(/<script(?:[ \t\r\n][^>]*)?>[\S\s]*?<\/script[ \t\r\n]*>|<\/?(?:i?frame|html|script|object)(?:[ \t\r\n][^<>]*)?>/gi, ' '); | |
var htmlDoc = document.implementation.createHTMLDocument ? | |
document.implementation.createHTMLDocument('HTMLParser') : | |
document.implementation.createDocument(null, 'html', null); | |
var range = document.createRange(); | |
range.selectNodeContents(document.documentElement); | |
htmlDoc.documentElement.appendChild(htmlDoc.importNode(range.createContextualFragment(html),true)); | |
return htmlDoc; | |
} | |
var count = 0; | |
Minibuffer.addCommand({ | |
name : 'Twitter::ReTweet', | |
command : function(stdin){ | |
if(stdin.length){ | |
var id = "retweet" + count++; | |
Minibuffer.status(id, 'ReTweet...'); | |
// locationとpinned-or-current-linkの違いを吸収 | |
var data = (typeof stdin[0] === 'string')? stdin : stdin.map(function(node){ return node.href }); | |
data = data.filter(function(url){ | |
return /\/\/twitter\.com\/.*?\/(status|statuses)\/\d+/.test(url); | |
}) | |
with(DC){ | |
parallel(data.map(function(url){ | |
return xhttp.get(url).next(function(res){ | |
var text = parseText(res.responseText, url); | |
return twit(text).next(function(){ | |
}); | |
}); | |
})).next(function(){ | |
Minibuffer.status(id, 'Done', 100); | |
}); | |
} | |
} | |
return stdin; | |
} | |
}); | |
Minibuffer.addShortcutkey({ | |
key : 't', | |
description : 'ReTweet', | |
command : function(){ | |
try { | |
var stdin = Minibuffer.execute((/\/\/twitter\.com\/.*?\/(status|statuses)\/\d+/.test(location.href))? 'location' : 'pinned-or-current-link'); | |
}catch(e) { | |
var stdin = []; | |
} | |
Minibuffer.execute('Twitter::ReTweet|clear-pin',stdin); | |
} | |
}); | |
} | |
if(window.Minibuffer){ | |
boot(); | |
} else { | |
window.addEventListener('GM_MinibufferLoaded', boot, false); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment