By Wizputer
Has no other scripts.
// ==UserScript==
// @name Facebook Poke O' Matic
// @version 1.5
// @author John Watson
// @namespace wizputer.pokeomatic
// @description Poke all button, with option to auto poke-all. Dialog of attempted pokees, and removes pokee from sidebar on success. A built in configurable poke limit with an override prompt. Displays poke counter with the limit. Pokes section hide button.
// @include http://facebook.com/home.php*
// @include http://*.facebook.com/home.php*
// @include http://apps.facebook.com/pokeomatic
// ==/UserScript==
//Author contact info: John Watson <wizputer@wizputer.net>
//Copyright (C) 2007. John Watson and contributor(s).
//This script 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; version 2 fo the License. More
//information and a copy of the license available at http://www.gnu.org/copyleft/gpl.html
//This script is distribute 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.
/******** CHANGE LOG ********/
// [2007-06-24][1.0][Initial release]
// [2007-06-25][1.1][Poke counter bug fix and added display of the poke counter.]
// [2007-06-26][1.2][Added a button to reset the poke counter when it's reached and the counter is updated when poking.]
// [2007-06-26][1.3][Added "Pokes" section even when no pokes for people to see the poke counter and enable/disable auto-poke. Also added a "hide" button to hide the "Pokes" section.]
// [2007-06-27][1.4][Rewrote the way the script searches for pokes.]
// [2007-07-09][1.5][Added Poke Stats logging. (Requires the Poke Stats application to be installed to your profile only, not either user script)]
// Enable this to get some console messages
var DEBUG = 0;
/******** GLOBALS ********/
// Values aren't based on any fact, suggestions would be appreciated
var MAX_POKES = GM_getValue("fb_max_pokes");
if (MAX_POKES == null) {
MAX_POKES = 100;
GM_setValue("fb_max_pokes",100);
}
// In seconds for accuracy
var MAX_TIME = GM_getValue("fb_max_time");
if (MAX_TIME == null) {
MAX_TIME = 60 * 60 * 24; //24 hours
GM_setValue("fb_max_time", MAX_TIME);
}
var AUTO_POKE = GM_getValue("fb_auto_poke");
if (AUTO_POKE == null) {
AUTO_POKE = 0; // Off
GM_setValue("fb_auto_poke", 0);
}
// Enable/Disable Poke Stats logging
var POKE_STATS = GM_getValue("fb_poke_stats");
if (POKE_STATS == null) {
POKE_STATS = 0; // Disabled
GM_setValue("fb_poke_stats",0);
}
// Holder for my FaceBook ID
var MY_ID = document.getElementById('user').value;
/******** FUNCTIONS ********/
// Retrieves pokers from sidebar and stores information into array, while adding the Poke All button and checkbox
// If there any pokers and either AUTO_POKE is on or user said to poke, pop up dialog stating number of people being poked and pass the array of info
// and update the number of pokes counter
// If at the set poke limit, show dialog asking if user wants to continue to poke or not
function getPokes(nomax,act){
var pokeInfo;
var date = new Date();
// Get current time from 1/1/1970 in seconds
var time = Math.floor(date.getTime()/1000);
// Get current number of pokes if time period hasnt elapsed, if it has reset to 0
var curNumPokes = (GM_getValue("fb_pokeEnd")>time)?GM_getValue("fb_numPokes"):0;
pokeInfo = new Array();
// Seperate document into divs
var divs = document.getElementsByTagName("div");
var pokesSection;
// Go through each one
for (var i = 0; i < divs.length; i++) {
// Find the pokes sidebar item
if (divs[i].getAttribute("class") == "sidebar_item pokes") {
pokesSection = divs[i].getElementsByTagName("div");
if (divs[i].getAttribute("id")!="pokes") {
// Add an id to the Pokes section to easily hide it
var idAttr = document.createAttribute("id");
idAttr.nodeValue = "pokes";
divs[i].setAttributeNode(idAttr);
}
break;
}
}
if (pokesSection != undefined) {
for (var i = 0; i < pokesSection.length; i++) {
// Find the pokers
if (pokesSection[i].getAttribute("class") == "ind_poke") {
// Add them into an array
pokeInfo.push(pokesSection[i]);
// Find the body
} else if (pokesSection[i].getAttribute("class") == "sidebar_item_body") {
var pokesBody = pokesSection[i].getElementsByTagName("div");
// Add the Poke All button and checkbox if they dont exist
if (pokesSection[i].innerHTML.indexOf('Poke All') == -1) {
pokesSection[i].innerHTML += '<form><table><tr>' +
'<td><input class="inputsubmit" type="button" id="poke_all" value="Poke All" /></td>' +
'<td><input id="auto_poke" type="checkbox" ' + ((AUTO_POKE)?'CHECKED':'') + '></td>' +
'<td><label for="auto_poke">Auto Poke All</label></td></tr>' +
'<tr><td id="poke_counter" colspan=3>Poke counter: ' + curNumPokes + '/' + MAX_POKES + ' pokes.</td></tr></table></form>';
}
// Find the header, and add the hide button if the pokes id doesnt exist (meaning it already hasnt been added)
} else if (pokesSection[i].getAttribute("class") == "sidebar_item_header clearfix" && pokesSection[i].innerHTML.indexOf('hide_pokes') == -1) {
pokesSection[i].innerHTML += '<div class="option"><a href="#" id="hide_pokes">hide</a></div>';
}
}
// If we have someone to poke, and user said to or auto poke is enabled
if (pokeInfo.length && (act || AUTO_POKE)) {
var dialog = new unsafeWindow.pop_dialog();
var newNumPokes = 0;
// If we haven't reached our max pokes yet, or if user already said to disregard the limit
if (((newNumPokes = (curNumPokes + pokeInfo.length)) < MAX_POKES) || nomax) {
// Get the post form id from the hidden field
var post_form_id = document.getElementById('post_form_id').value;
var pokedPage = "";
// Show dialog stating number of people to be poked
var html = '<div class="dialog_loading">Poking ' + pokeInfo.length + ' people...</div>';
dialog.show_dialog(html);
// Update the number of people poked for limit
updatePokes(pokeInfo.length);
// Start poking
poke(post_form_id,pokeInfo,pokedPage,dialog);
// Update counter
updateCounter(newNumPokes,MAX_POKES);
// Reached or going to reach limit by poking everyone
} else {
// Ask user to disregard the limit
dialog.show_choice("Max pokes reached!","Disregard max and poke anyways?","Yes",function(){getPokes(1,1);},"No",function(){dialog.fade_out(500, 1100);},"","Reset Counter",function(){resetCounter(); dialog.fade_out(500, 1100);});
}
}
} else {
insertPokesSection();
}
return false;
}
// Go through the pokeInfo array and poke everyone
function poke(post_form_id,pokeInfo,pokedPage,dialog){
// There are still people left to poke
if (pokeInfo.length > 0) {
// Get next person to poke
var div = pokeInfo.pop();
// Seperate into anchor tags
var hrefs = div.getElementsByTagName("a");
// Get the poker ID
var pokeId = hrefs[1].href.match(/id=(\d*)/)[1];
// Get the url to send poke to
var postUrl = hrefs[1].href.match(/http:\/\/(.*\.)facebook\.com/)[0] + "/poke.php";
// Create string to send to poke.php
var pokepost = "post_form_id=" + post_form_id + "&id=" + pokeId + "&confirmed=1&pokeback=1";
// Thanks to EZPoke (Lukas Fragodt & Mike Soh) for the onload and onerror functions
GM_xmlhttpRequest(
{
method:'POST',
url:postUrl,
headers:
{
'User-Agent':window.navigator.userAgent,
'Content-Type':'application/x-www-form-urlencoded',
},
data:pokepost,
onload: function(res) {
// OK
if (res.status == 200) {
if (res.responseText.indexOf('has not received your last poke yet') != -1) {
// Remove Poke and Remove links and replace with "Poked before!"
hrefs[1].removeAttribute('href');
hrefs[1].innerHTML = 'Poked before!';
hrefs[2].removeAttribute('href');
hrefs[2].innerHTML = '';
if (DEBUG) GM_log(hrefs[0].innerHTML + ' has not received your last poke');
} else if (res.responseText.indexOf('You have poked') != -1) {
// Remove the person we poked
remove(div);
// If Poke Stats logging is enabled, log the poke
if (POKE_STATS) pokeStatsLog(pokeId);
if (DEBUG) GM_log(hrefs[0].innerHTML + ' poked!');
// Unkown response
} else {
// Remove Poke and Remove links and replace with "Poke failed!"
hrefs[1].removeAttribute('href');
hrefs[1].innerHTML = 'Poke failed!';
hrefs[2].removeAttribute('href');
hrefs[2].innerHTML = '';
if (DEBUG) GM_log('Unkown reponse: ' + res.responseText);
}
// Received not OK status
} else {
// Remove Poke and Remove links and replace with "Poke failed!"
hrefs[1].removeAttribute('href');
hrefs[1].innerHTML = 'Poke failed!';
hrefs[2].removeAttribute('href');
hrefs[2].innerHTML = '';
if (DEBUG) GM_log('Poke failed, not OK response - status received: ' + res.status);
}
},
onerror: function(res) {
// Remove Poke and Remove links and replace with "Poke failed!"
hrefs[1].removeAttribute('href');
hrefs[1].innerHTML = 'Poke failed!';
hrefs[2].removeAttribute('href');
hrefs[2].innerHTML = '';
if (DEBUG) GM_log('Unkown error when poking. Status: ' + res.status + ' Text: ' + res.statusText);
}
});
// Update the poked page with name and profile link
pokedPage += '<a href="' + hrefs[0].href + '">' + hrefs[0].innerHTML + '</a><br>';
// Wait 100 milliseconds before doing next poke
setTimeout(poke,100,post_form_id,pokeInfo,pokedPage,dialog);
// No one left to poke
} else {
// Show the people we poked or tried to poke
dialog.show_message("Poked these people:",pokedPage);
if (DEBUG) GM_log('Poked list: ' + pokedPage);
}
return false;
}
// Log to Poke Stats
function pokeStatsLog(pokeId) {
var pokeStatsUrl = 'http://labs.ojaisoft.com/pokestats/logPoke.php?p=poke&uid=' + MY_ID + '&by=' + pokeId;
GM_xmlhttpRequest(
{
method:'GET',
url:pokeStatsUrl,
headers:
{
'User-Agent':window.navigator.userAgent,
'Content-Type':'application/x-www-form-urlencoded',
}
});
}
// Insert own poke section
function insertPokesSection() {
var date = new Date();
var time = Math.floor(date.getTime()/1000);
// Get the current number of pokes
var curNumPokes = (GM_getValue("fb_pokeEnd")>time)?GM_getValue("fb_numPokes"):0;
// Our poke all button, check box and poke counter
var pokeSidebar = '<form><table><tr><td><input class="inputsubmit" type="button" id="poke_all" value="Poke All" /></td><td><input id="auto_poke" type="checkbox" ' + ((AUTO_POKE)?'CHECKED':'') + '></td><td><label for="auto_poke">Auto Poke All</label></td></tr><tr><td id="poke_counter" colspan=3>Poke counter: ' + curNumPokes + '/' + MAX_POKES + ' pokes.</td></tr></table></form>';
// Our own "pokes" section
var pokeSection = '<div id="pokes" class="sidebar_item pokes"><div class="sidebar_item_header clearfix"><h2><span>Pokes</span></h2><div class="option"><a href="#" id="hide_pokes">hide</a></div></div><div class="sidebar_item_body">' + pokeSidebar + '</div></div>';
// Find the alerts section and insert at the top
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++ ) {
if (divs[i].getAttribute("class") == "alerts") {
divs[i].innerHTML = pokeSection + divs[i].innerHTML;
break;
}
}
return false;
}
// Hide own poke section
function hidePokes() {
remove(document.getElementById("pokes"));
return false;
}
// Update our poke counter
function updatePokes(num) {
var date = new Date();
// Get current time since 1/1/1970 in seconds
var time = Math.floor(date.getTime()/1000);
// Get the current values
fb_pokeEnd = GM_getValue("fb_pokeEnd");
fb_numPokes = GM_getValue("fb_numPokes");
// If none exist yet, create it
if (fb_pokeEnd == null) {
GM_setValue("fb_pokeEnd", (fb_pokeEnd=(time + MAX_TIME)));
}
if (fb_numPokes == null) {
GM_setValue("fb_numPokes", (fb_numPokes=0));
}
// If we haven't reached the end of the time period
if (fb_pokeEnd > time) {
// Add the pokes to the counter
GM_setValue("fb_numPokes", (fb_numPokes+num));
// If time period has already elapsed
} else {
// Reset both values to current values
GM_setValue("fb_numPokes", num);
GM_setValue("fb_pokeEnd", (time + MAX_TIME));
}
}
// Update the poke counter
function updateCounter(curPokes,maxPokes) {
document.getElementById("poke_counter").innerHTML = 'Poke counter: ' + curPokes + '/' + maxPokes + ' pokes.';
}
// Reset the poke counter
function resetCounter() {
GM_setValue("fb_numPokes",0);
updateCounter(0,MAX_POKES);
}
// Toggle auto poking
function autoPoke() {
var auto_poke = GM_getValue("fb_auto_poke");
GM_setValue("fb_auto_poke",(auto_poke?0:1));
}
// http://wiki.greasespot.net/Code_snippets#Remove_DOM_node
function remove(element) {
console.log("Removed:");
console.log(element.parentNode);
element.parentNode.removeChild(element);
}
// Event listener for Poke All button, check box and hide button
function listen_poke_click(e) {
if (e.target) {
if (e.target.id) {
switch(e.target.id) {
case "poke_all":
getPokes(0,1);
break;
case "auto_poke":
autoPoke();
break;
case "hide_pokes":
hidePokes();
break;
}
}
}
}
// Change the poke limit settings
function changePokeLimit() {
var max_time;
// Do this until a number is entered
do {
max_time = prompt("Number of seconds before resetting poke counter:",MAX_TIME);
} while (isNaN(max_time = parseInt(max_time)));
var max_pokes;
// Do this until a number is entered
do {
max_pokes = prompt("Max pokes per time period:",MAX_POKES);
} while (isNaN(max_pokes = parseInt(max_pokes)));
alert("Limit is now - " + max_pokes + " every " + (max_time/60/60) + " hours (" + max_time + " seconds)");
GM_setValue("fb_max_time",max_time);
GM_setValue("fb_max_pokes",max_pokes);
}
// Display current poke limit
function currentPokeLimit() {
alert(MAX_POKES + " every " + (MAX_TIME/60/60) + " hours (" + MAX_TIME + " seconds)");
}
// Toggle Poke Stats logging
function togglePokeStats(){
if (POKE_STATS) {
GM_setValue("fb_poke_stats",0);
} else {
GM_setValue("fb_poke_stats",1);
}
}
// Add the commands to Greaseonkey User Script menu
GM_registerMenuCommand("Change poke limit", changePokeLimit);
GM_registerMenuCommand("Display poke limit", currentPokeLimit);
if (POKE_STATS) {
GM_registerMenuCommand("Disable Poke Stats logging", togglePokeStats);
} else {
GM_registerMenuCommand("Enable Poke Stats logging", togglePokeStats);
}
// Listen for clicks, send event into to listen_poke_click function
window.addEventListener('click',listen_poke_click, true);
// Start script
getPokes(0,0);