Skip to content

Instantly share code, notes, and snippets.

@Constellation
Created August 19, 2009 06:28
Show Gist options
  • Save Constellation/170204 to your computer and use it in GitHub Desktop.
Save Constellation/170204 to your computer and use it in GitHub Desktop.
// ==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