There are 84 previous versions of this script.
Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)
// ==UserScript==
// @name Facebook Invites
// @namespace FacebookInvites
// @description Invites your friends to the app if they've already allowed the app access. Adds an bulk add form in message threads.
// @include http://*.facebook.com/*
// @include https://*.facebook.com/*
// @include http://forums.zynga.com/*
// @require http://sizzlemctwizzle.com/updater.php?id=43682
// ==/UserScript==
/*
window.friendsWithAppList = List of friends with this app.
window.friendsWithAppNotInvited = List of friends with this app we can invite.
window.friendsWithAppId = The app id where we retreived the list of friends from.
window.friendsInInviteDialog = friends in the invite dialog
*/
//var SUC_script_num = 43682; // Change this to the number given to the script by userscripts.org (check the address bar)
//try{function updateCheck(forced){if ((forced) || (parseInt(GM_getValue('SUC_last_update', '0')) + (86400000*7) <= (new Date().getTime()))){try{GM_xmlhttpRequest({method: 'GET',url: 'http://userscripts.org/scripts/source/'+SUC_script_num+'.meta.js?'+new Date().getTime(),headers: {'Cache-Control': 'no-cache'},onload: function(resp){var local_version, remote_version, rt, script_name;rt=resp.responseText;GM_setValue('SUC_last_update', new Date().getTime()+'');remote_version=parseInt(/@uso:version\s*(.*?)\s*$/m.exec(rt)[1]);local_version=parseInt(GM_getValue('SUC_current_version', '-1'));if(local_version!=-1){script_name = (/@name\s*(.*?)\s*$/m.exec(rt))[1];GM_setValue('SUC_target_script_name', script_name);if (remote_version > local_version){GM_setValue('SUC_current_version', remote_version);if(confirm('There is an update available for the Greasemonkey script "'+script_name+'."\nWould you like to go to the install page now?')){GM_openInTab('http://userscripts.org/scripts/show/'+SUC_script_num);}}else if (forced)alert('No update is available for "'+script_name+'."');}else GM_setValue('SUC_current_version', remote_version+'');}});}catch (err){if (forced)alert('An error occurred while checking for updates:\n'+err);}}}GM_registerMenuCommand(GM_getValue('SUC_target_script_name', '???') + ' - Manual Update Check', function(){updateCheck(true);});updateCheck(false);}catch(err){}
// Checkbox list: http://apps.facebook.com/dragonwars/recruit.php
// Picture list: http://apps.facebook.com/egghunt/invite.php
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }
var nHtml={
FindByAttr:function(obj,tag,attr,className) {
if(attr=="className") { attr="class"; }
var q=document.evaluate(".//"+tag+"[@"+attr+"='"+className+"']",obj,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
if(q && q.singleNodeValue) { return q.singleNodeValue; }
return null;
},
FindByClassName:function(obj,tag,className) {
return this.FindByAttr(obj,tag,"className",className);
},
FindByXPath:function(obj,xpath) {
try {
var q=document.evaluate(xpath,obj,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
} catch(e) {
GM_log('bad xpath:'+xpath);
}
if(q && q.singleNodeValue) { return q.singleNodeValue; }
return null;
},
VisitUrl:function(url) {
window.setTimeout(function() {
document.location.href=url;
},500+Math.floor(Math.random()*500));
},
ClickWin:function(win,obj,evtName) {
var evt = win.document.createEvent("MouseEvents");
evt.initMouseEvent(evtName, true, true, win,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
return !obj.dispatchEvent(evt);
},
Click:function(obj) {
return this.ClickWin(window,obj,'click');
},
ClickTimeout:function(obj,millisec) {
window.setTimeout(function() {
return nHtml.ClickWin(window,obj,'click');
},millisec+Math.floor(Math.random()*500));
},
ClickUp:function(obj) {
this.ClickWin(window,obj,'mousedown');
this.ClickWin(window,obj,'mouseup');
this.ClickWin(window,obj,'click');
},
GetText:function(obj,depth) {
var txt='';
if(depth==undefined) { depth=0; }
if(depth>40) { return; }
if(obj.textContent!=undefined) { return obj.textContent; }
for(var o=0; o<obj.childNodes.length; o++) {
var child=obj.childNodes[o];
txt+=this.GetText(child,depth+1);
}
return txt;
}
};
function DebugLog(mess) {
GM_log(mess);
}
FacebookInvites={
addAsFriendButtons:false,
addMeUpto:0,
addMeUptoMax:0, // how many users do we try to add as friends on this page. Only 1 when we're on profile page.
addMeDone:{},
waitForAddMe:null,
waitForAddMeStarted:null,
bulkAddMeTimeout:null,
messObj:null,
allAppsId:"0ALLAPPS",
bulkAddOptions:{},
scriptName:'Facebook Invites',
SetMessage:function(mess) {
if(!this.messObj) {
var content=document.getElementById('content');
if(!content) content=document.body;
if(content) {
var div=document.createElement('div');
div.style.paddingTop='48px';
div.innerHTML=mess;
content.insertBefore(div,content.childNodes[0]);
this.messObj=div;
} else {
GM_log('cannot find content div');
}
}
this.messObj.innerHTML=mess;
},
IsTooManySelected:function() {
var toomany=nHtml.FindByXPath(document,"//div[@class='toomany_selected']");
if(toomany && toomany.style.display!='none') {
GM_log('Too many friends selected');
return true;
}
return false;
},
InviteFriendsCheckBox:function(div,friendsHash,click) {
var inps=div.getElementsByTagName('input');
var friendsClicked=0;
var selected={};
var isSmallPictures=this.IsFriendsSmallPictures(div);
for(var i=0; i<inps.length; i++) {
var inp=inps[i];
var val=""+inp.value;
if(friendsHash!=null && !friendsHash[val]) {
continue;
}
if(selected[val]) { continue; }
var sel=true;
if(isSmallPictures) {
if(inp.parentNode.className.indexOf("selectedCheckable")>=0) {
sel=true;
} else { sel=false; }
} else {
if(inp.id!="ids[]") {
continue;
}
if(inp.parentNode.parentNode.className=="unselected_list") {
sel=false;
}
}
if(inp.parentNode.style.display=='none') { continue; }
if(click(sel,val)) {
selected[val]=1;
nHtml.Click(inp.parentNode);
friendsClicked++;
if(this.IsTooManySelected()) {
break;
}
}
}
return friendsClicked;
},
InviteFriendsPictures:function(div,friendsHash,click) {
var lis=div.getElementsByTagName('li');
var selected=0;
for(var l=0; l<lis.length; l++) {
var li=lis[l];
var as=li.getElementsByTagName('a');
if(as.length<1) { continue; }
var userid=""+li.getAttributeNode('userid').value;
if(friendsHash!=null && !friendsHash[userid]) {
continue;
}
if(click(li.className=='selected',userid)) {
nHtml.Click(as[0]);
selected++;
if(this.IsTooManySelected()) {
break;
}
}
}
return selected;
},
InviteFriendsClick:function(div,friendsHash,click) {
if(!this.IsFriendsDivPictures(div) || this.IsFriendsSmallPictures(div)) {
return this.InviteFriendsCheckBox(div,friendsHash,click);
}
return this.InviteFriendsPictures(div,friendsHash,click);
},
IsFriendsDivPictures:function(div) {
if(div.className.indexOf("condensed_multi_friend_selector")>=0) {
return false;
}
return true;
},
IsFriendsSmallPictures:function(div) {
if(div.className.indexOf("fbProfileBrowserListContainer")>=0) {
return true;
}
return false;
},
GetFriendsDiv:function() {
var friends2=nHtml.FindByClassName(document.body,"div","condensed_multi_friend_selector");
if(friends2) { return friends2; }
friends2=nHtml.FindByClassName(document.body,"div","fbProfileBrowserListContainer");
if(friends2) { return friends2; }
var friends=document.getElementById("friends");
return friends;
},
DoIFrame:function(url) {
var f=document.getElementById('FBInvitesFrame');
if(!f) {
f=document.createElement('iframe');
f.style.display='none';
f.id='FBInvitesFrame';
document.body.appendChild(f);
}
f.src=url;
return f;
},
previousStr:'this',
InviteFriends:function() {
if(document.getElementById('InviteFriendRefresh')) {
// we've already done this page.
return;
}
var friends=this.GetFriendsDiv();
if(!friends) {
return false;
}
var link=document.createElement('a');
link.href='javascript:;';
link.id='InviteFriendRefresh';
this.previousStr='this';
var appId=this.GetAppId();
var oldAppId=GM_getValue('appid','');
var linkMess=document.createElement('span');
linkMess.innerHTML='';
link.innerHTML="• Refresh your list of friends who are using this application.";
link.title="Go to the 'friends who are using this applications' page. This needs to be done before new friends will be selected here.";
if(!appId && !oldAppId) {
linkMess.innerHTML="Need to visit an application's invite page to collect a list of friends first!";
} else if(!appId) {
// we're in the facebook friends list or some other non-app thing.
link.innerHTML="";
this.previousStr='previous';
}
var friendsHash=this.GetFriendsWithApp();
var appFriendsHash=null;
if(appId && oldAppId) {
var lastSync=GM_getValue('FriendsWithAppSyncTime_'+appId,'');
if(lastSync!='') {
appFriendsHash=this.GetFriendsWithApp(appId);
friendsHash=appFriendsHash;
var lastSyncD=new Date();
lastSyncD.setTime(lastSync);
var alertStyle='';
var now=new Date().getTime();
if(lastSync<(now-86400*1000*3)) {
alertStyle="style='color: #f00'";
}
linkMess.innerHTML+=" <b "+alertStyle+">Friends list last refreshed on: "+lastSyncD.toString()+"</b><br />";
} else if(appId!=oldAppId) {
linkMess.innerHTML+=" <b>Warning! The list of friends are from another app.</b><br />";
this.previousStr='previous';
}
}
if(appFriendsHash==null && appId) {
// don't have anything in the memory for this app, first time user...
// this.VisitFriendsList();
// link.innerHTML="Important: "+link.innerHTML;
link.style.fontSize='15pt';
}
var css=document.createElement('style');
css.type='text/css';
css.innerHTML='#InviteFriendsDiv a { color: #008; } #InviteFriendsDiv a:hover { text-decoration: underline; }';
document.getElementsByTagName('head')[0].appendChild(css);
var managementDiv=document.createElement('div');
managementDiv.innerHTML="You can also grab the users from any page via the greasemonkey icon under 'user script commands'<br />";
if(appId) {
// we're in an app, not facebook. let's hide the friends management section.
managementDiv.style.display='none';
}
managementDiv.style.marginLeft='10px';
var managementLink=document.createElement('a');
managementLink.innerHTML='• Friends management';
managementLink.title='Open up the friends management area. More functions to handle friends ';
managementLink.addEventListener('click',function() {
managementDiv.style.display=managementDiv.style.display=='none'?'block':'none';
},false);
var linkDiv=document.createElement('div');
this.messObj=document.createElement("div");
this.messObj.style.fontSize='14pt';
linkDiv.id='InviteFriendsDiv';
linkDiv.appendChild(this.messObj);
linkDiv.appendChild(linkMess);
linkDiv.appendChild(link);
linkDiv.appendChild(document.createElement("br"));
linkDiv.appendChild(managementLink);
linkDiv.appendChild(document.createElement("br"));
linkDiv.appendChild(managementDiv);
linkDiv.style.border='2px solid #888';
linkDiv.style.padding='4px';
linkDiv.style.color='#444';
linkDiv.style.backgroundColor='#fff';
var clearLink=document.createElement('a');
clearLink.href='javascript:;';
clearLink.id='InviteFriendClear';
clearLink.innerHTML='Deselect';
var selectAllLink=document.createElement('a');
selectAllLink.innerHTML='Select';
var bull=document.createElement("font")
bull.innerHTML="• ";
linkDiv.appendChild(bull);
linkDiv.appendChild(selectAllLink);
linkDiv.appendChild(document.createTextNode(" / "));
linkDiv.appendChild(clearLink);
linkDiv.appendChild(document.createTextNode(" all friends."));
linkDiv.appendChild(document.createElement("br"));
var removeLink=document.createElement('a');
removeLink.innerHTML='Deselect';
var unionLink=document.createElement('a');
unionLink.innerHTML='Join';
unionLink.title='Only select friends using '+this.previousStr+' application and friends currently selected here.';
var appUidslink=document.createElement('a');
appUidslink.onclick='javascript:return false;';
appUidslink.innerHTML='Friends in game';
appUidslink.target='_blank';
var appNotInvitedUidslink=document.createElement('a');
appNotInvitedUidslink.onclick='javascript:return false;';
appNotInvitedUidslink.target='_blank';
appNotInvitedUidslink.innerHTML='In game and in invite box';
var addLink=document.createElement('a');
addLink.innerHTML='Select';
var bull=document.createElement("font");
bull.innerHTML="• ";
var bull2=document.createElement("font");
bull2.innerHTML="• ";
managementDiv.appendChild(bull2);
managementDiv.appendChild(document.createTextNode("Copy link to copy uids:"));
managementDiv.appendChild(appUidslink);
managementDiv.appendChild(document.createTextNode(" / "));
managementDiv.appendChild(appNotInvitedUidslink);
managementDiv.appendChild(document.createElement("br"));
managementDiv.appendChild(bull);
managementDiv.appendChild(addLink);
managementDiv.appendChild(document.createTextNode(" / "));
managementDiv.appendChild(removeLink);
managementDiv.appendChild(document.createTextNode(" / "));
managementDiv.appendChild(unionLink);
managementDiv.appendChild(document.createTextNode(' Friends from the current list.'));
var copyLink=document.createElement('a');
copyLink.innerHTML='• Use the selected friends below as the current list.';
managementDiv.appendChild(document.createElement("br"));
managementDiv.appendChild(copyLink);
var useBufferLink=null;
if(appFriendsHash!=null) {
useBufferLink=document.createElement('a');
useBufferLink.innerHTML="• Use the previous application's friends list for select/deselect/join.";
managementDiv.appendChild(document.createElement("br"));
managementDiv.appendChild(useBufferLink);
}
joinRecentLink=document.createElement('a');
joinRecentLink.innerHTML="• Only include friends who are also in the first page of 'recently added friends'.";
linkDiv.appendChild(joinRecentLink);
linkDiv.appendChild(document.createElement("br"));
var randomLink=document.createElement('a');
randomLink.href='javascript:;';
randomLink.innerHTML='• Add random friends who are using '+this.previousStr+' application.';
linkDiv.appendChild(randomLink);
var detachLink=document.createElement('a');
detachLink.innerHTML='• Move this block to the top';
detachLink.title="If you're having visibility problems";
linkDiv.appendChild(document.createElement("br"));
linkDiv.appendChild(detachLink);
var contentDiv=document.getElementById('content');
if(!contentDiv) contentDiv=document.body;
var randomDialog=document.createElement('div');
randomDialog.innerHTML="<br /><br /><form><input type='checkbox' id='AddRandomFriendsAnyFriends' />Add any friends, not just people who're using the app.<br />Friends to add: <input id='AddRandomFriendsNum' size='4' value='1' /><input id='AddRandomFriendsButton' type='button' value='Add Random Friends' /></form>";
randomDialog.style.border="2px solid #888";
randomDialog.style.padding='4px';
randomDialog.style.position='fixed';
randomDialog.style.backgroundColor='#fff';
randomDialog.style.color='#000';
randomDialog.style.left=0;
randomDialog.style.top=0;
randomDialog.style.display="none";
contentDiv.appendChild(randomDialog);
var randomButton=document.getElementById('AddRandomFriendsButton');
var inviteToggle=this.GetDivToggle(linkDiv,'ShowInviteFriends',true);
inviteToggle.innerHTML='<b>'+this.scriptName+': Show invite friends block</b>';
inviteToggle.style.backgroundColor='#fff';
inviteToggle.style.color='#008';
inviteToggle.style.padding='4px';
// if(!this.IsFriendsDivPictures(friends)) {
// friends.parentNode.insertBefore(linkDiv,friends);
// } else {
friends.parentNode.insertBefore(inviteToggle,friends);
friends.parentNode.insertBefore(linkDiv,friends);
// }
link.addEventListener('click',function() { FacebookInvites.VisitFriendsList(); },false);
copyLink.addEventListener('click',function() {
var friendsList=[];
friendsHash={};
FacebookInvites.InviteFriendsClick(friends,null,function(c,id) {
if(c) {
friendsHash[id]=1;
friendsList.push(id);
}
return false;
});
var friendsListStr=friendsList.join(',');
GM_setValue('FriendsWithApp',friendsListStr);
FacebookInvites.SetMessage("The list we're using now has "+friendsList.length+" friends.");
},false);
selectAllLink.addEventListener('click',function() {
FacebookInvites.InviteFriendsClick(friends,null,function(c) { return c?false:true; });
},false);
clearLink.addEventListener('click',function() {
FacebookInvites.InviteFriendsClick(friends,null,function(c) { return c?true:false; });
},false);
removeLink.addEventListener('click',function() {
FacebookInvites.InviteFriendsClick(friends,friendsHash,function(c) { return c?true:false; });
},false);
unionLink.addEventListener('click',function() {
FacebookInvites.InviteFriendsClick(friends,null,function(c,id) {
if(c) return friendsHash[id]?false:true;
return false;
});
},false);
if(useBufferLink!=null) {
useBufferLink.addEventListener('click',function() {
friendsHash=FacebookInvites.GetFriendsWithApp();
FacebookInvites.CalcInvitedHash(friendsHash);
},false);
}
joinRecentLink.addEventListener('click',function() {
// visit recent added friends in iframe,
var iframe=FacebookInvites.DoIFrame('http://www.facebook.com/friends/?added&ref=tn');
GM_log('Waiting for recent friends to load');
unsafeWindow.joinRecentLoadedLink=function() {
GM_log('Recent friends loaded');
var recentFriends=FacebookInvites.GetFriendsFromPage(iframe.contentDocument.body);
var ids=[];
for(var id in friendsHash) { ids.push(id); }
var t=0;
ids.forEach(function(id) {
if(!recentFriends[id]) {
friendsHash[id]=undefined;
} else {
t++;
}
});
FacebookInvites.InviteFriendsClick(friends,null,function(c) {
if(c) {
return true;
}
});
FacebookInvites.InviteFriendsClick(friends,null,function(c,id) {
var r=friendsHash[id]?true:false;
if(c) { r=r?false:true; GM_log('huh? something is still selected?'); }
return r;
});
FacebookInvites.SetMessage("The list we're using now has "+t+" friends.");
iframe.src='about:blank';
document.body.removeChild(joinRecentLoadedLink);
};
},false);
addLink.addEventListener('click',function() {
FacebookInvites.InviteFriendsClick(friends,friendsHash,function(c) { return c?false:true; });
},false);
randomLink.addEventListener('click',function() {
randomDialog.style.display='block';
},false);
detachLink.addEventListener('click',function() {
FacebookInvites.DetachDiv();
},false);
randomButton.addEventListener('click',function() {
randomDialog.style.display='none';
var randomNum=document.getElementById('AddRandomFriendsNum');
var wanted=parseInt(randomNum.value);
var friendsHashRandom={};
var added=0;
var anyFriends=document.getElementById('AddRandomFriendsAnyFriends').checked;
var friendsInDialog={}; // friends that are not selected in the dialog
FacebookInvites.InviteFriendsClick(friends,null,function(c,id) { if(!c) { friendsInDialog[id]=1; } return false; } );
var friendsArr=[];
var hashToUse=friendsHash;
if(anyFriends) {
hashToUse=friendsInDialog;
}
for(var f in hashToUse) {
friendsArr.push([f,Math.random()]);
}
friendsArr.sort(function(a,b) { return a[1]-b[1]; });
for(var fUpto=0; fUpto<friendsArr.length; fUpto++)
{
if(added>=wanted) {
break;
}
var f=friendsArr[fUpto][0];
if(!friendsInDialog[f]) { continue; }
friendsHashRandom[f]=""+friendsHash[f];
added++;
}
FacebookInvites.InviteFriendsClick(friends,friendsHashRandom,function(c,id) { return c?false:true; });
},false);
window.friendsWithAppId=oldAppId;
this.CalcInvitedHash(friendsHash);
this.InviteFriendsClick(friends,friendsHash,function(c,id) {
var r=c?false:true;
/* we don't have an appid anymore in iframed invite dialogs.
if(!appId) {
// can't find app id, we're in facebook, lets' not auto add all the friends.
return false;
}
*/
return r;
});
appUidslink.href='about:blank#'+this.MakeCsvFromHashNames(friendsHash);
appNotInvitedUidslink.href='about:blank#'+this.MakeCsvFromHashNames(window.friendsWithAppNotInvited);
return true;
},
MakeCsvFromHashNames:function(friendsHash) {
var uidsStr='';
for(var n in friendsHash) {
if(uidsStr.length>0) uidsStr+=",";
uidsStr+=n;
}
return uidsStr;
},
GetInviteFriendsDiv:function() {
return document.getElementById('InviteFriendsDiv');
},
DetachDiv:function() {
var linkDiv=this.GetInviteFriendsDiv();
if(!linkDiv) { return; }
linkDiv.style.position='fixed';
linkDiv.style.left=0;
linkDiv.style.top='24px';
},
CalcInvitedHash:function(friendsHash) {
var friendsDiv=this.GetFriendsDiv();
var totalFriendsWithApp=0;
for(var f in friendsHash) {
totalFriendsWithApp++;
}
var invited=0;
var invitedHash={};
var friendsInInviteDialog={};
this.InviteFriendsClick(friendsDiv,null,function(c,id) {
if(friendsHash[id]) {
var r=c?false:true;
if(r) invitedHash[id]=1;
if(r) { invited++; }
}
friendsInInviteDialog[id]=1;
return false;
});
window.friendsWithAppList=friendsHash;
window.friendsWithAppNotInvited=invitedHash;
window.friendsInInviteDialog=friendsInInviteDialog;
this.SetMessage(" (Friends with "+this.previousStr+" application that you can invite:"+invited+" out of "+totalFriendsWithApp+")");
},
idRe:new RegExp('[^a-z]id=([0-9]+)','i'),
GetAppId:function() {
var builtBy=nHtml.FindByClassName(document.body,"span","page_built_by");
if(builtBy) {
var as=builtBy.getElementsByTagName("a");
if(as.length>0) {
var m=this.idRe.exec(as[0].href);
if(m && m.length>0) {
var id=m[1];
return id;
}
}
}
var appContentDiv=nHtml.FindByXPath(document.body,"//div[contains(@id,'app_content_')]");
if(appContentDiv) {
var m=/^app_content_([0-9]+)$/.exec(appContentDiv.id);
if(m && m.length>1) {
return m[1];
}
}
var api_key_input=nHtml.FindByXPath(document.body,"//input[@name='api_key' and @type='hidden']");
// the new small pictures invite screen.
if(api_key_input) return api_key_input.value;
return null;
},
VisitFriendsList:function() {
var appid=this.GetAppId();
GM_setValue('appid',appid);
GM_setValue('FriendsWithApp','');
GM_setValue('InviteUrl',document.location.href);
// document.location.href="http://www.facebook.com/social_graph.php?node_id="+appid+"&class=AppUserManager&edge_type=mutual&start=0"; //change suggested by Lox Myth - see http://userscripts.org
http://www.facebook.com/browse/?type=friends_using_app&app_id=268652830776/topics/34630#posts-166598
var url="http://www.facebook.com/browse/?type=friends_using_app&app_id="+appid;
GM_log('Going to get friends with apps list:'+url);
location.href=url;
return true;
},
GetFriendsWithApp:function(appId) {
var friends=GM_getValue('FriendsWithApp'+(appId!=undefined?("_"+appId):''),'').split(/,/);
var friendsHash={};
for(var f=0; f<friends.length; f++) {
var n=friends[f];
if(n=="") { continue; }
friendsHash[n]=1;
}
return friendsHash;
},
AddFriendsWithApp:function() {
var inviteUrl=GM_getValue('InviteUrl','');
if(inviteUrl=='') { return; }
var content=document.getElementById('content');
if(!content) { return; }
var as=content.getElementsByTagName('a');
var nextUrl=null;
var friends=this.GetFriendsWithApp();
this.ClickClose();
// var ss=document.evaluate("//a[contains(@href,'/social_graph.php') and contains(@title,'Next')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null); //change suggested by Lox Myth - see http://userscripts.org/topics/34630#posts-166598
//it doesn't work with different localization
// suggested by: jcppkkk
// var ss=document.evaluate("//span[@class!='UIPager_ButtonWrapper UIPager_ButtonDisabled']/a[@class='UIPager_Button UIPager_ButtonForward']",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var ss=document.evaluate("//a[contains(@class,'uiMorePagerPrimary') and contains(@href,'friends_using_app')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
if(ss.snapshotLength>0) {
var lastpager=ss.snapshotItem(ss.snapshotLength-1);
// var numberRe=/^[\\s0-9]+$/;
// if(!numberRe.exec(lastpager.innerHTML)) {
// we still have a "next" button.
GM_log('Next page found:'+lastpager.href);
nextUrl=lastpager.href;
// }
} else {
GM_log('No next page found');
}
var friendsAdded=0;
var friendIds=this.GetFriendsFromPage(content);
for(var id in friendIds) {
if(friends[id]) { continue; }
friends[""+id]=1;
friendsAdded++;
}
/*
for(var aUpto=0; aUpto<as.length; aUpto++) {
var a=as[aUpto];
// if(a.href.indexOf("/friends/")<0) { //change suggested by Austin Pereira - http://userscripts.org/topics/34741#posts-167127
var id=this.GetFriendIdFromLink(a,this.profileRe);
if(false) {
if(a.parentNode.className.indexOf('fsl fwb fcb')<0) {
continue;
}
var m=this.idRe.exec(a.href);
if(m && m.length>0) {
id=m[1];
} else { continue; }
}
if(friends[id]) { continue; }
var name=a.innerHTML;
friends[""+id]=1;
friendsAdded++;
}
*/
var friendsListStr=this.SaveFriendsFromHash(friends);
var appid=GM_getValue('appid',0);
GM_setValue('FriendsWithApp_'+appid,friendsListStr);
GM_setValue('FriendsWithAppSyncTime_'+appid,(new Date()).getTime().toString() );
if(nextUrl!=null) {
nHtml.VisitUrl(nextUrl);
} else {
// cannot find "next" button, lets go back to app.
GM_setValue('InviteUrl','');
GM_log('Going back to previous url in app:'+inviteUrl);
nHtml.VisitUrl(inviteUrl);
}
return friendsAdded>0?true:false;
},
SaveFriendsFromHash:function(friends) {
var friendsList=[];
for(var n in friends) {
if(n=="") {continue; }
friendsList.push(n);
}
var friendsListStr=friendsList.join(',');
GM_setValue('FriendsWithApp',friendsListStr);
return friendsListStr;
},
StartBulkAddMe:function() {
this.addMeUpto=0;
this.RestartAddMe();
},
SetupBulkAddMeProfileButton:function() {
var button=document.getElementById('BulkAddMeProfileButton');
var autoBulkAdd=this.GetAutoBulkAdd();
button.style.color=autoBulkAdd?'#c00':'';
button.value=(autoBulkAdd?"Disable ":"Enable")+" auto add on profile Page";
},
AddMeLink:function(lp) {
if(document.getElementById("AddMeLinkDiv")) { return; }
if(!lp) lp=document.getElementById("all_threads");
// if(!lp) { lp=document.getElementById("see_all_posts"); }
if(!lp) {
return false;
}
var div=document.createElement('div');
div.id='AddMeLinkDiv';
var bulkAddToggle=this.GetDivToggle(div,'ShowBulkAdd',true);
bulkAddToggle.innerHTML='<b>'+this.scriptName+': Show bulk add friends block</b>';
var autoBulkAdd=FacebookInvites.GetAutoBulkAdd();
div.innerHTML=
(this.GetAutoBulkAdd() && window.name!=""?'<a href="javascript:window.parent.CloseIFrameByName(window.name)">Close frame</a><br />':'')+
"<form id='BulkAddMe'>Comment:<textarea id='bulkAddComment' name='comment' cols='40' rows='4' /></textarea><br />"+
"Friend List to add confirmed friends to:<input id='bulkAddFriendList' />(exactly with capital letters)<br />"+
"<input type='checkbox' id='BulkAddMeButtonPages' />Bulk add everyone here and the previous pages of this discussion board<br />"+
"<input id='bulkAddDelay' value='10' size='4' />seconds between adds<br />"+
"<input type='checkbox' id='popupToAddFriend' checked title='Popup profile to add friend' />Add user via the users' profile instead. (This makes sure that we can add this user first before trying to add.)<br />"+
"<a id='BulkAddOptionsToggle' href='javascript:;'>Options</a><br />"+
"<input type='button' id='BulkAddMeButton' value='Bulk Add Everyone here' /><br />"+
"<input type='button' id='BulkAddMeProfileButton' value='' title='Useful for pages that do not have the add friend feature or is outside of facebook.' />(Once enabled, you can click with the middle mouse button on any profile link to add them)<br />"+
"</form>";
div.style.border='1px solid #000';
div.style.padding='10px';
lp.parentNode.insertBefore(bulkAddToggle,lp);
lp.parentNode.insertBefore(div,lp);
var divOptions=document.createElement('div');
divOptions.id='AddMeOptionsDiv';
divOptions.innerHTML=
"<input type='checkbox' id='BulkAddNewsFeed' />Publish to news feed<br />"+
"<input type='checkbox' id='testBulkAddMeButton' title='Test Only, do not add, just go through the process.' />Test only<br />"+
"<input type='checkbox' id='BulkAddIgnoreErrors' />Ignore errors, continue even when facebook returns an errors<br />";
divOptions.style.display='none';
var toggle=document.getElementById('BulkAddOptionsToggle');
toggle.parentNode.insertBefore(divOptions,toggle.nextSibling);
this.SetupBulkAddMeProfileButton();
toggle.addEventListener('click',function() {
divOptions.style.display=divOptions.style.display=='none'?'block':'none';
},false);
var t=this;
var bulkAddMeButton=document.getElementById('BulkAddMeButton');
bulkAddMeButton.addEventListener('click',function() {
var addAsFriend=t.FindNthAddAsFriends();
if(addAsFriend) {
document.getElementById('popupToAddFriend').checked=false;
t.addAsFriendButtons=addAsFriend.snapshotLength;
} else { t.addAsFriendButtons=0; }
t.StartBulkAddMe();
},false);
var bulkAddMeProfile=document.getElementById('BulkAddMeProfileButton');
bulkAddMeProfile.addEventListener('click',function() {
GM_setValue('autoBulkAdd_RemoveWhenFinished',false);
//this.autoBulkAdd_RemoveWhenFinished=false;
t.SetAutoBulkAdd(t.GetAutoBulkAdd()?false:true);
t.SetupBulkAddMeProfileButton();
},false);
return true;
},
AddMeLinkAnyPage:function() {
if(document.getElementById("AddMeLinkDiv")) { return; }
var content=document.getElementById('content');
if(!content) content=document.body;
var p=document.createElement('p');
p.innerHTML="<br /><br />";
content.insertBefore(p,content.childNodes[0]);
return FacebookInvites.AddMeLink(content.childNodes[1]);
},
AddAsFriendLinks:function() {
var pop_content=document.getElementById('pop_content');
if(!pop_content) return;
var list=nHtml.FindByXPath(pop_content,".//div[contains(@id,'object_browser_content_area')]");
if(!list) return;
this.AddMeLinkAnyPage();
},
RestartAddMe:function() {
if(this.bulkAddMeTimeout!=null) {
window.clearTimeout(this.bulkAddMeTimeout);
this.bulkAddMeTimeout=null;
}
this.SetWaitForAddMe(null);
this.addMeDone={};
var o={};
o.friendList=document.getElementById('bulkAddFriendList').value.trim();
o.comment=document.getElementById('bulkAddComment').value;
o.delay=document.getElementById('bulkAddDelay').value;
o.testAddMe=document.getElementById('testBulkAddMeButton').checked;
o.ignoreErrors=document.getElementById('BulkAddIgnoreErrors').checked;
o.doPrevPages=document.getElementById('BulkAddMeButtonPages').checked;
o.newsFeed=document.getElementById('BulkAddNewsFeed').checked;
if(this.IsPopupToAddFriend()) {
//this.autoBulkAdd_RemoveWhenFinished=true;
GM_setValue('autoBulkAdd_RemoveWhenFinished',true);
FacebookInvites.SetAutoBulkAdd(true);
}
this.bulkAddOptions=o;
this.BulkAddMe(new Date().getTime());
},
IsPopupToAddFriend:function() {
var p=document.getElementById('popupToAddFriend');
if(p && p.checked) { return true; }
return false;
},
HasAddFriendDialog:function(a) {
var addFriendDialog=false;
if(a.href && a.href.indexOf('profile')>=0) {
addFriendDialog=true;
}
/*
var oncl=a.getAttribute('onclick');
if(oncl && oncl.indexOf('show_addfriend_dialog')>=0) {
addFriendDialog=true;
}
*/
return addFriendDialog;
},
FindNthAddAsFriends:function(nth) {
var popDialogss=document.evaluate(".//div[contains(@id,'pop_content')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for(var s=0; s<popDialogss.snapshotLength; s++) {
var pop_content=popDialogss.snapshotItem(s);
var ss=document.evaluate("//a[contains(@class,'UIActionButton')]",pop_content,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
return ss;
}
return null;
},
FindNthAddAsFriend:function(nth) {
var ss=this.FindNthAddAsFriends();
if(ss && nth<ss.snapshotLength) {
return ss.snapshotItem(nth);
}
return null;
},
FindNthPost:function(nth) {
var content=document.getElementById('content');
if(location.href.indexOf('.facebook.com')<0) {
content=document.body;
}
if(!content) return;
var as=content.getElementsByTagName('a');
var upto=0;
for(var aUpto=0; aUpto<as.length; aUpto++) {
var a=as[aUpto];
var addFriendDialog=this.HasAddFriendDialog(a);
if(!addFriendDialog && a.href.indexOf('k=')<0) {
// this person is already our friend.
continue;
}
// author_post: used in discussions
// profile_link: used in reviews
if(!addFriendDialog && a.className!="author_post" && a.className!="profile_link") {
continue;
}
if(a.parentNode.className.indexOf("fb_menu")>=0 || a.innerHTML.indexOf('<img')>=0) {
continue;
}
var pn=a;
var presence=false;
while(pn && pn.tagName!="BODY") {
if(pn.id=="presence") {
presence=true;
}
pn=pn.parentNode;
}
if(presence) { continue; }
if(nth==upto++) { return a; }
}
return null;
},
ClickFriendListDropDown:function(div) {
GM_log('ClickFriendListDropDown');
//var friendAdd=nHtml.FindByAttr(div,'span','class','FriendAddingTool_Menu');
var friendAdd=nHtml.FindByXPath(div,".//a[contains(@class,'uiSelectorButton')]");
if(friendAdd) {
nHtml.ClickUp(friendAdd);
/*
var friendAddDropDown=nHtml.FindByAttr(friendAdd,'span','class','UIActionMenu_Text');
// show the drop down for friends' lists
if(friendAddDropDown) {
nHtml.ClickUp(friendAddDropDown);
} else {
GM_log('cannot find friend list drop down');
}
*/
} else {
GM_log('cannot find the friends list drop down');
}
},
GetFriendListDropDown:function(div) {
if(!div) { GM_log('GetFriendListDropDown: no div'); }
//return nHtml.FindByAttr(div,'div','class','FriendAddingTool_InnerMenu');
var dropDown=nHtml.FindByXPath(div,".//a[contains(@class,'uiSelectorButton') and contains(@class,'selected')]");
if(dropDown) {
dropDown=dropDown.parentNode;
}
return dropDown;
},
SelectFriendListDropDown:function(friendAddSelect,friendList) {
GM_log('SelectFriendListDropDown');
if(!friendAddSelect) { GM_log('Bad!, no friendAddSelect'); }
var friendListItem=nHtml.FindByXPath(friendAddSelect,".//li[string()='"+friendList+"']");
if(friendListItem) {
nHtml.ClickUp(friendListItem);
GM_log('click friend list item:'+friendListItem.innerHTML);
} else {
GM_log('Cannot find friend List item:'+friendList);
}
},
SkipButton:function() {
// skip reported suggest a friend dialogs from facebook.
var skip=document.getElementById('skip');
if(skip && skip.tagName=="INPUT") {
GM_log('Clicking skip button');
nHtml.Click(skip);
return true;
}
return false;
},
SetWaitForAddMe:function(v) {
this.waitForAddMe=v;
this.waitForAddMeStarted=(new Date()).getTime();
},
CloseIFrameOnCompletion:function() {
if(window.name=="" || !unsafeWindow.parent) return;
var t=this;
try {
window.setTimeout(function() {
t.FindCaptcha();
if(!t.hasCaptcha) {
if(unsafeWindow.parent && unsafeWindow.parent.CloseIFrameByName) {
GM_log('closing iframe:'+window.name);
unsafeWindow.parent.CloseIFrameByName(window.name);
}
} else {
GM_log('Has captcha do not close iframe:'+window.location.href);
}
t.CloseIFrameOnCompletion();
},5000);
} catch(e) {
GM_log('close iframe problem:'+e);
}
},
FindCaptcha:function() {
var captcha=document.getElementById('captcha_session');
this.hasCaptcha=captcha?true:false;
return captcha;
},
hasCaptcha:false,
BulkAddMe:function(startTime) {
var waitMillis=250;
var error=document.getElementById('error');
if(error && !this.bulkAddOptions.ignoreErrors) {
var visible=true;
while(error.tagName!="BODY") {
if(error.style.display=="none") {
visible=false;
break;
}
error=error.parentNode;
}
if(visible) {
GM_log('Error found, bulk add aborted');
//if(GM_getValue('autoBulkAdd_RemoveWhenFinished',false))
if(this.autoBulkAdd_RemoveWhenFinished && !this.profilePageAdd)
this.SetAutoBulkAdd(false);
return;
}
}
this.ClickClose();
// DebugLog(this.waitForAddMe+","+this.addMeUpto);
var captcha=this.FindCaptcha();
var cp=captcha;
while(cp && cp.tagName!="BODY") {
if(cp.tagName=="FORM") {
if(cp.action && cp.action.indexOf('edittopic')>=0) {
// ignore captcha for making forum posts.
captcha=undefined;
}
break;
}
cp=cp.parentNode;
}
var popDialogss=document.evaluate(".//div[contains(@class,'pop_dialog')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
//var popDialog=document.getElementById("pop_content");
var popDialog=null;
for(var popss=0; popss<popDialogss.snapshotLength; popss++) {
var pd=popDialogss.snapshotItem(popss);
var inps=pd.getElementsByTagName('INPUT');
if(!inps || inps.length==0) { continue; }
// var friendAddingTool=nHtml.FindByXPath(pd,".//div[contains(@class,'FriendAddingTool')]");
// if(!friendAddingTool) continue;
popDialog=pd;
break;
}
if(this.SkipButton()) {
// LoveYou43v3r reported that it got stuck in some skip dialogs.
waitMillis=10000;
} else if(captcha && popDialog) {
// yuck captcha, wait for the user to do something.
GM_log('found captcha, wait for user input');
waitMillis=2000;
} else if(this.waitForAddMe=="add") {
if(popDialog) {
var a=nHtml.FindByXPath(popDialog,".//a[contains(@href,'/addfriend.php')]");
if(!a) {
// maybe we've already added this friend.
var close=nHtml.FindByAttr(popDialog,"input","name","close");
if(close) {
this.waitForAddMe=null;
GM_log('Click close on error/already added dialog');
nHtml.Click(close);
} else {
GM_log('waiting for add friend popup');
}
} else {
GM_log('Click addfriend');
nHtml.Click(a);
this.SetWaitForAddMe("message");
}
}
} else if(this.waitForAddMe=="message") {
var add=null;
if(popDialog) {
add=nHtml.FindByAttr(popDialog,"input","name",'connect');
var ok=nHtml.FindByAttr(popDialog,"input","name",'ok');
var ss=document.evaluate(".//input[@type='button']",popDialog,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
if(ss.snapshotLength==1 && ok) {
// maybe the you are already connected message, just click ok
GM_log('Click ok button');
nHtml.Click(ok);
}
}
if(popDialog && add) {
var friendAddSelect=this.GetFriendListDropDown(popDialog);
var friendList=this.bulkAddOptions.friendList;
if(!friendAddSelect && friendList.length>0) {
this.ClickFriendListDropDown(document.body);
} else {
if(friendList.length>0) {
this.SelectFriendListDropDown(friendAddSelect,friendList);
}
var newsFeed=nHtml.FindByXPath(popDialog,".//input[contains(@id,'news_feed_')]");
if(newsFeed) newsFeed.checked=this.bulkAddOptions.newsFeed;
var showComment=nHtml.FindByXPath(popDialog,".//a[contains(@onclick,'showMessage')]");
if(showComment) {
GM_log('Click show comment link');
nHtml.Click(showComment);
}
var tas=popDialog.getElementsByTagName('textarea');
if(tas.length>0) {
tas[0].value=this.bulkAddOptions.comment;
} else {
GM_log('Could not find message textarea');
}
var messLink=nHtml.FindByXPath(popDialog,".//a[contains(@onclick,'addMsgBox')]");
if(messLink) {
GM_log('Click show message box link');
nHtml.Click(messLink);
}
if(this.bulkAddOptions.testAddMe) {
add=nHtml.FindByAttr(popDialog,"input","name","cancel");
}
if(add) {
var delay=this.bulkAddOptions.delay;
this.SetWaitForAddMe(null);
// this means that it goes into the else loop after clicking on connect which means that it ignores the "already connected" error
// therefore i've added the code to click on already connected in the else part of the if statement
waitMillis=1000*delay;
var t=this;
window.setTimeout(function() {
GM_log('Click add friend!');
nHtml.Click(add);
if(t.GetAutoBulkAdd()) {
t.CloseIFrameOnCompletion();
}
},this.bulkAddOptions.testAddMe?1500:0);
}
}
}
if(this.waitForAddMe=="message" && (this.waitForAddMeStarted+15000)< ((new Date()).getTime()) ) {
var b1=document.getElementById('dialog_button1');
var b2=document.getElementById('dialog_button2');
if(b1 && !b2) {
GM_log('We are already friends with this person');
nHtml.Click(b1);
} else {
// 15 secs is up, still no dialog found.
GM_log('Skipping this user cause no add friend dialog is showing up.'+window.location.href);
}
this.SetWaitForAddMe(null);
}
} else {
while(1) {
if(this.addMeUptoMax>0 && this.addMeUpto>=this.addMeUptoMax) {
GM_log('FinishedBulkAddMe, max added:'+this.addMeUptoMax);
return;
}
var a=null;
if(this.addAsFriendButtons) {
a=this.FindNthAddAsFriend(this.addMeUpto);
// sometimes the list of users dialog disappears inbetween adding a friend.
if(this.addMeUpto<this.addAsFriendButtons) {
var addAsFriends=this.FindNthAddAsFriends();
if(addAsFriends) {
this.addAsFriendButtons=addAsFriends.snapshotLength;
} else if(!a) {
break;
}
}
} else {
a=this.FindNthPost(this.addMeUpto);
}
this.addMeUpto++
if(a==null && !this.profilePageAdd) {
if(!this.BulkAddMePrevPage()) {
if(GM_getValue('autoBulkAdd_RemoveWhenFinished',false))
//if(autoBulkAdd_RemoveWhenFinished)
this.SetAutoBulkAdd(false);
GM_log('FinishedBulkAddMe');
return;
}
this.addMeUpto=0;
waitMillis=12000;
break;
}
//error checking for already connected dialog - added by VX
var add=null;
if(popDialog) {
add=nHtml.FindByAttr(popDialog,"input","name",'connect');
var ok=nHtml.FindByAttr(popDialog,"input","name",'ok');
var ss=document.evaluate(".//input",popDialog,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
if(ss.snapshotLength==1 && ok) {
// maybe the you are already connected message, just click ok
GM_log('Click ok button');
nHtml.Click(ok);
/*
//click cancel on old dialog
popDialog=document.getElementById("pop_content");
if(popDialog) {
var cancel=nHtml.FindByAttr(popDialog,"input","name","cancel");
GM_log('Cancel clicked');
nHtml.Click(cancel);
}
*/
}
}
// finished edit by vx
// var hasAddFriendDialog=this.HasAddFriendDialog(a);
// var ref=hasAddFriendDialog?a.getAttribute('onclick'):a.href;
if(this.addAsFriendButtons) {
// We have some add as friend buttons
if(this.profilePageAdd) {
var content=document.getElementById('content');
if(content)
//a=nHtml.FindByXPath(content,".//a[contains(@href,'/addfriend.php')]");
a=nHtml.FindByXPath(content,".//a[contains(@href,'/addfriend.php')]");
}
var title=nHtml.FindByXPath(a.parentNode.parentNode.parentNode,".//a[contains(@class,'UIObjectListing_Title')]");
if(!title) continue;
var ref=title.href;
if(this.addMeDone[ref]) { continue; }
this.addMeDone[ref]=1;
nHtml.Click(a);
waitMillis=2000;
this.SetWaitForAddMe("message");
var t=this;
window.setTimeout(function() {
t.ClickClose();
},500);
} else {
var ref=a.href;
var idm=this.idRe.exec(a.href);
if(!idm) { continue; }
if(this.addMeDone[ref]) { continue; }
this.addMeDone[ref]=1;
this.ShowAddFriendDialog(idm[1],this.IsPopupToAddFriend());
if(!this.profilePageAdd && this.IsPopupToAddFriend()) {
waitMillis=10000;
this.SetWaitForAddMe(null);
} else {
waitMillis=100;
this.SetWaitForAddMe("message");
}
}
this.waitForAddMeStarted=(new Date()).getTime();
/*
nHtml.Click(a);
if(hasAddFriendDialog) {
this.waitForAddMe="message";
} else {
this.waitForAddMe="add";
}
*/
break;
}
}
if(this.bulkAddOptions.testAddMe && waitMillis<2000) { waitMillis=2000; }
this.bulkAddMeTimeout=window.setTimeout(function() {
FacebookInvites.BulkAddMe(startTime);
},waitMillis);
},
profileNameUpto:1,
OpenInFrame:function(url) {
if(location.href.indexOf('facebook.com')<0) {
GM_openInTab(url);
return;
}
var f=document.createElement('iframe');
f.width='100%';
f.height=window.innerHeight*0.8;
var name='ProfileIFrame'+this.profileNameUpto;
f.id=name;
f.name=name;
f.src=url;
document.body.insertBefore(f,document.body.childNodes[0]);
if(this.profileNameUpto==1) {
var script=document.createElement('script');
script.innerHTML='function '+
'CloseIFrameByName(name) { window.setTimeout(function() {'+
'var f=document.getElementById(name); if(f) { f.parentNode.removeChild(f); } '+
'},100);'+
'}';
document.body.appendChild(script);
}
this.profileNameUpto++;
},
ShowAddFriendDialog:function(uid,popupToAddFriend) {
// var addFriendClick=nHtml.FindByXPath(document,"//a[contains(@onclick,'ConnectDialog')]");
if(popupToAddFriend && !this.profilePageAdd) {
GM_log('Lets go to the profile page:'+uid);
this.OpenInFrame('http://www.facebook.com/profile.php?id='+uid);
/*
this.SetMessage('Facebook has not included the javascript to add friends from this page, have to open the profile page in a new tab.'+
"Enable auto add on the profile page if you have not done it.");
*/
} else {
GM_log('showfriend:'+uid);
/* Disabled: 18/feb/2010
var addFriendClick=nHtml.FindByXPath(document,"//a[contains(@href,'rel_dialog=1') and contains(@href,'connect.php')]");
nHtml.Click(addFriendClick);
*/
var a=document.createElement('script');
// 29/nov/2009
a.innerHTML="Dialog.bootstrap('http://www.facebook.com/ajax/profile/connect.php?profile_id="+
uid+"&rel_dialog=1&src=top_bar&ondone_reload=0',null,false);";
// a.innerHTML='new ConnectDialog("'+uid+'", "friend_other", null, this, 0, "", -1.000000, "", "").show();';
// a.innerHTML='show_addfriend_dialog("'+uid+'", this, undefined, undefined, undefined, undefined, undefined, "profile_others");';
var t=this;
window.setTimeout(function() {
document.body.appendChild(a);
},5000);
}
},
BulkAddMePrevPage:function() {
if(!this.bulkAddOptions.doPrevPages) {
return false;
}
var ss=document.evaluate("//a[contains(@onclick,'start')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var numberRe=/^[\\s0-9]+$/;
var onclickRe=new RegExp("start[\"\\s]*:\\s*[\-0-9]+");
var foundUpto=0;
var firstPagerLink=null;
for(var s=ss.snapshotLength-1; s>=0; s--) {
var a=ss.snapshotItem(s);
var oncl=a.getAttribute('onclick');
if(!oncl) { continue; }
if(!onclickRe.exec(oncl)) {
continue;
}
if(foundUpto>=1) {
// 2nd last link
nHtml.Click(a);
return true;
}
foundUpto++;
}
/*
for(var s=0; s<ss.snapshotLength; s++) {
var a=ss.snapshotItem(s);
var oncl=a.getAttribute('onclick');
if(!oncl) { continue; }
if(!onclickRe.exec(oncl)) {
continue;
}
if(numberRe.exec(a.textContent)) {
if(foundUpto>0) {
// only 1 pager link, it must be "prev" on the 2nd page, there won't be a "first" link.
nHtml.Click(firstPagerLink);
return true;
}
break;
}
if(foundUpto==0) {
firstPagerLink=a;
}
if(foundUpto==1) {
// the 2nd pager link with text
nHtml.Click(a);
return true;
}
foundUpto++;
}
*/
GM_log('No previous link found');
return false;
},
ClearFriendsBuffer:function() {
this.SetMessage("0 Friends in the current list.");
this.SaveFriendsFromHash({});
},
dataGTRe:/eng_tid":([0-9]+)/,
GetFriendIdFromLink:function(a,profileRe) {
var ppid=a.parentNode.parentNode.id;
var ppclass=a.parentNode.parentNode.className;
// ignore profile links in the status update and notifications areas.
if(ppid.indexOf('notification_')>=0 || ppclass=='status_updates' || a.parentNode.className=='fb_menu_title' || a.parentNode.id=='friend_guesser') { return null; }
var profileM=profileRe.exec(unescape(a.href));
// <a data-gt="{"engagement":{"eng_type":1,"eng_src":2,"eng_tid":1384454335,"eng_data":[]}}" href="http://www.facebook.com/Sailormmark">Mark Voll</a>
var dataGT=a.getAttribute('data-gt');
if(dataGT) {
var r=this.dataGTRe.exec(dataGT);
if(r) {
return r[1];
}
}
var id=null;
if(profileM && profileM.length>1) {
id=profileM[2];
} else {
var imgs=a.getElementsByTagName('img');
if(imgs && imgs.length>0) {
var imgM=this.imgRe.exec(imgs[0].src);
if(imgM && imgM.length>1) {
id=imgM[1];
}
}
}
return id;
},
imgRe:new RegExp("http://profile.ak.facebook.com/.*/[a-z]([0-9]+)_.*\\.jpg"),
profileRe:new RegExp('.facebook.com.*/(profile|friends).*id=([0-9]+)'), //change suggested by Austin Pereira - http://userscripts.org/topics/34741#posts-167127
GetFriendsFromPage:function(doc,profileRe) {
var as=doc.getElementsByTagName('a');
if(!profileRe) {
profileRe=this.profileRe;
}
var friendsFromPage={};
for(var aUpto=0; aUpto<as.length; aUpto++) {
var a=as[aUpto];
var id=this.GetFriendIdFromLink(a,profileRe);
if(id && !friendsFromPage[id]) {
GM_log('add friend to list:'+id);
friendsFromPage[id]=1;
}
}
return friendsFromPage;
},
/*
ShowAddFriendsFromPage:function() {
var div=document.createElement('div');
div.style.position='fixed';
div.style.left=0;
div.style.top=0;
div.innerHTML="<form>"+
"Next button: <input value='.facebook.com.*profile.php.*id=([0-9]+)' id='AddFriendsFromPageButton' />"+
"<input type='button' value='Go' id='AddFriendsFromPageButton' /><br /></form>";
document.body.appendChild(div);
var AddFriendsFromPageButton=document.getElementById('AddFriendsFromPageButton');
AddFriendsFromPageButton.addEventListener(function() {
var re=new RegExp(document.getElementById('AddFriendsFromPageButton').value);
FacebookInvites.GetFriendsFromPage(re,true);
},false);
},
*/
ClickAllFacebookFriendLinks:function() {
var ss=document.evaluate("//a[contains(@href,'.facebook.com')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var profileRe=new RegExp('facebook\.com/[^/]+$');
var profilePhpRe=new RegExp('facebook\.com/.*profile.php.*id=');
for(var s=0; s<ss.snapshotLength; s++) {
var a=ss.snapshotItem(s);
if(profileRe.exec(a.href) || profilePhpRe.exec(a.href)) {
GM_openInTab(a.href);
}
}
},
// add friends from any page
AddFriendsFromPage:function(info) {
if(info.pageUpto==undefined) {info.pageUpto=0; }
var friends=this.GetFriendsWithApp();
var addedFriends=0;
var friendsFromPage=this.GetFriendsFromPage(info.doc,info.profileRe);
for(var id in friendsFromPage) {
if(!friends[id]) {
friends[id]=1;
addedFriends++;
}
}
this.SaveFriendsFromHash(friends);
var totalFriends=0; for(var f in friends) { totalFriends++; }
GM_log('added '+addedFriends);
this.SetMessage("Added "+addedFriends+" to the current list, total:"+totalFriends);
if(info.doNextPage) {
var nextPage=nHtml.FindByXPath(document,".//a[contains(@class,'UIPager_ButtonForward')]");
if(nextPage) {
nHtml.Click(nextPage);
if(nextPage.parentNode.className.indexOf('Disabled')>=0) {
// no more next buttons
GM_log("No more next page buttons");
info.doNextPage=false;
}
} else {
var ss=document.evaluate("//a[contains(@onclick,'b:appfriends')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
if(ss && ss.snapshotLength>0) {
var lastItem=ss.snapshotItem(ss.snapshotLength-1);
var numberRe=/^[\\s0-9]+$/;
var m=numberRe.exec(lastItem.innerHTML.trim());
if(!m) {
// last one is not a number so it's a "next" button.
nHtml.Click(lastItem);
} else {
GM_log("No more next page buttons");
info.doNextPage=false;
}
} else if(info.pageUpto==0) {
// we can't even find a next button on the first page, let's not click 'next'
GM_log('No next button on first page, do not do multiple pages.');
info.doNextPage=false;
}
}
if(info.doNextPage) {
GM_log('Wait for Next button');
window.setTimeout(function() {
info.pageUpto++;
FacebookInvites.AddFriendsFromPage(info);
},2000);
}
}
},
//////////////////////////////////////
profileIdRe:new RegExp('id=([0-9]+)'),
IterateButtons:function(func) {
var ss=document.evaluate(".//*[contains(@class,'appRequest')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var info={
'func':func,
'ss':ss,
'sUpto':0,
// 'currentApp':'Unknown',
// 'currentAppIcon':null,
// 'currentAname':'',
// 'confirmUpto':0,
'nthButton':0
}
this.IterateButtonsNext(info);
},
IterateButtonsNext:function(info) {
var t=this;
if(info.sUpto>=info.ss.snapshotLength) return false;
var li=info.ss.snapshotItem(info.sUpto);
info.sUpto++;
if(li.className.indexOf('appRequestGroup')>0) {
var img=nHtml.FindByXPath(li,".//a[contains(@class,'UIImageBlock_ICON_Image')]/img");
var game=nHtml.FindByXPath(li,".//a[contains(@href,'apps.facebook')]/strong");
info.icon=img.src;
info.app=game.innerHTML;
t.IterateButtonsNext(info);
return;
}
if(li.className.indexOf('appRequestBody')<0) {
var inp=nHtml.FindByXPath(li,".//input[contains(@name,'action')]");
if(inp) {
info.value=inp.value;
info.obj=inp;
if(!info.func(info)) {
return;
}
}
}
t.IterateButtonsNext(info);
},
/*
IterateButtonsOld:function(func) {
var ss=document.evaluate(
"//*[contains(@class,'confirm_boxes') "+
"or contains(@class,'uiHeaderTop') "+
"or contains(@class,'mbl') "+
"or contains(@class,'uiRequestCloseSelectorButton') "+
"or contains(@class,'inputbutton') "+
"or contains(@name,'actions[') "+
"or contains(@class,'uiListVerticalItemBorder') "+
"or @class='confirm']",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var info={
'func':func,
'ss':ss,
'sUpto':0,
'currentApp':'Unknown',
'currentAppIcon':null,
'currentAname':'',
'confirmUpto':0,
'nthButton':0
}
this.IterateButtonsNext(info);
},
IterateButtonsNextOld:function(info) {
var donext=this.IterateButtonsNext2(info);
if(donext)
this.IterateButtonsNext(info);
},
IterateButtonsNextOld2:function(info) {
// var ss=document.evaluate("//*[contains(@class,'confirm_boxes') or contains(@class,'inputbutton') or @class='confirm']",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
// var currentApp='Unknown';
// var currentAname='';
// var confirmUpto=0;
// var nthButton=0;
var ss=info.ss;
if(info.sUpto>=ss.snapshotLength) { return; }
// for(var s=0; s<ss.snapshotLength; s++) {
var sObj=ss.snapshotItem(info.sUpto);
info.sUpto++;
if(sObj.className.indexOf('BulkAddButton')>=0) {
return true;
}
if(sObj.className=='confirm' || sObj.className.indexOf('uiListVerticalItemBorder')>=0) {
info.nthButton=0;
info.confirmUpto++;
return true;
}
if(sObj.className.indexOf('mbl')>=0
|| sObj.className.indexOf('uiHeaderTop')>=0) {
var spans=sObj.getElementsByTagName('span');
var h3s=sObj.getElementsByTagName('H3');
//var imgs=sObj.getElementsByTagName('img');
var icon=nHtml.FindByXPath(sObj,".//img[contains(@class,'UIImageBlock_ICON_Image')]");
if(h3s.length>0) {
info.currentApp=h3s[0].textContent.trim();
if(spans.length>0) {
info.currentAname=spans[0].id;
}
if(icon) {
info.currentAppIcon=[icon.src,icon.className];
} else {
//var is=sObj.getElementsByTagName('i');
//if(is.length>0 && is[0].className.indexOf('ICON')>=0) {
info.currentAppIcon=['',''];
//}
}
}
return true;
}
if(sObj.className.indexOf('confirm_boxes')>=0) {
var aname=sObj.id;
var imgs=sObj.getElementsByTagName('img');
var spans=sObj.getElementsByTagName('span');
if(spans.length>0) {
info.currentApp=spans[0].textContent.trim();
info.currentAname=aname;
if(imgs.length>0 && imgs[0].className.indexOf('ICON')>=0) {
info.currentAppIcon=[imgs[0].src,imgs[0].className];
} else {
var is=sObj.getElementsByTagName('i');
if(is.length>0 && is[0].className.indexOf('ICON')>=0) {
info.currentAppIcon=['',is[0].className];
}
}
}
return true;
}
var buttonValue=sObj.value;
var parent=sObj.parentNode;
var pmRe=RegExp('p.m ');
while(parent
// || (parent.className.indexOf('info')<0 && parent.tagName!="LI")
) {
if(parent.tagName=='BODY') { parent=null; break; }
if(parent.className!=undefined) {
if(parent.className.indexOf('uiListVerticalItemBorder')>=0 && parent.tagName=="LI") {
break;
}
if(parent.className.indexOf('confirm')>=0 && parent.tagName=="DIV") {
break;
}
//if(parent.className.indexOf('mbl')>=0 && parent.tagName=="DIV") {break; }
}
parent=parent.parentNode;
}
var profileHref=null;
var profileId=null;
if(parent) {
profileHref=nHtml.FindByXPath(parent,".//a[contains(@href,'profile.php')]");
if(profileHref) {
var pm=this.profileIdRe.exec(profileHref.href);
if(pm && pm.length>1) {
profileId=pm[1];
}
var nameInfo=profileHref.innerHTML.trim().split(new RegExp('\\s+'),2);
if(buttonValue) {
buttonValue=buttonValue.replace(profileHref.innerHTML+"'s",'');
buttonValue=buttonValue.replace(profileHref.innerHTML,'');
buttonValue=buttonValue.replace(nameInfo[0]+"'s",'');
buttonValue=buttonValue.replace(nameInfo[0],'');
} else {
buttonValue='X';
}
} else {
GM_log('No profile for button: '+sObj.value+',par:'+parent.tagName);
}
} else {
GM_log('Cannot find parent to button: '+sObj.value);
}
if(info.currentApp=="") {
return true;
}
var donext=false;
if(sObj.className.indexOf('inputbutton')>=0
|| sObj.className.indexOf('uiRequestCloseSelectorButton')>=0 // X close button
|| (sObj.name && sObj.name.indexOf('actions[')>=0)) {
donext=info.func(
{
'aname':info.currentAname,
'app':info.currentApp,
'icon':info.currentAppIcon,
'obj':sObj,
'info':info,
'value':buttonValue,
'parent':parent,
'profileId':profileId,
'confirmUpto':info.confirmUpto,
'nthButton':info.nthButton
});
}
info.nthButton++;
return donext;
},
*/
IsTest:function() {
var testBox=document.getElementById('BulkRequestsTest');
if(!testBox) { return false; }
var test=testBox?testBox.checked:false;
return test;
},
OpenInIFrame:function(url) {
var iframe=document.createElement('iframe');
iframe.style.display='none';
if(url) iframe.src=url;
document.body.appendChild(iframe);
return iframe;
},
RemoveIFrame:function(iframe) {
// we need to remove here with a timeout so that we're not removing while in an event of the iframe that we're removing.
window.setTimeout(function() {
GM_log('Remove iframe, document loaded or timed out');
iframe.parentNode.removeChild(iframe);
},3*1000);
},
RemoveIFrameOnLoad:function(iframe) {
var t=this;
window.setTimeout(function() {
if(iframe.contentDocument) {
iframe.contentDocument.addEventListener('load',function() {
if(iframe) t.RemoveIFrame(iframe);
iframe=null;
},false);
}
},2000);
window.setTimeout(function() {
if(iframe) t.RemoveIFrame(iframe);
iframe=null;
},30*1000);
},
SetBulkRequestOpenType:function(t) {
var select=document.getElementById('BulkRequestsNewTab');
if(!select) return;
for(var s=0; s<select.options.length; s++) {
var option=select.options[s];
if(option.value==t) { select.selectedIndex=s; }
}
},
GetBulkRequestOpenType:function() {
return document.getElementById('BulkRequestsNewTab').value;
},
NormalClick:function(form,button,clickFunc) {
var t=this;
var url=form.action+'?__a=1';
var ss=document.evaluate(".//input[@type='hidden']",form,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var data=button.name+'='+button.value+'&';
data+='nctr[_mod]=pagelet_requests&'+
'lsd&'+
'post_form_id_source=AsyncRequest&'+
'__user='+unsafeWindow.Env.user;
for(var s=0; s<ss.snapshotLength; s++) {
var inp=ss.snapshotItem(s);
data+='&'+inp.name+'='+inp.value;
}
GM_xmlhttpRequest({
'url':url,
'method':'POST',
'data':data,
onerror:function() {
GM_log("Failed to Open:"+url);
t.AddAutoAcceptError("Error with:"+url);
},
onload:function(resp) {
function unQuote(str) {
return str.replace(/\\(.)/g,'$1');
}
var m=/goURI\(([^\]]+)\);"/.exec(resp.responseText);
var newurl=unQuote(unQuote(m[1]));
newurl=newurl.replace(/^"/,'');
newurl=newurl.replace(/"$/,'');
clickFunc(newurl);
t.AddAutoAcceptError("Visited:"+newurl);
GM_log("Opened ok:"+newurl);
}
});
/*
form.action=form.action+'?__a=1';
form.target='_blank';
form.onsubmit='';
SendNormalClick();
function AppendHidden(n,v) {
var inp=document.createElement('input');
inp.type='hidden';
inp.name=n;
inp.value=v;
form.appendChild(inp);
}
AppendHidden('actions[accept]','Aceptar');
AppendHidden('nctr[_mod]','pagelet_requests');
AppendHidden('lsd','');
AppendHidden('post_form_id_source','AsyncRequest');
AppendHidden('__user',unsafeWindow.Env.user);
*/
},
ClickAutoAcceptButton:function(obj,normalClick) {
var t=this;
if(this.IsTest()) {
obj.style.border='3px solid #f00';
return;
}
var t=this;
//var onclick=obj.getAttribute('onclick');
var openType=this.GetBulkRequestOpenType();
if(openType=="") {
normalClick=true;
}
// var platformRe=new RegExp("click_add_platform_app[^;]+'(http[^']+)'");
var platformRe=/actions\[(http[^\]]+)\]/;
var m=platformRe.exec(obj.name);
if(m) {
var url=m[1].replace('&','&');
GM_log("Opening:"+url);
if(openType=='hidden') {
GM_xmlhttpRequest({
'url':url,
'method':'GET',
onerror:function() {
GM_log("Failed to Open:"+url);
t.AddAutoAcceptError("Error with:"+url);
},
onload:function() {
t.AddAutoAcceptError("Visited:"+url);
GM_log("Opened ok:"+url);
}
});
} else if(openType=='iframe') {
var iframe=this.OpenInIFrame(url);
iframe.style.display='block';
iframe.width='100%';
iframe.height='400';
t.RemoveIFrameOnLoad(iframe);
} else {
GM_openInTab(url);
}
}
var p=obj.parentNode;
var form=null;
while(p.tagName!="BODY" && p) {
if(p.tagName=="FORM") { form=p; break; }
p=p.parentNode;
}
// if(normalClick) {
if(form) {
t.NormalClick(form,obj,function(newurl) {
if(openType=='hidden') {
GM_xmlhttpRequest({
'url':newurl,
'method':'GET',
onload:function() {
GM_log('visited url without showing:'+newurl);
}
});
} else if(openType=='iframe') {
var iframe=this.OpenInIFrame();
iframe.src=newurl;
window.setTimeout(function() {
iframe.parentNode.removeChild(iframe);
},5000);
} else if(openType=='') {
GM_openInTab(newurl);
}
});
//GM_log('form:'+unsafeWindow.Env.user);
// form.submit();
// nHtml.Click(obj);
} else {
GM_log('Error: cannot find form with button'+obj.innerHTML);
}
/*
} else if(openType=='hidden' || openType=='tab') {
var ss=document.evaluate(".//input",form,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var dataStr='';
for(var s=0; s<ss.snapshotLength; s++) {
var inp=ss.snapshotItem(s);
if(inp.type.toUpperCase()=="SUBMIT") {
if(inp.name!=obj.name) {
continue;
}
}
dataStr+=escape(inp.name)+'='+escape(inp.value)+'&';
}
GM_xmlhttpRequest({
'url':form.action,
'headers':{'Content-type':'application/x-www-form-urlencoded'},
'method':'POST',
'data':dataStr
});
} else {
var iframe=this.OpenInIFrame();
iframe.contentDocument.body.innerHTML=
"<base href='"+document.location.href+
"' /><form method='"+form.method+"' action='"+form.action+"'>"+
form.innerHTML+"</form>";
iframe.contentDocument.forms[0].submit();
window.setTimeout(function() {
iframe.parentNode.removeChild(iframe);
},5000);
}
*/
},
GetMaxClicks:function() {
var maxClicks=document.getElementById('BulkRequestsMaxClicks');
if(!maxClicks) return 0;
return maxClicks.value;
},
GetClickDelay:function() {
var maxClicks=document.getElementById('BulkRequestsDelay');
if(!maxClicks) return null;
var v=parseInt(maxClicks.value);
if(isNaN(v)) return null;
return v;
},
ClickAutoAccept:function(e) {
var target=e.target;
var appInfo=target.parentNode.id.split('_',2);
var app=appInfo[1];
app=unescape(app);
var nth=null;
var button=null;
var byText=null;
if(target.id=='BulkClickByTextButton') {
byText=document.getElementById('BulkClickByText').value.toLowerCase().trim();
if(byText=="") return;
} else {
if(e.target.value.substring(e.target.value.length-6)=='button') {
var nthM=/^([0-9]+)/.exec(e.target.value);
nth=parseInt(nthM[1])-1;
} else {
var buttonInfo=e.target.value.split(' x ',2);
button=buttonInfo[1];
}
}
var friendsClicked={};
if(!e.buttonUpto) { e.buttonUpto=0; }
var t=this;
this.IterateButtons(function(info) {
t.SkipButton();
var ok=false;
var maxClicks=t.GetMaxClicks();
if(maxClicks>0 && e.buttonUpto>=maxClicks) {
return false;
}
if(byText!=null && info.value.toLowerCase().indexOf(byText)>=0) {
ok=true;
}
if((
(app==t.allAppsId || info.app==app)
&& (info.value==button || info.nthButton==nth)
) || ok) {
if(info.profileId) {
friendsClicked[info.profileId]=1;
}
/*
var friendList=document.getElementById('AcceptFriendList').value;
var friendAddSelect=t.GetFriendListDropDown(info.parent);
if(friendList.length>0) {
t.ClickFriendListDropDown(info.parent);
window.setTimeout(function() {
// wait for the drop down.
friendAddSelect=t.GetFriendListDropDown(info.parent);
if(!friendAddSelect) {
GM_log("Cannot find friend list drop down!");
}
if(friendAddSelect) {
// we have a drop down
t.SelectFriendListDropDown(friendAddSelect,friendList);
}
window.setTimeout(function() {
t.ClickAutoAcceptButton(info.obj,true);
t.IterateButtonsNext(info.info);
},1000);
},3000);
e.buttonUpto++;
return false;
}
*/
var openType=t.GetBulkRequestOpenType();
// var friendMenu=nHtml.FindByXPath(info.parent,".//span[@class='FriendAddingTool_Menu']");
// if(openType=="" || friendMenu) {
var currentButtonUpto=e.buttonUpto;
var currentObj=info.obj;
var wait;
var clickDelay=t.GetClickDelay();
if(clickDelay!=null) {
wait=clickDelay*1000*e.buttonUpto;
}
else if(openType=='hidden') wait=800*e.buttonUpto;
else wait=3*1000*e.buttonUpto;
window.setTimeout(function() {
t.SetAutoAcceptStatus("Clicking button: "+(currentButtonUpto+1));
t.ClickAutoAcceptButton(currentObj,false);
t.IterateButtonsNext(info);
},wait);
e.buttonUpto++;
return false;
}
return true;
});
this.SaveFriendsFromHash(friendsClicked);
},
ClickBlockButton:function() {
var blockDiv=nHtml.FindByXPath(document,".//div[contains(@class,'dialog_buttons')]");
if(!blockDiv) { return; }
var block=nHtml.FindByXPath(blockDiv,".//input[@type='button']");
if(block) {
GM_log('block button pressed');
nHtml.Click(block);
return true;
}
return false;
},
SetBlockUpto:function(clicked,s) {
var clickedStr='';
for(var click in clicked) {
clickedStr+=click+"###";
}
GM_setValue('blockLinkClicked',clickedStr);
GM_setValue('blockLinkUpto',s);
},
GetBlockUpto:function(clicked) {
var clickedStr=GM_getValue('blockLinkClicked','');
var clickedArr=clickedStr.split('###');
for(var c=0; c<clickedArr.length; c++) {
clicked[clickedArr[c]]=1;
}
return GM_getValue('blockLinkUpto',-1);
},
BlockAllApps:function() {
var clicked={};
var s=this.GetBlockUpto(clicked);
if(s<0) { return; }
var stopBlockAll=document.getElementById('StopBlockAllApps');
if(!stopBlockAll) {
this.SetMessage("<a id='StopBlockAllApps'>Stop block all applications</a>");
stopBlockAll=document.getElementById('StopBlockAllApps');
stopBlockAll.addEventListener('click',function() {
FacebookInvites.SetBlockUpto({},-1);
},false);
}
var s=0;
var test=this.IsTest();
var ss=document.evaluate("//a[contains(@onclick,'block_app_dialog')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var obj=null;
while(1) {
if(s>=ss.snapshotLength) {
this.SetMessage('Done block all');
this.SetBlockUpto({},-1);
window.setTimeout(function() {
this.ClickBlockButton();
},5000);
return;
}
obj=ss.snapshotItem(s);
var onclick=obj.getAttribute('onclick');
if(!clicked[onclick]) {
clicked[onclick]=1;
break;
}
s++;
continue;
}
this.SetBlockUpto(clicked,s);
window.setTimeout(function() {
GM_log('click block:'+obj.getAttribute('onclick'));
if(test) {
obj.style.border='3px solid #f00';
} else {
nHtml.Click(obj);
}
window.setTimeout(function() {
if(!FacebookInvites.ClickBlockButton()) {
// clicking the block button will reload the page, we will run again when the page reloads.
FacebookInvites.BlockAllApps();
}
},3000);
},1000);
},
GetDivToggle:function(mDiv,settingName,def) {
var bulkReqToggle=document.createElement('a');
bulkReqToggle.href='javascript:;';
var t=this;
bulkReqToggle.addEventListener('click',function() {
var show=GM_getValue(settingName,def);
var show=show?false:true;
GM_setValue(settingName,show);
mDiv.style.display=show?'block':'none';
},false);
mDiv.style.display=GM_getValue(settingName,def)?'block':'none';
return bulkReqToggle;
},
/*
SwitchConfirmDiv:function(nthButtonsToggle,nth) {
nthButtonsToggle.innerHTML=nth?"Switch to named buttons":"Switch to nth buttons";
document.getElementById("nthConfirmDiv").style.display=nth?"block":"none";
document.getElementById("nameConfirmDiv").style.display=nth?"none":"block";
GM_setValue('showNthDiv',nth);
},
*/
GetLastClicked:function(target) {
var lastClickedArr=GM_getValue("LastClicked","").split(',');
var lastClicked={};
for(var i=0; i<lastClickedArr.length; i+=2) {
if(lastClickedArr[i]=="") continue;
lastClicked[lastClickedArr[i]]=lastClickedArr[i+1];
}
return lastClicked;
},
SaveLastClicked:function(target) {
var lastClicked=this.GetLastClicked();
var appInfo=target.parentNode.id.split('_',2);
// var hash=target.parentNode.getAttribute('appHash');
var hash=target.parentNode.getAttribute('appName');
var valInfo=target.value.split(' x ');
var val=target.value;
if(valInfo.length>=2) val=valInfo[1];
lastClicked[hash]=this.GetBulkRequestOpenType()+"#"+val;
// lastClicked[hash]=this.GetBulkRequestOpenType()+"#"+target.value;
var lastClickedArr=[];
for(var id in lastClicked) {
lastClickedArr.push(id);
lastClickedArr.push(lastClicked[id].replace(/,/g,''));
}
GM_setValue("LastClicked",lastClickedArr.join(','));
},
ClickAutoAccepts:function(buttons) {
var buttonUpto=0;
for(var b=0; b<buttons.length; b++) {
var buttonInfo=buttons[b];
var button=buttonInfo.button;
var e={'target':button,'buttonUpto':buttonUpto};
this.SetBulkRequestOpenType(buttonInfo.openType);
this.ClickAutoAccept(e);
buttonUpto=e.buttonUpto;
}
},
SetAutoAcceptStatus:function(html) {
var d=document.getElementById('AutoAcceptStatus');
if(d) d.innerHTML=html;
},
AddAutoAcceptError:function(html) {
var d=document.getElementById('AutoAcceptError');
if(!d) return;
var div=document.createElement('div');
div.innerHTML=html;
d.appendChild(div);
},
ClickAllMoreRequests:function() {
var ss=document.evaluate(".//a[contains(@class,'uiMorePagerPrimary')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
var clicked=0;
for(var s=0; s<ss.snapshotLength; s++) {
var a=ss.snapshotItem(s);
nHtml.Click(a);
clicked++;
}
return clicked;
},
// add a link to auto accept all the friend requests on the page.
AddAutoAccept:function() {
var event=document.getElementById('globalContainer');
if(event) {
event=event.childNodes[0];
}
/*
var event=document.getElementById('friend_suggestion');
if(!event) event=document.getElementById('friend_add');
if(!event) event=document.getElementById('event_invite');
*/
if(!event) { return; }
var mDiv=document.getElementById('BulkRequestsDiv');
if(mDiv) { return; }
this.ClickAllMoreRequests();
mDiv=document.createElement('div');
var buttonTypes={};
var buttonsCount={};
var maxButtons={};
var appTypes={};
this.IterateButtons(function(info) {
var app=info.app;
var buttonValue=info.value;
appTypes[app]={'hash':info.aname,'icon':info.icon};
if(buttonTypes[app]==undefined) {
buttonTypes[app]={};
}
if(buttonTypes[app][buttonValue]==undefined) {
buttonTypes[app][buttonValue]=0;
}
buttonTypes[app][buttonValue]++;
appTypes[FacebookInvites.allAppsId]={'hash':'','desc':'<b>All Applications</b>'};
var buttonUpto=info.nthButton;
if(!maxButtons[app] || buttonUpto>=maxButtons[app]) {
maxButtons[app]=buttonUpto+1;
if(!maxButtons[FacebookInvites.allAppsId] || buttonUpto>=maxButtons[FacebookInvites.allAppsId])
maxButtons[FacebookInvites.allAppsId]=buttonUpto+1;
}
return true;
});
var bulkReqToggle=this.GetDivToggle(mDiv,'ShowBulkReqClick',true);
bulkReqToggle.innerHTML='<b>'+this.scriptName+': Show bulk click requests block</b>';
var toggleErrorDivJs='document.getElementById("AutoAcceptError").style.display'+
'=document.getElementById("AutoAcceptError").style.display=="none"'+
'?"block":"none"';
mDiv.id='BulkRequestsDiv';
var delay=this.GetClickDelay();
if(delay==null) delay='';
mDiv.innerHTML=
"You will have to press reload here to see the changes afterwards.<br />"+
"<input type='checkbox' id='BulkRequestsTest' />Test only(only highlights the buttons to be clicked)<br />"+
"<select id='BulkRequestsNewTab'><option value='' selected>Normal Click</option><option value='hidden' >Hidden (fastest but may not work)</option></select> when clicking on something (Some applications need this to confirm that you've accepted)<br />"+
// <option value='tab' >Open up a new tab</option>
// <option value='iframe'>Open up in iframe (at the bottom of page)</option>
"Only click <input size='3' id='BulkRequestsMaxClicks' /> buttons at a time, <input size='3' id='BulkRequestsDelay' value='"+delay+"' />secs inbetween each click.<br />"+
// "Friend list: <input type='text' id='AcceptFriendList' /> (only for when you're accepting friends)<br />"+
// "<input id='BulkClickByTextButton' type='button' value='Click all buttons with this text:' /> <input type='text' id='BulkClickByText' /> <br />"+
"<div id='AutoAcceptStatus'></div>"+
"<a href='javascript:;' onclick='"+toggleErrorDivJs+"'>Show messages</a><br /><div id='AutoAcceptError' style='display: none'></div>"
;
/*
// "<a id='nthButtonsToggle' style='font-size: 14pt' href='javascript:;'></a><br />"
var nthButtonsToggle=nHtml.FindByXPath(mDiv,"//a[@id='nthButtonsToggle']");
if(nthButtonsToggle) {
var t=this;
nthButtonsToggle.addEventListener('click',function() {
var show=document.getElementById("nthConfirmDiv").style.display=='none'?true:false;
t.SwitchConfirmDiv(nthButtonsToggle,show);
},false);
}
*/
var t=this;
mDiv.appendChild(document.createElement('br'));
var blockAllApps=document.createElement('A');
blockAllApps.innerHTML="Click on all 'Block application' links (becareful, facebook has no list of blocked applications)";
blockAllApps.addEventListener('click',function() {
FacebookInvites.SetBlockUpto({},0);
FacebookInvites.BlockAllApps();
},false);
mDiv.appendChild(blockAllApps);
mDiv.appendChild(document.createElement('br'));
mDiv.appendChild(document.createElement('br'));
var lastClickedButtons=[];
var clickLastClicked=document.createElement('A');
clickLastClicked.innerHTML='Click the same buttons you clicked last time(all the green ones)';
clickLastClicked.addEventListener('click',function() {
t.ClickAutoAccepts(lastClickedButtons);
},false);
mDiv.appendChild(clickLastClicked);
mDiv.appendChild(document.createElement('br'));
mDiv.appendChild(document.createElement('br'));
var nthDiv=document.createElement('div');
nthDiv.id='nthConfirmDiv';
nthDiv.style.display='none';
var nthTable=document.createElement('table');
nthDiv.appendChild(nthTable);
var appsArr=[];
for(var app in appTypes) {
appsArr.push(app);
}
var lastClicked=this.GetLastClicked();
appsArr=appsArr.sort();
var nameDiv=document.createElement('div');
nameDiv.id='nameConfirmDiv';
var nameTable=document.createElement('table');
nameDiv.appendChild(nameTable);
var lastClickedColor='#0f0';
for(var a=0; a<appsArr.length; a++) {
var app=appsArr[a];
var d=document.createElement('div');
var appInfo=appTypes[app];
if(appInfo.desc) { appDesc=appInfo.desc; }
else { appDesc=app; }
var appLink='<table border=0><tr><td>';
if(appInfo.icon) {
if(appInfo.icon[0]!="") {
appLink+="<img src='"+appInfo.icon[0]+"' />";
} else {
appLink+="<i class='"+appInfo.icon[1]+"'></i>";
}
}
appLink+="</td><td><a href='#"+appInfo.hash+"'>"+appDesc+"</a></td></tr></table>";
var hash=appTypes[app].hash;
var divId='ButtonApp_'+escape(app);
// var lastClickedForAppStr=lastClicked[hash];
var lastClickedForAppStr=lastClicked[app];
var lastClickedForApp=null;
var lastClickedOpenType='hidden';
if(lastClickedForAppStr) {
var lastClickedForAppInfo=lastClickedForAppStr.split('#');
if(lastClickedForAppInfo.length==1) {
lastClickedForApp=lastClickedForAppInfo[0];
} else {
lastClickedOpenType=lastClickedForAppInfo[0];
lastClickedForApp=lastClickedForAppInfo[1];
}
}
d.id=divId;
// d.setAttribute('appHash',hash);
d.setAttribute('appName',app);
var buttons=buttonTypes[app];
var buttonsAdded=0;
if(buttons) {
for(var button in buttons) {
var count=buttons[button];
//if(count<=1) { continue; }
var inp=document.createElement('input');
inp.type='button';
inp.className='inputbutton BulkAddButton';
inp.value=count+" x "+button;
if(lastClickedForApp && button==lastClickedForApp) {
inp.style.color=lastClickedColor;
lastClickedButtons.push({'button':inp,'openType':lastClickedOpenType});
}
inp.addEventListener('click',function(e) {
t.SaveLastClicked(e.target);
t.ClickAutoAccept(e);
},false);
d.appendChild(inp);
d.appendChild(document.createTextNode(' '));
buttonsAdded++;
}
}
var nthApp=document.createElement('DIV');
nthApp.id=divId;
// nthApp.setAttribute('appHash',hash);
nthApp.setAttribute('appName',app);
//nthApp.innerHTML=appDesc;
var maxButton=maxButtons[app];
for(var b=0; b<maxButton; b++) {
var inp=document.createElement('input');
inp.type='button';
inp.className='inputbutton BulkAddButton';
var suffix="th";
var b10=b%10;
if(b10==0) { suffix="st"; }
else if(b10==1) { suffix="nd"; }
else if(b10==2) { suffix="rd"; }
inp.value=(b+1)+suffix+" button";
if(lastClickedForApp && inp.value==lastClickedForApp) {
inp.style.color=lastClickedColor;
lastClickedButtons.push({'button':inp,'openType':lastClickedOpenType});
}
inp.addEventListener('click',function(e) {
t.SaveLastClicked(e.target);
t.ClickAutoAccept(e);
},false);
nthApp.appendChild(inp);
nthApp.appendChild(document.createTextNode(' '));
}
// nthApp.appendChild(document.createElement('BR'));
var nthRow=nthTable.insertRow(-1);
var desccell=nthRow.insertCell(-1);
desccell.innerHTML=appLink;
desccell.style.width='200px';
desccell.style.verticalAlign='top';
nthRow.insertCell(-1).appendChild(nthApp);
//nthDiv.appendChild(nthApp);
if(buttonsAdded>0) {
var nameRow=nameTable.insertRow(-1);
var desccell=nameRow.insertCell(-1);
desccell.style.width='200px';
desccell.style.verticalAlign='top';
desccell.innerHTML=appLink;
nameRow.insertCell(-1).appendChild(d);
}
}
mDiv.appendChild(nameDiv);
mDiv.appendChild(nthDiv);
event.parentNode.insertBefore(bulkReqToggle,event);
event.parentNode.insertBefore(mDiv,event);
// this.SwitchConfirmDiv(nthButtonsToggle,GM_getValue('showNthDiv',false));
/*
var BulkClickByTextButton=document.getElementById('BulkClickByTextButton');
BulkClickByTextButton.addEventListener('click',function(e) {
FacebookInvites.ClickAutoAccept(e);
},false);
*/
},
// auto bulk add when we get to the profile page.
SetAutoBulkAdd:function(enabled) {
GM_setValue('autoBulkAdd_Enabled',enabled);
if(document.getElementById('bulkAddComment')) {
GM_setValue('autoBulkAdd_Comment',document.getElementById('bulkAddComment').value);
GM_setValue('autoBulkAdd_FriendList',document.getElementById('bulkAddFriendList').value);
GM_setValue('autoBulkAdd_Test',document.getElementById('testBulkAddMeButton').checked);
}
},
GetAutoBulkAdd:function() {
var enabled=GM_getValue('autoBulkAdd_Enabled',false);
if(enabled && document.getElementById('bulkAddComment')) {
document.getElementById('bulkAddComment').value=GM_getValue('autoBulkAdd_Comment','');
document.getElementById('bulkAddFriendList').value=GM_getValue('autoBulkAdd_FriendList','');
document.getElementById('testBulkAddMeButton').checked=GM_getValue('autoBulkAdd_Test',false);
}
return enabled;
},
//////////////////////////
UncheckShowNews:function() {
var chks = document.evaluate("/html[@id='facebook']/body//input[@value='news_feed']",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i =0; i < chks.snapshotLength; i++) { chks.snapshotItem(i).checked=false;}
},
// click the "close" buttons
ClickClose:function() {
/*
var db=document.getElementById('dialog_buttons');
if(!db) db=nHtml.FindByXPath(document,"//div[contains(@class,'dialog_buttons')]");
if(!db) return;
*/
var popDialogss=document.evaluate(".//div[contains(@id,'pop_content')]",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for(var s=0; s<popDialogss.snapshotLength; s++) {
var pop_content=popDialogss.snapshotItem(s);
var chks = document.evaluate(".//input",pop_content,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
if(chks.snapshotLength==1) {
// only one button
var inp=chks.snapshotItem(0);
if(inp.name=='close') {
// only one button and it says "close"
GM_log('Close button clicked');
nHtml.Click(inp);
}
}
}
},
profilePageAdd:false,
CheckPage:function() {
var t=this;
try{
if(unsafeWindow.top && unsafeWindow.top.joinRecentLoadedLink!=undefined && unsafeWindow.joinRecentLoadedLink==undefined) {
window.setTimeout(function() {
if(unsafeWindow.top) {
unsafeWindow.top.joinRecentLoadedLink();
}
},5000);
return;
}
}catch(e) {
//GM_log('no permission probably:'+e);
// return;
}
var href=document.location.href+document.location.hash;
var ok=false;
// if(href.indexOf("/reqs.php")>=0) {
if(href.indexOf("/games")>=0) {
this.UncheckShowNews();
t.AddAutoAccept();
}
// if(href.indexOf("/profile.php")>=0) {
var profileStream=document.getElementById('profile_stream_container');
var okToAddAsFriend=false;
if(document.location.href.indexOf('/iframe/')<0) {
if(document.getElementById('pagelet_header_personal') && !profileStream) {
// we're not friends yet.
this.AddMeLinkAnyPage();
var addLink=nHtml.FindByXPath(document,".//a[contains(@href,'rel_dialog=1')]");
if(this.GetAutoBulkAdd() && !this.profilePageAdd) {
// auto add this person.
this.profilePageAdd=true;
if(addLink) {
this.addMeUptoMax=1;
this.StartBulkAddMe();
}
okToAddAsFriend=true;
}
}
if(!okToAddAsFriend && this.GetAutoBulkAdd()) {
// we're currently friends, let's close
this.CloseIFrameOnCompletion();
}
}
// if(href.indexOf("/social_graph.php")>=0) { //change suggested by Lox Myth - see http://userscripts.org/topics/34630#posts-166598
if(href.indexOf("friends_using_app")>=0) {
ok=this.AddFriendsWithApp();
} else {
this.AddMeLink();
ok=this.InviteFriends();
}
this.AddAsFriendLinks();
window.setTimeout(function() { FacebookInvites.CheckPage() },5000);
}
};
GM_registerMenuCommand('FB Invites - Show Bulk add friends dialog',function() {
FacebookInvites.AddMeLinkAnyPage();
});
GM_registerMenuCommand('FB Invites - Add all the friends on this page',function() {
var content=document.getElementById('content');
if(!content) content=document.body;
FacebookInvites.AddFriendsFromPage({'doc':content,'doNextPage':true});
});
GM_registerMenuCommand('FB Invites - Clear the current list of friends',function() {
FacebookInvites.ClearFriendsBuffer();
});
GM_registerMenuCommand('FB Invites - Detach the block if it is not visible',function() {
FacebookInvites.DetachDiv();
});
if(location.href.indexOf('facebook.com')<0) {
GM_registerMenuCommand('FB Invites - Open all facebook friend links here in new tabs',function() {
FacebookInvites.ClickAllFacebookFriendLinks();
});
}
if(location.href.indexOf('apps.facebook.com') > 0) {
GM_registerMenuCommand('FB Invites - Update friends using this application',function() {
FacebookInvites.VisitFriendsList();
});
}
window.addEventListener("load", function(e) {
window.GetFacebookInvites = function() {
return FacebookInvites;
}
FacebookInvites.CheckPage();
FacebookInvites.BlockAllApps();
/*
window.setTimeout(function() {
var uid="100000214449696";
var a=document.createElement('script');
// 29/nov/2009
a.innerHTML="Dialog.bootstrap('http://www.facebook.com/ajax/profile/connect.php?profile_id="+
uid+"&rel_dialog=1&src=top_bar&ondone_reload=0',null,false);";
document.body.appendChild(a);
},2000);
*/
}, false);
// join recent friends.
// test nth block, block buttons.