This is a script I wrote that would start with a given one of my friends on Facebook, poke all their friends, then move on to each of their friends and poke them, ad infinitum. Ended up poking upwards of 50,000 people and caused pandemonium among our friend group.

read more
on friendExtractionGivenan(id, type)
	
	
	if type is equal to "indirect" then
		tell application "Safari"
			set doc to front document
			set done_loading to false
			do JavaScript "
		window.location.assign('https://www.facebook.com/" & id & "?sk=friends&v=friends');
		" in doc
			delay 2
		end tell
	end if
	
	if type is equal to "direct" then
		tell application "Safari"
			set doc to front document
			set done_loading to false
			do JavaScript "
		window.location.assign('https://www.facebook.com/profile.php?id=" & id & "&sk=friends&v=friends');
		" in doc
			delay 2
		end tell
	end if
	
	
	
	
	tell application "Safari"
		repeat while done_loading is not equal to true
			set doc to front document
			set done_loading to do JavaScript "
			var done = false;
			 if (document.readyState=='complete'){
			 	done=true;
			}
			
			done;
				" in doc
			delay 1
		end repeat
	end tell
	
	
	
	tell application "Safari"
		set doc to front document
		set this_url to URL of doc
		set done_scrolling to false
		set filtered_URLs to {}
		set completed_once to false
		set erred_once to false
		
		
		repeat while done_scrolling is not equal to true
			try
				set done_scrolling to do JavaScript "
		
		var completed_once = " & completed_once & ";
		if(completed_once!=true){
		var done;
		var number_of_trys =0;
		}
    function scrollToBottom(){
      bottom = document.body.scrollHeight;
      current = window.innerHeight+ document.body.scrollTop;
	done = false;
      if((bottom-current) >0){
        window.scrollTo(0, bottom);
        setTimeout (scrollToBottom, 3500 ); //If the loading exceeds this timeout, a try will be used.
      }
	  else {
			done = true;	
			
	  }
    };
	if(completed_once!=true){
   	 scrollToBottom();
	}
	
	if(done==true&&number_of_trys<10){//This number changes the number of allowed timeouts
		done=false;
		number_of_trys++;
		setTimeout(scrollToBottom, 2000);
		//This number sets the allotted timeout length.
		//If the loading exceeds both the timeout above and this timeout, another try will be used immediately.
	}
	
	done;
	
    " in doc
				
				set completed_once to true
				delay 1.0
			on error
				
			end try
		end repeat
		
		
		
		set URLs to false
		repeat while URLs is equal to false
			set URLs to do JavaScript "

	   URLArray = [];

	      		allLinks = document.links;
		for (i = 0; i < allLinks.length; i++) {
		
			URLArray.push(allLinks[i].href);
		}
			URLArray;
			
	  " in doc
		end repeat
		return URLs
		
	end tell
	
end friendExtractionGivenan
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on pokedem_friends(id, type, database1)
	try
		if type is equal to "indirect" then
			tell application "Safari"
				set doc to front document
				set done_loading to false
				do JavaScript "
		window.location.assign('https://www.facebook.com/" & id & "');
		" in doc
				delay 1
			end tell
		end if
		
		if type is equal to "direct" then
			tell application "Safari"
				set doc to front document
				set done_loading to false
				do JavaScript "
		window.location.assign('https://www.facebook.com/profile.php?id=" & id & "');
		" in doc
				delay 1
			end tell
		end if
		
		tell application "Safari"
			repeat while done_loading is not equal to true
				set doc to front document
				set done_loading to do JavaScript "
			var done = false;
			 if (document.readyState=='complete'){
			 	done=true;
			}
			
			done;
				" in doc
				delay 1
			end repeat
		end tell
		
		
		
		tell application "System Events"
			tell process "Safari"
				click at {1898, 166} -- {from left, from top} 
				delay 0.5
				click at {1866, 187} -- {from left, from top} this varies depending on whether the user is online
				--delay 1
				--if numberPoked is less than 2000 then
				--click at {1565, 319} -- {from left, from top} 
				--else
				--	click at {1565, 444} -- {from left, from top}
				--end if
				
				delay 0.5
				tell application "Database Events"
					open database1
					tell database1
						make new record with properties {name:id}
					end tell
					save database1
				end tell
				
				
			end tell
		end tell
	on error errormsg
		if errormsg is equal to "User canceled." then
			return true
		else
			return false
		end if
	end try
	return false
