Skip to content

Instantly share code, notes, and snippets.

@quietlynn
Created March 23, 2012 14:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save quietlynn/2171459 to your computer and use it in GitHub Desktop.
Save quietlynn/2171459 to your computer and use it in GitHub Desktop.
Google+ Conditional Fuu
/*
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