-
-
Save taizooo/182804 to your computer and use it in GitHub Desktop.
This file contains hidden or 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/* | |
// @include http://search.twitter.com/* | |
// @include http://pcod.no-ip.org/* | |
// @require http://gist.github.com/198443.txt | |
// ==/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 = createDocumentFromString(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 twitManually(stat){ | |
var base = 'http://twitter.com/'; | |
var url = base + '?status=' + encodeURIComponent(stat); | |
GM_openInTab(url); | |
} | |
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 = createDocumentFromString(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); | |
}); | |
} | |
} | |
function getUrl(stdin){ | |
// 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); | |
}) | |
return data; | |
} | |
var count = 0; | |
Minibuffer.addCommand({ | |
name : 'Twitter::ReTweet', | |
command : function(stdin){ | |
if(stdin.length){ | |
var id = "retweet" + count++; | |
Minibuffer.status(id, 'ReTweet...'); | |
var data = getUrl(stdin); | |
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.addCommand({ | |
name : 'Twitter::ReTweet::Manually', | |
command : function(stdin){ | |
if(stdin.length){ | |
var data = getUrl(stdin); | |
with(DC){ | |
parallel(data.map(function(url){ | |
return xhttp.get(url).next(function(res){ | |
var text = parseText(res.responseText, url); | |
return twitManually(text).next(function(){ | |
}); | |
}); | |
})) | |
} | |
} | |
return stdin; | |
} | |
}); | |
function getTarget(){ | |
return Minibuffer.execute((/\/\/twitter\.com\/.*?\/(status|statuses)\/\d+/.test(location.href))? 'location' : 'pinned-or-current-link'); | |
} | |
Minibuffer.addShortcutkey({ | |
key : 't', | |
description : 'ReTweet', | |
command : function(){ | |
try { | |
var stdin = getTarget(); | |
}catch(e) { | |
var stdin = []; | |
} | |
Minibuffer.execute('Twitter::ReTweet|clear-pin',stdin); | |
} | |
}); | |
Minibuffer.addShortcutkey({ | |
key : 'T', | |
description : 'ReTweet::Manually', | |
command : function(){ | |
try { | |
var stdin = getTarget(); | |
}catch(e) { | |
var stdin = []; | |
} | |
Minibuffer.execute('Twitter::ReTweet::Manually|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