end pokedem_friends
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on pokedem_friends_of_friends(id, type, numberPoked, database1)
	try
		if type is equal to "indirect" then
			tell application "Safari"
				set doc to front document
				set done_loading to false
				do JavaScript "
		window.location.assign('https://www.facebook.com/" & id & "');
		" in doc
				delay 1
			end tell
		end if
		
		if type is equal to "direct" then
			tell application "Safari"
				set doc to front document
				set done_loading to false
				do JavaScript "
		window.location.assign('https://www.facebook.com/profile.php?id=" & id & "');
		" in doc
				delay 1
			end tell
		end if
		
		tell application "Safari"
			repeat while done_loading is not equal to true
				set doc to front document
				set done_loading to do JavaScript "
			var done = false;
			 if (document.readyState=='complete'){
			 	done=true;
			}
			
			done;
				" in doc
				delay 1
			end repeat
		end tell
		
		
		
		tell application "System Events"
			tell process "Safari"
				click at {1898, 187} -- {from left, from top} {1898, 184}
				delay 0.5
				click at {1860, 190} -- {from left, from top}{1860, 215} this varies depending on whether the user is online
				delay 1.5
				if numberPoked is less than 2000 then
					click at {1565, 319} -- {from left, from top} 
				else
					click at {1565, 444} -- {from left, from top}
				end if
				delay 2
			end tell
		end tell
	on error
		
	end try
end pokedem_friends_of_friends
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on extractionOfIDsFrom(unfiltered_links)
	set unfiltered to unfiltered_links
	set filtered to {}
	set direct_IDs to {}
	set indirect_IDs to {}
	set refined_IDs to {}
	set returned_IDs to {}
	repeat with x from 1 to count of items of unfiltered
		set n to item x of unfiltered
		
		if "=pb" is in n then
			
			if n is not in filtered then set end of filtered to n
		end if
	end repeat
	
	
	
	repeat with y from 1 to count of items of filtered
		set profile to item y of filtered
		
		if "profile.php?" is in profile then
			
			set end of direct_IDs to text ((offset of "=" in profile) + 1) thru ((offset of "&" in profile) - 1) of profile
			
		else
			set end of indirect_IDs to text 25 thru ((offset of "?" in profile) - 1) of profile
			
		end if
		
	end repeat
	
	return direct_IDs & indirect_IDs
	
end extractionOfIDsFrom
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on pokedExtraction(unfiltered_links)
	set unfiltered to unfiltered_links
	set filtered to {}
	set direct_IDs to {}
	set indirect_IDs to {}
	set refined_IDs to {}
	set returned_IDs to {}
	
	
	repeat with y from 1 to count of items of unfiltered
		set alreadyCaptured to false
		set profile to item y of unfiltered
		if "profile.php?" is in profile then
			
			set theitem to text ((offset of "=" in profile) + 1) thru end of profile
			set alreadyCaptured to true
			if theitem is not in direct_IDs then set end of direct_IDs to theitem
			
			
		end if
		if alreadyCaptured is false then
			set theitem to text 25 thru end of profile
			if theitem is not in indirect_IDs then
				set characters1 to count theitem
				--display dialog theitem
				if (characters1 is less than 40) then set end of indirect_IDs to theitem
				
			end if
		end if
		
		
		
	end repeat
	
	return direct_IDs & indirect_IDs
	
end pokedExtraction
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

on direct_indirect_ID_Checker(id)
	try
		id as integer
		return "direct"
	on error
		
		return "indirect"
	end try
end direct_indirect_ID_Checker

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on existsInDatabaseChecker(user_id, database1)
	tell application "Database Events"
		
		if record user_id of database1 exists then
			return true
		else
			return false
		end if
	end tell
end existsInDatabaseChecker

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on existsInplistChecker(user_id, database)
	tell application "System Events"
		
		if property list item user_id of database exists then
			return true
		else
			return false
		end if
	end tell
end existsInplistChecker

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on alreadyPoked(blah, returnedIDs, database1)
	tell application "Database Events"
		repeat with a from 1 to count of items in blah
			set anID to item a of blah
			if record anID of database1 exists then
				
			else
				set end of returnedIDs to anID
			end if
		end repeat
	end tell
	return returnedIDs
end alreadyPoked
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on storePokes(returnedIDs, database1)
	tell application "Database Events"
		
		repeat with a from 1 to count of items in returnedIDs
			set anID to item a of returnedIDs
			tell database1
				make new record with properties {name:anID}
			end tell
		end repeat
		save database1
	end tell
end storePokes
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on exportToPlist(database1)
	
	tell application "System Events"
		set parent_dictionary to make new property list item with properties {kind:record}
		set the plistfile_path to ("Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:" & "Who_Youve_poked.plist")
		set plist to make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
	end tell
	
	
	tell application "Database Events"
		repeat with y from 1 to count of records in database1
			set currentRecordName to name of record y of database1
			
			tell application "System Events"
				tell plist
					make new property list item at end with properties {kind:record, name:currentRecordName}
				end tell
			end tell
			
			
		end repeat
	end tell
end exportToPlist
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on howmanypeopleyouvepoked(database1)
	tell application "Database Events"
		set hep to count of records in database1
	end tell
	display dialog hep
end howmanypeopleyouvepoked
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on hasthisuserbeenpoked(user, database1)
	
	tell application "Database Events"
		if record user of database1 exists then
			set result1 to "This user has already been poked"
		else
			set result1 to "This user has not been poked"
		end if
	end tell
	display dialog result1
	
end hasthisuserbeenpoked
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on refreshwhohasbeenpoked(database1)
	tell application "Safari"
		set doc to front document
		set done_loading to false
		do JavaScript "
		window.location.assign('http://www.facebook.com/pokes');
		" in doc
		delay 2
	end tell
	
	tell application "Safari"
		repeat while done_loading is not equal to true
			set doc to front document
			set done_loading to do JavaScript "
			var done = false;
			 if (document.readyState=='complete'){
			 	done=true;
			}
			
			done;
				" in doc
			delay 1
		end repeat
	end tell
	
	tell application "Safari"
		set URLs to false
		repeat while URLs is equal to false
			set URLs to do JavaScript "

	   URLArray = [];

	      		allLinks = document.links;
		for (i = 0; i < allLinks.length; i++) {
		
			URLArray.push(allLinks[i].href);
		}
			URLArray;
			
	  " in doc
		end repeat
		
	end tell
	
	
	
	set unfiltered to URLs
	set filtered to {}
	set direct_IDs to {}
	set indirect_IDs to {}
	set refined_IDs to {}
	set returned_IDs to {}
	
	
	repeat with y from 1 to count of items of unfiltered
		set alreadyCaptured to false
		set profile to item y of unfiltered
		if "profile.php?" is in profile then
			
			set theitem to text ((offset of "=" in profile) + 1) thru end of profile
			set alreadyCaptured to true
			if theitem is not in direct_IDs then set end of direct_IDs to theitem
			
			
		end if
		if alreadyCaptured is false then
			set theitem to text 25 thru end of profile
			if theitem is not in indirect_IDs then
				set characters1 to count theitem
				--display dialog theitem
				if (characters1 is less than 40) then set end of indirect_IDs to theitem
				
			end if
		end if
		
		
		
	end repeat
	
	set returnedIDs to direct_IDs & indirect_IDs
	display dialog (count of returnedIDs)
	tell application "Database Events"
		
		repeat with a from 1 to count of items in returnedIDs
			set anID to item a of returnedIDs
			tell database1
				make new record with properties {name:anID}
			end tell
		end repeat
		
	end tell
	save database1
	
	
end refreshwhohasbeenpoked
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

set theOutputFolder to POSIX path of "Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:"
set databaselocation to POSIX path of "Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:ThePokedUpdated.dbev"
tell application "Database Events"
	set database1 to database databaselocation
end tell

tell application "System Events"
	
	set parent_dictionary to make new property list item with properties {kind:record}
	set the plistfile_path to ("Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:" & "Poked.plist")
	set database to property list file plistfile_path
end tell

--howmanypeopleyouvepoked(database1)
--hasthisuserbeenpoked("Monstermac77", database1)
--display dialog existsInplistChecker("1068287181", database)

--refreshwhohasbeenpoked(database1)
--exportToPlist(database1)



set processCancelled to false
set requestingStartingID to display dialog "Press direct or indirect if you would like to poke one individual's friends" default answer "100002585480013" with title "Poker" buttons {"Indirect", "Direct", "Cancel"} default button "Direct"
set button_pressed to the button returned of the result
if the button_pressed is "Direct" then
	set startingIDType to "Direct"
	
else if the button_pressed is "Indirect" then
	set startingIDType to "Indirect"
	
else
	set processCancelled to true
	
end if

if processCancelled is false then
	set desiredAction to display dialog "Who would you like to poke?" with title "Poker" buttons {"Poke friends", "Poke friends' friends", "Cancel"} default button "Cancel"
	set button_pressed to the button returned of the result
	
	if the button_pressed is "Poke friends" then
		set startingID to text returned of requestingStartingID
		set unfiltered_links to friendExtractionGivenan(startingID, startingIDType)
		set returnedIDs to extractionOfIDsFrom(unfiltered_links)
		set blah to returnedIDs
		set returnedIDs to {}
		
		set returnedIDs to alreadyPoked(blah, returnedIDs, database1)
		
		repeat with c from 1 to count of items in returnedIDs
			set targetID to item c of returnedIDs
			set IDType to direct_indirect_ID_Checker(targetID)
			pokedem_friends(targetID, IDType, numberPoked)
		end repeat
		
		storePokes(returnedIDs, database1)
		save database1
		display dialog "Would you like to continue to the friends of friends?" with title "Poker Continued" buttons {"Yes", "No"} default button 2
		
		set button_pressed to the button returned of the result
		set numberPoked to 0
		if the button_pressed is "Yes" then
			repeat with c from 1 to count of items in returnedIDs
				set currentID to item c of returnedIDs
				set dataAlreadyCollected to existsInplistChecker(currentID, database)
				if dataAlreadyCollected is false then
					set IDType to direct_indirect_ID_Checker(currentID)
					set unfiltered_links to friendExtractionGivenan(currentID, IDType)
					set friends_of_friend to extractionOfIDsFrom(unfiltered_links)
					
					set blah to friends_of_friend
					set friends_of_friend to {}
					
					set friends_of_friend to alreadyPoked(blah, friends_of_friend, database1)
					
					repeat with d from 1 to count of items in friends_of_friend
						set numberPoked to numberPoked + 1
						set thetargetID to item d of friends_of_friend
						set theIDType to direct_indirect_ID_Checker(thetargetID)
						pokedem_friends(thetargetID, theIDType, numberPoked)
					end repeat
					
					storePokes(friends_of_friend, database1)
				end if
			end repeat
		end if
		
	else if the button_pressed is "Poke friends' friends" then
		set startingID to text returned of requestingStartingID
		set unfiltered_links to friendExtractionGivenan(startingID, startingIDType)
		set returnedIDs to extractionOfIDsFrom(unfiltered_links)
		set usercancelled to false
		
		repeat with c from 1 to count of items in returnedIDs
			
			if usercancelled is false then
				try
					set currentID to item c of returnedIDs
					set dataAlreadyCollected to existsInplistChecker(currentID, database)
					if dataAlreadyCollected is false then
						set IDType to direct_indirect_ID_Checker(currentID)
						set unfiltered_links to friendExtractionGivenan(currentID, IDType)
						set friends_of_friend to extractionOfIDsFrom(unfiltered_links)
						set blah to friends_of_friend
						set friends_of_friend to {}
						set friends_of_friend to alreadyPoked(blah, friends_of_friend, database1)
						
						
						repeat with d from 1 to count of items in friends_of_friend
							if usercancelled is false then
								set thetargetID to item d of friends_of_friend
								set theIDType to direct_indirect_ID_Checker(thetargetID)
								set usercancelled to pokedem_friends(thetargetID, theIDType, database1)
							end if
						end repeat
						
						--figure out a way to prevent this item to be stored unless all of the friends have been poked
						-- this is to avoid miss-storages due to user-cancellation DONE
						
						if usercancelled is false then
							tell application "System Events"
								tell database
									
									make new property list item at end with properties {kind:record, name:currentID}
								end tell
							end tell
						end if
						
					end if
				on error errormsg
					if errormsg is equal to "User canceled." then
						set usercancelled to true
					end if
				end try
				
			end if
		end repeat
	else
		
	end if
	
end if


--storePokes(friends_of_friend, database1)

--tell application "Database Events"
--	set database1 to database databaselocation
--	open database1
--	repeat with a from 1 to count of items in friends_of_friend
--		set anID to item a of friends_of_friend
--		tell database1
--			make new record with properties {name:anID}
--		end tell
--	end repeat
--	save database1

--end tell