Skip to content

Instantly share code, notes, and snippets.

@saitamanodoruji
Created March 29, 2010 10:50
Show Gist options
  • Save saitamanodoruji/347734 to your computer and use it in GitHub Desktop.
Save saitamanodoruji/347734 to your computer and use it in GitHub Desktop.
Share2chOnTumblr
// ==UserScript==
// @name Share2chOnTumblr
// @namespace http://saitamanodoruji.tumblr.com/
// @description Share 2ch conversation on Tumblr as Quote
// @include http://*.2ch.net/test/read.cgi/*
// @include http://*.2ch.net/*/kako/*
// @include http://*.bbspink.com/test/read.cgi/*
// @include http://jbbs.livedoor.jp/bbs/read.cgi/*
// @include http://jbbs.livedoor.jp/*/*/*/*.html
// @include http://p2.chbox.jp/read.php?url=http://*.2ch.net/test/read.cgi/*
// @include http://mimizun.com/*
// @include http://unkar.org/r/*
// @include http://yomi.mobi/read.cgi/temp/*
// @include http://ex14.vip2ch.com/test/read.cgi/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://*.2ch.net/test/read.cgi/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://*.2ch.net/*/kako/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://*.bbspink.com/test/read.cgi/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://jbbs.livedoor.jp/bbs/read.cgi/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://jbbs.livedoor.jp/*/*/*/*.html
// @include http://webcache.googleusercontent.com/search?q=cache:http://p2.chbox.jp/read.php?url=http://*.2ch.net/test/read.cgi/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://mimizun.com/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://unkar.org/r/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://yomi.mobi/read.cgi/temp/*
// @include http://webcache.googleusercontent.com/search?q=cache:http://ex14.vip2ch.com/test/read.cgi/*
// @version 0.2.12
// @update 2013-12-26
// ==/UserScript==
// 必要なもの:
// LDRize http://coderepos.org/share/browser/lang/javascript/userscripts/ldrize.user.js?
// Minibuffer http://coderepos.org/share/browser/lang/javascript/userscripts/minibuffer.user.js?
// sharedObject http://exe.tyo.ro/2011/11/greasemonkey0912minibufferldrize.html
//
// 使い方:
// 1. 2ちゃんねるのスレを開く
// 2. j、k で Quote したいレスを選んで p で pin する
// 3. ショートカットキーの q を押すか、Alt + x で Minibuffer を開いて
// pinned-or-current-node|share2chontumblr|clear-pin と入れて Enter を押す
// 4. pin したレスがまとまって 1 個の Quote ポストになる
//
// reference:
// ShareTwitterOnTumblr by snj14
// http://white.s151.xrea.com/blog/2008-03-02-09-30.html
// 2ch.extractor.js by ku
// http://gist.github.com/123087
// http://ku.tumblr.com/post/27747617
(function(){
// ----------------------------------------------------------------------------------------
// 設定
// ----------------------------------------------------------------------------------------
const KEY_TO_SHARE_IN_PLAIN_TEXT = 'q';
// プレーンテキストで Quote するためのショートカットキー
// 使わないときは 'q' を '' にする
//
const KEY_TO_SHARE_IN_HTML = 'Q';
// HTML で Quote するためのショートカットキー
// 使わないときは 'Q' を '' にする
//
const SHARE2CHONTUMBLR_HTML_QUOTE_FORMAT = 0;
// HTML Quote の形式
// 0: そのまま
// 1: 成形する (2ch.extractor.js 方式。dd,dt を使わないので Dashboard では見やすい)
//
const SHARE2CHONTUMBLR_POST_STATE = 0;
// 公開設定
// 0: publish now
// 1: save as draft
// 2: add to queue
// 3: private
//
const SHARE2CHONTUMBLR_ALLOW_PHOTO_REPLIES = 1;
// photo reply の許可
// 0: 不許可
// 1: 許可
//
const SEND_TO_TWITTER = 0;
// twitter にも送るか(送るには Tumblr に twitter account を登録する必要がある)
// 0: 送らない
// 1: 送る
// ----------------------------------------------------------------------------------------
const DSBD_URL = 'http://www.tumblr.com/dashboard';
const SECURE_FORM_KEY_URL = 'http://www.tumblr.com/svc/secure_form_key';
const UPDATE_URL = 'http://www.tumblr.com/svc/post/update';
var boot = function() {
var $X = sharedObject.Minibuffer.$X
var D = sharedObject.Minibuffer.D
var status = sharedObject.Minibuffer.status
var createDocumentFromString = sharedObject.Minibuffer.createDocumentFromString
function getSource(url){with(D()){return xhttp.get(url)}}
function postData(url, aData){with(D()){return xhttp.post(url, aData)}}
function createBody(stdin, format) {
var res = [];
var dt = stdin.map(function(s){return s.innerHTML;});
var dd = stdin.map(function(s){
if ( window.location.href.match(/^http:\/\/mimizun\.com/) ) {
var r = $X('./following-sibling::div[contains(concat(" ", @class, " "), " res ")]', s)[0]
.innerHTML.replace(/<br>/g, '<br />') + "<br /><br />";
var mimizunAdXPath = './/img[contains(@alt, "ads")] |' +
'.//img[contains(@alt, "ads")]/following-sibling::a |' +
'.//img[contains(@alt, "ads")]/following-sibling::br |' +
'.//script | .//noscript | .//noscript/following-sibling::br |' +
'.//iframe | .//iframe/following-sibling::br';
var doc = createDocumentFromString(r);
$X(mimizunAdXPath, doc).forEach(function(n) {n.parentNode.removeChild(n);});
return $X('//body', doc)[0].innerHTML.replace(/<br>/g, '<br />').replace(/\s+$/, '').replace(/<!--.*?-->/g, '');
} else {
return $X('./following-sibling::dd[not(contains(concat(" ", @class, " "), " respopup "))]', s)[0]
.innerHTML.replace(/<br>/g, '<br />');
}
});
if ( window.location.href.match(/^http:\/\/unkar\.org\/r/) ) {
var dd0 = createDocumentFromString(dd[0]);
var div0 = $X('//div[script]', dd0)[0];
if (div0) div0.parentNode.removeChild(div0);
dd[0] = $X('//body', dd0)[0].innerHTML;
dd = dd.map(function(dd){
return dd + '<br /><br />';
});
}
switch(format) {
// HTML (raw)
case 0:
for (i = 0; i < stdin.length; i++) {
dt[i] = '<dt>' + dt[i] + '</dt>';
dd[i] = '<dd>' + dd[i] + '</dd>';
res[i] = [dt[i], dd[i]].join('');
}
break;
// HTML (2ch.extractor.js)
case 1:
for (i = 0; i < stdin.length; i++) {
res[i] = [dt[i], dd[i]].join('<br />');
}
break;
// plain text
case 2:
for (i = 0; i < stdin.length; i++) {
dt[i] = stdin[i].textContent;
dd[i] = dd[i].replace(/<br \/>/g, '\n').replace(/<[^>]+>/g, '');
res[i] = [dt[i], dd[i]].join('\n');
}
break;
}
return res.join('');
}
function createSource(stdin) {
var resNums = [];
var resRange = '';
for (i = 0; i < stdin.length; i++) {
try {
resNums[i] = stdin[i].innerHTML.match(/^\s*(\d+)/)[1];
} catch(e) {}
}
if(resNums.length > 1) {
resNums.sort(function(a, b) { return a - b });
resRange = resNums[0] + '-' + resNums[resNums.length - 1];
} else if(resNums.length == 1) {
resRange = resNums[0];
}
if ( document.location.toString().match(/^((?:http:\/\/p2\.chbox\.jp\/read\.php\?url=)?http:\/\/(?:[^.]+\.(?:2ch\.net|bbspink\.com)\/test\/read\.cgi\/|mimizun\.com\/log\/2ch\/|yomi\.mobi\/read\.cgi\/temp\/[^_]+_[^_]+_)[^\/]+\/\d+)/) ) {
var url = RegExp.$1 + '/' + resRange;
} else {
var url = document.location.toString();
}
return '<a href="' + url + '">' + document.title + '</a>';
}
function parseParams(doc){
var elms = $X('id("edit_post")//*[translate(name(),"input", "INPUT") ="INPUT" or translate(name(),"textarea", "TEXTAREA")="TEXTAREA" or translate(name(),"select", "SELECT")="SELECT"]', doc);
var params = {};
elms.forEach(function(elm){
if(elm.nodeName == 'INPUT' && elm.type=='checkbox' && !elm.checked) {
params[elm.name] = '';
} else {
params[elm.name] = elm.value;
}
});
return params;
}
function createPostData(params, body, source){
var arr = [];
var param;
var postState = [0, 1, 2, 'private'];
for(param in params){
if (!/(?:preview_post|send_to_twitter|post\[promotion_type\]|post\[highlight\]|post\[typekit\])/.test(param)
|| (param == 'send_to_twitter' && SEND_TO_TWITTER) ) {
arr.push(encodeURIComponent(param));
arr.push('=');
if(param == 'post[one]') {
arr.push(body);
} else if(param == 'post[two]') {
arr.push(source);
} else if(param == 'post[source_url]') {
arr.push(decodeURIComponent(source).replace(/^<a href="([^"]*)">[^<]*<\/a>/, '$1'));
} else if(param == 'post[state]') {
arr.push(postState[SHARE2CHONTUMBLR_POST_STATE]);
} else if(param == 'allow_photo_replies' && SHARE2CHONTUMBLR_ALLOW_PHOTO_REPLIES) {
arr.push('on');
} else {
arr.push(encodeURIComponent(params[param]));
}
arr.push('&');
}
}
return arr.join('')
}
function share(body, source) {
var form_key, channel_id, secure_form_key, shared = D();
shared.xhttp.get(DSBD_URL).
next(function(res){
var doc = createDocumentFromString(res.responseText);
form_key = doc.querySelector('#search_form input[name="form_key"]').value;
channel_id = doc.querySelector('#search_form input[name="t"]').value;
return shared.xhttp({
method : 'post',
url : SECURE_FORM_KEY_URL,
headers : { 'X-tumblr-form-key': form_key },
});
}).
next(function(res){
secure_form_key = res.responseHeaders.match(/(?:^|\s)X-tumblr-secure-form-key: (.+)(?:$|\s)/)[1];
var data = {
form_key: form_key,
post: {},
context_id: '',
context_page: 'dashboard',
'is_rich_text[one]': '0',
'is_rich_text[two]': '0',
'is_rich_text[three]': '0',
channel_id: channel_id,
'post[slug]': '',
'post[source_url]': 'http://',
'post[date]': '',
'post[type]': 'quote',
'post[one]': body,
'post[two]': source,
'post[tags]': '',
'post[publish_on]': '',
'post[state]': ''
};
return shared.xhttp({
method: 'post',
url: UPDATE_URL,
data: JSON.stringify(data),
headers: {
'Content-Type' : 'application/json',
'X-tumblr-puppies' : secure_form_key,
},
});
}).
error(function(arg){
console.log('error',arg);
});
}
function share2chOnTumblr(stdin, format) {
if(!stdin.length){
status('Share2chOnTumblr', 'no item', 100);
} else {
var body = createBody(stdin, format);
var source = createSource(stdin);
var time = new Date().getTime();
with(D()){
next(function() {
share(body, source);
})
.next(function(res){
status('Share2chOnTumblr'+time, 'Share', 100);
})
}
}
}
sharedObject.Minibuffer.addCommand({
name: 'share-2ch-on-tumblr',
command: function(stdin) {
share2chOnTumblr(stdin, 2);
return stdin;
}
});
sharedObject.Minibuffer.addCommand({
name: 'share-2ch-on-tumblr-html',
command: function(stdin) {
share2chOnTumblr(stdin, SHARE2CHONTUMBLR_HTML_QUOTE_FORMAT);
return stdin;
}
});
if (KEY_TO_SHARE_IN_PLAIN_TEXT) {
sharedObject.Minibuffer.addShortcutkey({
key: KEY_TO_SHARE_IN_PLAIN_TEXT,
description: 'Share2chOnTumblr',
command : function(){
sharedObject.Minibuffer.execute('pinned-or-current-node|share-2ch-on-tumblr|clear-pin');
}
});
}
if (KEY_TO_SHARE_IN_HTML) {
sharedObject.Minibuffer.addShortcutkey({
key: KEY_TO_SHARE_IN_HTML ,
description: 'Share2chOnTumblr-HTML',
command : function(){
sharedObject.Minibuffer.execute('pinned-or-current-node|share-2ch-on-tumblr-html|clear-pin');
}
});
}
}
if (sharedObject.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