Created
March 23, 2012 14:57
-
-
Save quietlynn/2171459 to your computer and use it in GitHub Desktop.
Google+ Conditional Fuu
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
/* | |
Google+ Conditional Fuu => Automatically reply posts on certain conditions. | |
Copyright (C) 2012 Jingqin Lynn | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
// ==UserScript== | |
// @name Google+ Conditional Fuu | |
// @namespace http://project.quietmusic.org/j/ | |
// @description Automatically reply posts on certain conditions. | |
// @match https://plus.google.com/* | |
// ==/UserScript== | |
(function() { | |
//Use the <base> element to detect Google+ main page. | |
var base = document.querySelector('base'); | |
if (!base) return; | |
if (!base.href.match(/^https:\/\/plus\.google\.com(\/u\/\d+)?\/?/)) return; | |
//Chrome V8 don't support unsafeWindow. Time for a hack. | |
if (window == unsafeWindow) { | |
var span = document.createElement('span'); | |
span.setAttribute('onclick', 'return window;'); | |
unsafeWindow = span.onclick(); | |
} | |
//For shorter code. | |
var win = unsafeWindow; | |
win.ext = win.ext || {}; | |
if (win.ext.condFuu) { | |
return; | |
} else { | |
win.ext.condFuu = {}; | |
} | |
var main = function($) { | |
var getLocale = function() { | |
var lang = { | |
'en': { | |
'fuuDefaultValue' : 'Fuu', | |
'input_cond_xpath' : 'Please input the XPath expression for the posts to be auto-replyed.', | |
'input_reply_value' : 'Please input the text of the reply:' | |
}, | |
'zh-hans': { | |
'fuuDefaultValue' : '呼', | |
'input_cond_xpath' : '请输入自动回复时,贴子需要满足的条件(XPath 表达式):', | |
'input_reply_value' : '请输入自动回复的文本:' | |
}, | |
}; | |
//alias for languages | |
lang['zh-cn'] = lang['zh-hans']; | |
lang['zh-sg'] = lang['zh-hans']; | |
lang['zh-tw'] = lang['zh-hant']; | |
lang['zh-hk'] = lang['zh-hant']; | |
lang['zh'] = lang['zh-hans']; //fallback | |
lang[''] = lang['en']; //general fallback | |
var langCode = localStorage.getItem('cond-fuu-lang') || $.gplus.getLangCode(); | |
var loc = lang[langCode]; | |
if(!loc) { | |
loc = lang[langCode.substr(0,2)]; | |
if(!loc) { | |
loc = lang['']; | |
} | |
} | |
return loc; | |
}; | |
var fuuOnPost = function (post) { | |
var fuuComplete = function() { | |
post.stopDynamicSelect(handler); | |
$('.ext-fuu-button').attr('data-ext-fuu-ed', 'true'); | |
}; | |
var handler = post.dynamicSelect('.g-z-e-Ia-df', function(ed) { | |
fuu(ed, post, fuuComplete); | |
}); | |
$.gplus.doClick($('.rBJ4nd', post)[0]); | |
}; | |
//Add fuu-text to the editor and then submit the reply. | |
var fuu = function (ed, post, callback) { | |
if(ed.children.length == 0) { | |
var onNodeInserted = function(e) { | |
if(!e) e = event; | |
ed.removeEventListener('DOMNodeInserted', onNodeInserted, false); | |
fuu(ed, post, callback); | |
} | |
ed.addEventListener('DOMNodeInserted', onNodeInserted, false); | |
return; | |
} | |
if(ed.children[0].tagName == 'DIV') { | |
if(callback) callback(); | |
var handler = $(ed).dynamicSelect('iframe', function (frame) { | |
$(ed).stopDynamicSelect(handler); | |
//The content in the frame is changing, and DOMNodeInserted won't work. | |
//Use setInterval as a workaround. | |
var it = setInterval(function() { | |
if(frame.contentDocument.body.classList.contains('editable')) { | |
clearInterval(it); | |
fuu(frame.contentDocument.body, post); | |
} | |
}, 100); | |
}); | |
return; | |
} | |
if(callback) callback(); | |
//ed.ownerDocument.body.scrollIntoView(ed); | |
ed.textContent = localStorage.getItem('cond-fuu-text') || loc['fuuDefaultValue']; | |
//"Input" something to enable the submit button. | |
$.gplus.doKeypress(ed); | |
var submit = $('.b-a-ga', post); | |
if(submit.attr('aria-disabled') != 'true') { | |
$.gplus.doClick(submit[0]); | |
} | |
else { | |
//Webkit don't support DOMAttrModified. | |
//Use setInterval as workaround. | |
//Todo: use DOMAttrModified on supported browsers such as Firefox. | |
var it = setInterval(function() { | |
if(submit.attr('aria-disabled') != 'true') { | |
clearInterval(it); | |
$.gplus.doClick(submit[0]); | |
}; | |
}, 100); | |
} | |
return true; | |
}; | |
var showSettingUI = function (e) { | |
var fuuText = localStorage.getItem('cond-fuu-text') || loc['fuuDefaultValue']; | |
localStorage.setItem('cond-fuu-text', prompt(loc['input_reply_value'], fuuText) || fuuText); | |
var fuuXPath = localStorage.getItem('cond-fuu-xpath') || 'false()'; | |
localStorage.setItem('cond-fuu-xpath', prompt(loc['input_cond_xpath'], fuuXPath) || fuuXPath); | |
localStorage.setItem('cond-fuu-lastPost', new Date()); | |
if (e) e.preventDefault(); | |
}; | |
//Init | |
var loc = getLocale(); | |
//Match any new posts | |
$(document.body).dynamicSelect('.Te', function(post) { | |
post = $(post); | |
var handler = post.dynamicSelect('.k-Qf-C-RySO6d.UzyZPb', function (postLink) { | |
var title = postLink.getAttribute('title'); | |
if (title != "Timestamp") { | |
post.stopDynamicSelect(handler); | |
var time = new Date(title); | |
var lastTime = new Date(localStorage.getItem('cond-fuu-lastPost')); | |
if (time && time > lastTime && post.xpath(localStorage.getItem('cond-fuu-xpath') || 'false()', 'boolean')) { | |
localStorage.setItem('cond-fuu-lastPost', time); | |
post.attr('data-ext-cond-fuu', 'matched'); | |
fuuOnPost(post); | |
} | |
} | |
}); | |
}); | |
$(document.body).dynamicSelect('.afEYIc', function(button) { | |
$(button).on('contextmenu', showSettingUI); | |
}); | |
}; | |
if(win.ext.toolkitReady) { | |
main(win.jQuery); | |
} else { | |
win.ext.toolkitCallback = win.ext.toolkitCallback || []; | |
win.ext.toolkitCallback.push(main); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment