Creates a low-access, read-only interface to the FB Graph API.
Tính đến
Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta
// @require https://update.greasyfork.org/scripts/420/11266/WM%20Graph%20API%20Interface%20%28Beta%20Branch%29.js
// ==UserScript==
// @name WM Graph API Interface (Beta Branch)
// @namespace MerricksdadGraphInterface
// @description Creates a low-access, read-only interface to the FB Graph API.
// @license http://creativecommons.org/licenses/by-nc-nd/3.0/us/
// @version 3.2.1
// @copyright Charlie Ewing except where noted
// ==/UserScript==
//this script requires some functions in the WM Common Library
//this script needs access to a pre-defined JSON object
var workOffline=false;
(function(){
this.Graph = {
posts: {}, //location to store adjusted post data
authRequestOut: false, //dont ask for token while asking for token
authToken: (isChrome||getOpt("disableSaveAuthToken"))?null:getOpt("lastAuthToken"), //use stored fb token
userID: null,
userAlias: null,
userName: null,
fetchTimeout: 30,
requests: [],
likePost: function(postID,params){try{
//https://graph.facebook.com/POST_ID/likes?access_token=
var req; req=GM_xmlhttpRequest({
method: "POST",
url: "https://graph.facebook.com/"+postID+"/likes?access_token="+Graph.authToken,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
if (response.responseText=="true") {
if (params.callback) params.callback(params.post);
} else {
log(response.responseText);
}
}catch(e){log("Graph.likePost.onload: "+e);}},
onerror: function(response) {try{
}catch(e){log("Graph.likePost.onerror: "+e);}},
onabort: function(response) {try{
}catch(e){log("Graph.likePost.onabort: "+e);}},
ontimeout: function(response) {try{
}catch(e){log("Graph.likePost.ontimeout: "+e);}}
});
}catch(e){log("Graph.likePost: "+e);}},
unlikePost: function(postID){try{
//https://graph.facebook.com/POST_ID/likes?access_token=
var req; req=GM_xmlhttpRequest({
method: "DELETE",
url: "https://graph.facebook.com/"+postID+"/likes?access_token="+Graph.authToken,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
}catch(e){log("Graph.unlikePost.onload: "+e);}},
onerror: function(response) {try{
}catch(e){log("Graph.unlikePost.onerror: "+e);}},
onabort: function(response) {try{
}catch(e){log("Graph.unlikePost.onabort: "+e);}},
ontimeout: function(response) {try{
}catch(e){log("Graph.unlikePost.ontimeout: "+e);}}
});
}catch(e){log("Graph.unlikePost: "+e);}},
commentPost: function(postID,comment){try{
//https://graph.facebook.com/POST_ID/comments?message=&access_token=
var req; req=GM_xmlhttpRequest({
method: "POST",
url: "https://graph.facebook.com/"+postID+"/comments?access_token="+Graph.authToken+"&message="+comment,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
if (response.responseText=="true") {
//comment successful
} else {
log(response.responseText);
}
}catch(e){log("Graph.commentPost.onload: "+e);}},
onerror: function(response) {try{
}catch(e){log("Graph.commentPost.onerror: "+e);}},
onabort: function(response) {try{
}catch(e){log("Graph.commentPost.onabort: "+e);}},
ontimeout: function(response) {try{
}catch(e){log("Graph.commentPost.ontimeout: "+e);}}
});
}catch(e){log("Graph.commentPost: "+e);}},
requestAuthCodeB: function(callback){try{
log("Graph.requestAuthCodeB()");
if (Graph.authRequestOut) return {requestAlreadyOut:true}; //dont ask again while asking
Graph.authRequestOut = true;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: "http://developers.facebook.com/tools/explorer?&version=v1.0",
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
var test=response.responseText;
var auth=test.longestQuoteWithin();
if (auth!="") {
Graph.authToken = auth;
log("Graph.requestAuthCodeB: got token");
setOpt("lastAuthToken",auth);
} else {
log("Graph.requestAuthCodeB: "+response.responseText,{level:3});
}
Graph.authRequestOut=false;
if (callback) setTimeout(callback,0);
if(req)req=null;
}catch(e){log("Graph.requestAuthCodeB.onload: "+e);}},
onerror: function(response) {try{
Graph.authToken="";
Graph.authRequestOut=false;
log("Graph.requestAuthCodeB: error:"+response.responseText+"\n Trying again in 30 seconds.",{level:3});
setTimeout(function(){Graph.requestAuthCodeB(callback);},30000);
if(req)req=null;
}catch(e){log("Graph.requestAuthCodeB.onerror: "+e);}},
onabort: function(response) {try{
Graph.authToken="";
Graph.authRequestOut=false;
log("Graph.requestAuthCodeB: Request aborted, trying again in 30 seconds",{level:3});
if(req)req=null;
setTimeout(function(){Graph.requestAuthCodeB(callback);},30000);
}catch(e){log("Graph.requestAuthCodeB.onabort: "+e);}},
ontimeout: function(response) {try{
Graph.authToken="";
Graph.authRequestOut=false;
log("Graph.requestAuthCodeB: Request timeout, trying again in 30 seconds",{level:3});
if(req)req=null;
setTimeout(function(){Graph.requestAuthCodeB(callback);},30000);
}catch(e){log("Graph.requestAuthCodeB.ontimeout: "+e);}}
});
}catch(e){log("Graph.requestAuthCodeB: "+e);}},
requestAuthCode: function(callback){try{
log("Graph.requestAuthCode()");
if (Graph.authRequestOut) return {requestAlreadyOut:true}; //dont ask again while asking
Graph.authRequestOut = true;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: "http://developers.facebook.com/docs/reference/api/examples/",
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
var test=response.responseText;
var searchString='<a href="https://graph.facebook.com/me/home?access_token=';
var auth = test.indexOf(searchString),authEnd;
if (auth!=-1) {
authEnd = test.indexOf('">',auth);
var authCode = (test.substring(auth+(searchString.length), authEnd));
Graph.authToken = authCode;
setOpt("lastAuthToken",authCode);
log("Graph.requestAuthCode: got token");
} else {
log("Graph.requestAuthCode: "+response.responseText,{level:3});
}
Graph.authRequestOut=false;
if (callback) setTimeout(callback,0);
if(req)req=null;
}catch(e){log("Graph.requestAuthCode.onload: "+e);}},
onerror: function(response) {try{
Graph.authToken="";
Graph.authRequestOut=false;
log("Graph.requestAuthCode: error:"+response.responseText+"\n Trying again in 30 seconds.",{level:3});
setTimeout(function(){Graph.requestAuthCode(callback);},30000);
if(req)req=null;
}catch(e){log("Graph.requestAuthCode.onerror: "+e);}},
onabort: function(response) {try{
Graph.authToken="";
Graph.authRequestOut=false;
log("Graph.requestAuthCode: Request aborted, trying again in 30 seconds",{level:3});
if(req)req=null;
setTimeout(function(){Graph.requestAuthCode(callback);},30000);
}catch(e){log("Graph.requestAuthCode.onabort: "+e);}},
ontimeout: function(response) {try{
Graph.authToken="";
Graph.authRequestOut=false;
log("Graph.requestAuthCode: Request timeout, trying again in 30 seconds",{level:3});
if(req)req=null;
setTimeout(function(){Graph.requestAuthCode(callback);},30000);
}catch(e){log("Graph.requestAuthCode.ontimeout: "+e);}}
});
}catch(e){log("Graph.requestAuthCode: "+e);}},
fetchUser: function(params){try{
log("Graph.fetchUser()");
params=params || {};
if (!Graph.authToken) {
log("Graph.fetchUser: no authToken, get one");
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchUser(params);} );
} else {
log("Graph.fetchUser: cannot get new fb auth token",{level:3});
return {getAuthTokenFailed:true}
}
return;
}
var URL="https://graph.facebook.com/me?access_token="+Graph.authToken;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
if (response){
//convert to JSON
try{
var data = JSON.parse(response.responseText);
if (data["id"]||null){
//expected data exists
Graph.userID=data["id"||null];
Graph.userAlias=(data["username"]||null);
Graph.userName=(data["name"]||null);
if (params["callback"]) {
var fx=params["callback"];
delete params["callback"];
setTimeout(fx,0);
}
} else if (data["error"]||null) {
var emsg=data.error.message||null;
//check for session expired
if (emsg.find("Session has expired")||emsg.find("session is invalid")){
//session expired or logged out, get a new token
Graph.authToken="";
params["retries_expToken"]=(params["retries_expToken"])?params["retries_expToken"]+1:1; //count retries
if (params["retries_expToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchUser(params);} );
} else log("Graph.fetchUser: cannot refresh expired fb auth token",{level:3});
} else if (emsg) log("Graph.fetchUser: "+emsg,{level:3});
} else log("Graph.fetchUser: response was unrecognized",{level:3});
} catch (e){log("Graph.fetchUser: response error: "+e+": "+response);}
} else log("Graph.fetchUser: response was empty",{level:3});
if(req)req=null;
}catch(e){log("Graph.fetchUser.onload: "+e);}},
onabort: function(response) {try{
log("Graph.fetchUser: Request aborted, trying again in 30 seconds.");
setTimeout(function(){Graph.fetchUser(params);},30000);
if(req)req=null;
}catch(e){log("Graph.fetchUser.onabort: "+e);}},
ontimeout: function(response) {try{
log("Graph.fetchUser: Request timeout, trying again in 30 seconds.");
setTimeout(function(){Graph.fetchUser(params);},30000);
if(req)req=null;
}catch(e){log("Graph.fetchUser.ontimeout: "+e);}},
onerror: function(response) {try{
if (response.responseText=="") {
log(JSON.stringify(response));
log("Graph.fetchUser: responseText was empty. Check to make sure your browser is online.", {level:5});
}
var data = JSON.parse(response.responseText);
if (data) {if (data.error||null) {
var emsg=data.error.message||null;
//check for session expired
if (emsg.find("Session has expired")||emsg.find("session is invalid")){
//session expired or logged out, get a new token
Graph.authToken="";
params["retries_expToken"]=(params["retries_expToken"])?params["retries_expToken"]+1:1; //count retries
if (params["retries_expToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchUser(params);} );
} else log("Graph.fetchUser: cannot refresh expired fb auth token",{level:3});
} else if (emsg) log("Graph.fetchUser.onerror: "+emsg,{level:3});
}} else {
log("Graph.fetchUser.onerror: "+response+"\n Trying again in 30 seconds.");
setTimeout(function(){Graph.fetchUser(params);},30000);
if(req)req=null;
}
}catch(e){log("Graph.fetchUser.onerror: "+e);}}
});
}catch(e){log("Graph.fetchUser: "+e);}},
matchRequest: function(params){try{
for (var r in Graph.requests) {
var req = Graph.requests[r];
//match the feed
if (JSON.stringify(req.friends) == JSON.stringify(params.friends)){
//match the app filters
if (JSON.stringify(req.apps) == JSON.stringify(params.apps)) {
//match direction of request
if (req.direction==params.direction) {
return r;
}
}
}
}
return -1;
}catch(e){log("Graph.matchRequest: "+e);}},
validatePost: function(params){try{
var post=params.post;
var callback=params.callback;
var isOlder=params.next;
//log("Graph.validatePost()",{level:1});
//exclude non-app posts and posts with no action links
//if (!exists(post.actions||null) || !exists(post.application)) return;
//exclude posts with less than like and comment and which have no link
//if (!(post.actions.length>=2) || !exists(post.link)) return;
var postID=post["post_id"]||post["id"];
//exclude posts already in our repository
if (exists(Graph.posts[postID])) return;
//store a reference to this post
Graph.posts[postID]=1;
//send the post back to the callback function here
if (callback) setTimeout(function(){callback(post,isOlder);},0);
}catch(e){log("Graph.validatePost: "+e);}},
fetchPostsFQL_B: function(params){try{
console.log(JSON.stringify(params));
if (arguments.length==0) {
log("Graph.fetchPostsFQL: no parameters passed");
return;
}
/*
direction: 0=until now | 1=forward from front edge | -1=backward from back edge
apps = array of app id's to fetch posts for, error on no apps passed
friends = array of friend id's to fetch posts for, default all friends
limit = number to fetch
timeouts = number of timeouts so far when performing retry looping
targetEdge = unix time to continue fetching until
currentEdge = current remembered edge of feed
retries_noToken = number of times this function has called getAuthToken and failed
callback = function to enact on each post
edgeHandler = function to keep track of edges
*/
if (!(params.apps||null)) {
log("Graph.fetchPostsFQL: no apps requested");
return;
}
var bypassMatchRequest = (params.targetEdge||null)?true:false;
//validate current auth token
if (!Graph.authToken) {
log("Graph.fetchPostsFQL: no authToken, get one");
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchPostsFQL_B(params);} );
} else {
log("Graph.fetchPostsFQL: cannot get new fb auth token",{level:3});
return {getAuthTokenFailed:true};
}
return;
}
//check if there is a request already out with this feed id and matches the direction
if (!bypassMatchRequest) {
var r=Graph.matchRequest(params);
if (r!=-1){
log("Graph.fetchPostsFQL: a request is already out for posts in that direction and has not returned",{level:3});
return {requestAlreadyOut:true};
}
}
//compile feed request strings
var URL_prefix="https://graph.facebook.com/fql?access_token={0}&q=";
var URL="{\"query1\":\"SELECT post_id,target_id,message,app_id,action_links,created_time,attachment,app_data,like_info,source_id FROM stream WHERE source_id IN ({3}){1}{2} ORDER BY created_time DESC{4}\",\"query2\":\"SELECT uid,name FROM user WHERE uid IN (SELECT source_id FROM #query1)\"}";
URL_prefix=URL_prefix.replace("{0}",Graph.authToken);
//specialize call for specific friend post requests
if (params.friends||null) {
URL=URL.replace("{3}",params.friends.join(","));
} else {
URL=URL.replace("{3}","SELECT uid2 FROM friend WHERE uid1=me() LIMIT 5000");
}
//get older posts
//verify that the feed "until" time does not violate olderLimit set by user
if (params.direction<0){
URL=URL.replace("{2}"," AND created_time < "+params.currentEdge);
//get newer posts
} else if (params.direction>0){
URL=URL.replace("{2}"," AND created_time > "+params.currentEdge);
//fetch at current time
} else {
URL=URL.replace("{2}","");
}
//filters by apps requested
//unless no apps were passed or we specified no app filtering
if ((params.apps||null) && !(params.noAppFiltering||null)){
URL=URL.replace("{1}"," AND app_id IN ("+params.apps.join(",")+")");
} else {
//no app filtering, let WM do this internally
URL=URL.replace("{1}","");
}
//add the user defined fetchQty
URL=URL.replace("{4}","+LIMIT+"+(params.limit||25));
//encode the url
URL=URL_prefix+encodeURI(URL).replace(/\:/,"%3A").replace(/\#/,"%23");
log("Graph.fetchPostsFQL: processing feed <a target='_blank' href='"+URL+"'>"+URL+"</a>");
//remember this request
Graph.requests.push(mergeJSON(params));
//make the request
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
//show dev tools
if (opts && debug && !isChrome) if (opts.devDebugGraphData) {
var pkg=debug.print("Graph.fetchPostsFQL.onload.devDebugGraphData: ");
pkg.msg.appendChild(createElement("button",{type:"button",onclick:function(){
promptText(response.responseText);
}},[
createElement("img",{src:"http://i1181.photobucket.com/albums/x430/merricksdad/array.png",title:"Show Data",style:"width:16px;height:16px; vertical-align:bottom;"})
]));
}
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
if (response){
try{
//convert to JSON
var data = JSON.parse(response.responseText);
//manage the return object
if (exists(data.data)) {
//there should be two return queries under data
//zip the two together by matching the name to the source_id in the post
var realData = data.data[0].fql_result_set;
var nameData = data.data[1].fql_result_set;
var uidKeys = {};
for (var n=0,l=nameData.length;n<l;n++){
uidKeys[nameData[n].uid.toString()]=nameData[n].name;
}
for (var p=0,l=realData.length;p<l;p++){
realData[p].fromName = (uidKeys[realData[p].source_id.toString()]||"undefined");
}
data.data=realData;
//store posts
if (data.data.length) log("Graph.fetchPostsFQL.onLoad: "+data.data.length+" posts received. Validating data...");
else log("Graph.fetchPostsFQL.onLoad: facebook returned an empty data set.");
//no paging exists in the FQL system, we make our own
var gotMoreToDo=false;
var lastPullOldestPost=null;
var lastPullNewestPost=null;
if (data.data.length) {
lastPullOldestPost=data.data.last().created_time;
lastPullNewestPost=data.data[0].created_time;
}
if ((params.targetEdge||null) && (data.data.length)) {
gotMoreToDo = (params.direction<0)?
(lastPullOldestPost > params.targetEdge): //keep fetching older
(lastPullNewestPost < params.targetEdge); //keep fetching newer
}
//read them in backward
if (data.data.length) for (var i=data.data.length-1;i>=0;i--) {
var post=data.data[i];
//exclude posts already in our repository
if (Graph.posts[post["post_id"]]!=1) {
//store a reference to this post
Graph.posts[post["post_id"]]=1;
//send the post back to the callback function here
params.callback(post);
}
}
//process the edge handler for any request that returned posts
var edgeMsg = {friends:params.friends,apps:params.apps,edge:{}};
if (params.direction>=0) edgeMsg.edge.newer=lastPullNewestPost;
if (params.direction<=0) edgeMsg.edge.older=lastPullOldestPost;
if (data.data.length) if (params.edgeHandler||null) params.edgeHandler(edgeMsg);
//go back and do another request if we have specified we have more to do
//this is for use with fetchHours and similar functions
if (gotMoreToDo) {
log("Graph.fetchPostsFQL.onload: was not able to get enough in one return, going back for more...");
var newParams = mergeJSON(params);
newParams.currentEdge=(params.direction<0)?lastPullOldestPost:lastPullNewestPost;
Graph.fetchPosts(newParams);
}
} else if (data.error||null) {
//check for session expired
if ((data.error.message||"").find("Session has expired")){
//session expired, get a new token
Graph.authToken="";
params["retries_expToken"]=(params["retries_expToken"])?params["retries_expToken"]+1:1; //count retries
if (params["retries_expToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchPosts(params);} );
} else log("Graph.fetchPostsFQL: cannot refresh expired fb auth token",{level:3});
}
else if (data.error.message||null) log("Graph.fetchPosts: "+data.error.message,{level:3});
} else log("Graph.fetchPostsFQL: response was unrecognized",{level:3});
data=null;
} catch (e){log("Graph.fetchPostsFQL: response error: "+e+": "+response);}
} else log("Graph.fetchPostsFQL: response was empty",{level:3});
if(req)req=null;
}catch(e){log("Graph.fetchPostsFQL.onload: "+e);}},
onabort: function(response) {try{
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPostsFQL: aborted: "+response.responseText);
if(req)req=null;
}catch(e){log("Graph.fetchPostsFQL.onabort: "+e);}},
ontimeout: function(response) {try{
//remove the memory that a request is out
params.timeouts++;
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPostsFQL: timeout: retry="+(params.timeouts<3)+", "+response.responseText);
if(req)req=null;
if (params.timeouts<3) Graph.fetchPosts(params);
}catch(e){log("Graph.fetchPostsFQL.ontimeout: "+e);}},
onerror: function(response) {try{
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPostsFQL: error: "+response.responseText);
if(req)req=null;
}catch(e){log("Graph.fetchPostsFQL.onerror: "+e);}}
});
}catch(e){log("Graph.fetchPostsFQL_B: "+e);}},
fetchPostsFQL: function(params){try{
log("Graph.fetchPostsFQL("+((params.newer)?"newer":(params.older)?"older":"")+")",{level:1});
params=params || {};
params.timeouts=params.timeouts||0;
var bypassMatchRequest = (params.range||null)?true:false;
//remember the target position if this is a ranged search
//we'll pass targetrange back to this function later if we need to fetch more
if (params.range||null){
if (params.range.oldedge||null) params.targetedge = params.range.oldedge;
}
//validate auth token
if (!Graph.authToken) {
log("Graph.fetchPostsFQL: no authToken, get one");
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchPostsFQL(params);} );
} else {
log("Graph.fetchPostsFQL: cannot get new fb auth token",{level:3});
return {getAuthTokenFailed:true};
}
return;
}
//check if there is a request already out with this fb id and matches the direction
var r=Graph.matchRequest(params);
if (!bypassMatchRequest) if (r!=-1){
if (Graph.requests[r].older==null && Graph.requests[r].newer==null) {
log("Graph.fetchPostsFQL: the initial request for data has not been returned yet",{level:3});
return {initRequestSlow:true};
} else {
log("Graph.fetchPostsFQL: a request is already out for posts in that direction and has not returned",{level:3});
return {requestAlreadyOut:true};
}
}
var feed=params.feed||null;
var filter = (params.filter||"default");
//create default filter instances when they do not exist
if (params.groupApps||null) {
//set our filter to our first app in the groupApps
//this will be used below various times
filter = "app_"+params.groupApps[0];
if (feed||null) for (var a=0,l=params.groupApps.length;a<l;a++) {
var filtName = "app_"+params.groupApps[a];
if (!(feed.filters[filtName]||null)) feed.addFilter({id:filtName}); //create filter instance if needed
}
} else {
if (feed||null) if (!(feed.filters[filter]||null)) feed.addFilter({id:filter}); //create filter instance if needed
}
//compile feed request strings
var URL_prefix="https://graph.facebook.com/fql?access_token={0}&q=";
var URL="{\"query1\":\"SELECT post_id,target_id,message,app_id,action_links,created_time,attachment,app_data,like_info,source_id FROM stream WHERE source_id IN ({3}){1}{2} ORDER BY created_time DESC{4}\",\"query2\":\"SELECT uid,name FROM user WHERE uid IN (SELECT source_id FROM #query1)\"}";
URL_prefix=URL_prefix.replace("{0}",Graph.authToken);
//specialize call for specific friend post requests
if (params.specificFriend||null) {
URL=URL.replace("{3}",feed.id);
} else {
URL=URL.replace("{3}","SELECT uid2 FROM friend WHERE uid1=me() LIMIT 5000");
}
//get older posts
//verify that the feed "until" time does not violate olderLimit set by user
if (params.older){
var edge=(params.range||null)?params.range.oldedge:feed.filters[filter].oldedge;
if (edge||null){
var limit=(params.limit||null); //this is not FB search limit keyword, this is a WM timelimit
var timeNow=timeStamp();
//no oldest post limit on range fetches
if (params.range||null) limit=null;
if (limit) {
if ((timeNow-(edge*1000)) > limit) {
log("Graph.fetchPosts("+params.feed.url+"): the user-set older limit of this feed has been reached",{level:2});
return {olderLimitReached:true};
}
}
URL=URL.replace("{2}"," AND created_time < "+edge);
} else {
log("Graph.fetchPostsFQL("+params.feed.url+"): The previous result did not return pagination. Restarting fetching from current time.");
URL=URL.replace("{2}","");
}
//get newer posts
} else if (params.newer){
var edge=(params.range||null)?params.range.newedge:feed.filters[filter].newedge;
if (exists(edge)) {
URL=URL.replace("{2}"," AND created_time > "+edge);
}
//fetch at current time
} else {
URL=URL.replace("{2}","");
}
//filters come in the form of "app_123456789012"
if (params.groupApps||null) {
//fetch posts for multiple apps at once
URL=URL.replace("{1}"," AND app_id IN ("+params.groupApps.join(",")+")");
} else if (filter!=undefined && filter!=null){
URL=URL.replace("{1}"," AND app_id IN ("+filter.split("app_")[1]+")");
} else {
//no filter, nothing passed
//this should never happen
URL=URL.replace("{1}","");
}
//add the user defined fetchQty
URL=URL.replace("{4}","+LIMIT+"+(params.fetchQty||25));
//encode the url
URL=URL_prefix+encodeURI(URL).replace(/\:/,"%3A").replace(/\#/,"%23");
log("Graph.fetchPostsFQL: processing feed <a target='_blank' href='"+URL+"'>"+URL+"</a>");
//console.log(URL);
//return;
//remember this request
Graph.requests.push({feed:params.feed, older:params.older, newer:params.newer, filter:filter, groupApps:params.groupApps, specificFriend:params.specificFriend});
//console.log("request pushed");
//return;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
//show dev tools
if (opts && debug && !isChrome) if (opts.devDebugGraphData) {
var pkg=debug.print("Graph.fetchPostsFQL.onload.devDebugGraphData: ");
pkg.msg.appendChild(createElement("button",{type:"button",onclick:function(){
//response.responseText.toClipboard();
promptText(response.responseText);
}},[
createElement("img",{src:"http://i1181.photobucket.com/albums/x430/merricksdad/array.png",title:"Show Data",style:"width:16px;height:16px; vertical-align:bottom;"})
]));
}
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
if (response){
try{
//convert to JSON
var data = JSON.parse(response.responseText);
//manage the return object
if (exists(data.data)) {
//log("response contains data");
//there should be two return queries under data
//zip the two together by matching the name to the source_id in the post
var realData = data.data[0].fql_result_set;
var nameData = data.data[1].fql_result_set;
var uidKeys = {};
for (var n=0,l=nameData.length;n<l;n++){
uidKeys[nameData[n].uid.toString()]=nameData[n].name;
}
for (var p=0,l=realData.length;p<l;p++){
realData[p].fromName = (uidKeys[realData[p].source_id.toString()]||"undefined");
}
data.data=realData;
//store posts
if (data.data.length) log("Graph.fetchPostsFQL.onLoad: "+data.data.length+" posts received. Validating data...");
else log("Graph.fetchPostsFQL.onLoad: facebook returned an empty data set.");
//no paging exists in the FQL system, we make our own
var gotMoreToDo=false;
var lastPullOldestPost=null;
var lastPullNewestPost=null;
if (data.data.length) {
lastPullOldestPost=data.data.last().created_time;
lastPullNewestPost=data.data[0].created_time;
}
if ((params.targetedge||null) && (data.data.length)) {
gotMoreToDo = (lastPullOldestPost > params.targetedge);
}
//read them in backward
if (data.data.length) for (var i=data.data.length-1;i>=0;i--) {
var post=data.data[i];
Graph.validatePost({
post:post,
callback:params.callback||null,
older:params.older,
newer:params.newer
});
}
//go back and do another request if we have specified we have more to do
//this is for use with fetchHours and similar functions
if (gotMoreToDo) {
log("Graph.fetchPostsFQL.onload: was not able to get enough in one return, going back for more...");
//clone the last set of params
var newParams = mergeJSON(params);
newParams.range={oldedge:0,newedge:0}; //new instance to prevent byRef errors
//update the range settings
newParams.range.newedge=lastPullOldestPost;
newParams.range.oldedge=params.targetedge; //remember the original passed oldest data to target
//make the next request
Graph.fetchPosts(newParams);
}
//start cleanup
if (params.callback) delete params.callback;
//capture the next and prev urls, but dont overwrite current known time boundaries
if (data.data.length){
if (params.groupApps||null){
//manage all filters at once from the group-fetch apps array
for (var n=0,l=params.groupApps.length;n<l;n++){
var filtName = "app_"+params.groupApps[n];
if (!params.newer && !params.older) {
feed.filters[filtName].newedge = lastPullNewestPost;
feed.filters[filtName].oldedge = lastPullOldestPost;
}
if (params.newer) feed.filters[filtName].newedge = lastPullNewestPost;
if (params.older) feed.filters[filtName].oldedge = lastPullOldestPost;
}
} else if (filter!=undefined && filter!=null) {
//if the current request was a recent posts pull, set both edges
if (!params.newer && !params.older) {
feed.filters[filter].newedge = lastPullNewestPost;
feed.filters[filter].oldedge = lastPullOldestPost;
}
//if the current request got newer posts, push the newer post edge
if (params.newer) feed.filters[filter].newedge = lastPullNewestPost;
//if the current request got older posts, push the older post edge
if (params.older) feed.filters[filter].oldedge = lastPullOldestPost;
}
}
} else if (data.error||null) {
//check for session expired
if ((data.error.message||"").find("Session has expired")){
//session expired, get a new token
Graph.authToken="";
params["retries_expToken"]=(params["retries_expToken"])?params["retries_expToken"]+1:1; //count retries
if (params["retries_expToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchPosts(params);} );
} else log("Graph.fetchPostsFQL: cannot refresh expired fb auth token",{level:3});
}
else if (data.error.message||null) log("Graph.fetchPosts: "+data.error.message,{level:3});
} else log("Graph.fetchPostsFQL: response was unrecognized",{level:3});
data=null;
} catch (e){log("Graph.fetchPostsFQL: response error: "+e+": "+response);}
} else log("Graph.fetchPostsFQL: response was empty",{level:3});
if(req)req=null;
}catch(e){log("Graph.fetchPostsFQL.onload: "+e);}},
onabort: function(response) {try{
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPostsFQL: aborted: "+response.responseText);
if(req)req=null;
}catch(e){log("Graph.fetchPostsFQL.onabort: "+e);}},
ontimeout: function(response) {try{
//remove the memory that a request is out
params.timeouts++;
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPostsFQL: timeout: retry="+(params.timeouts<3)+", "+response.responseText);
if(req)req=null;
if (params.timeouts<3) Graph.fetchPosts(params);
}catch(e){log("Graph.fetchPostsFQL.ontimeout: "+e);}},
onerror: function(response) {try{
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPostsFQL: error: "+response.responseText);
if(req)req=null;
}catch(e){log("Graph.fetchPostsFQL.onerror: "+e);}}
});
}catch(e){log("Graph.fetchPostsFQL: "+e);}},
/* fetchPosts details:
params = {
feed:<feed reference>,
filter:<appID>,
next:<url containing 'until'>,
prev:<url containing 'since'>,
callback:<where to ship the return data>,
retries_noToken:<counter>,
fetchQty:<number>,
specific:<specific range object>
}
*/
fetchPosts: function(params){try{
log("Graph.fetchPosts is deprecated. Use Graph.fetchPostsFQL.");
return Graph.fetchPostsFQL(params);
log("Graph.fetchPosts()",{level:1});
params=params || {};
params.timeouts=params.timeouts||0;
var bypassMatchRequest = (params.range||null)?true:false;
//remember the target position if this is a ranged search
//the very first call we make is a "since" call, but all sequential calls are "until" calls due to FB's stupid pagination methods
if (params.range||null){
//log(params.range.since);
if (params.range.since||null) params.targetUntil = params.range.since;
}
if (!Graph.authToken) {
log("Graph.fetchPosts: no authToken, get one");
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchPosts(params);} );
} else {
log("Graph.fetchPosts: cannot get new fb auth token",{level:3});
return {getAuthTokenFailed:true};
}
return;
}
//check if there is a request already out with this fb id and matches the direction
var r=Graph.matchRequest(params);
if (!bypassMatchRequest) if (r!=-1){
if (Graph.requests[r].next==null && Graph.requests[r].prev==null) {
log("Graph.fetchPosts: the initial request for data has not been returned yet",{level:3});
return {initRequestSlow:true};
} else {
log("Graph.fetchPosts: a request is already out for posts in that direction and has not returned",{level:3});
return {requestAlreadyOut:true};
}
}
//for each user specified feed source, get posts
var feed=params.feed||null;
var filter = (params.filter||"default");
if (!(feed.filters[filter]||null)) feed.addFilter({id:filter}); //create filter instance if needed
var URL=feed.url+"?date_format=U&limit="+((params.range||null)?250:params.fetchQty)+"&access_token="+Graph.authToken;
//get older posts
//verify that the feed "until" time does not violate olderLimit set by user
if (params.next || ((params.range||null)?params.range.until||null:null) ){
var until=(params.range||null)?params.range.until:feed.filters[filter].next.getUrlParam("until");
//debug.print(["var until",until]);
if (until||null){
var limit=(params.limit||null); //this is not FB search limit keyword, this is a WM timelimit
var timeNow=timeStamp();
//no oldest post limit on range fetches
if (params.range||null) limit=null;
var fixTime = (until.length < 10)?(until+"000"):until;
//debug.print(["var until:",until, until.length, fixTime])
if (limit) {
if ((timeNow-(fixTime)) > limit) {
//log("Graph.fetchPosts("+params.feed.url+"): the user-set older limit of this feed has been reached",{level:2});
return {olderLimitReached:true};
}
}
URL+="&until="+fixTime;
} else {
log("Graph.fetchPosts("+params.feed.url+"): The previous result did not return pagination. Restarting fetching from current time.");
}
}
//get newer posts
//rules manager action fetchHours will be asking for a range staring at time X, so use range.since
else if (params.prev || ((params.range||null)?params.range.since||null:null) ) {
var since=(params.range||null)?params.range.since:feed.filters[filter].prev.getUrlParam("since");
if (exists(since)) {
URL+="&since="+since;
}
}
//add a filter if there is one
if (exists(params.filter)) URL+="&filter="+filter; //check using params.filter, do not use filter here or it may inject "default"
log("Graph.fetchPosts: processing feed <a target='_blank' href='"+URL+"'>"+URL+"</a>");
//remember this request
Graph.requests.push({feed:params.feed, next:params.next, prev:params.prev, filter:filter});
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph.fetchTimeout*1000,
onload: function(response) {try{
//show dev tools
if (opts && debug && !isChrome) if (opts.devDebugGraphData) {
var pkg=debug.print("Graph.fetchPosts.onload.devDebugGraphData: ");
pkg.msg.appendChild(createElement("button",{type:"button",onclick:function(){
//response.responseText.toClipboard();
promptText(response.responseText);
}},[
createElement("img",{src:"http://i1181.photobucket.com/albums/x430/merricksdad/array.png",title:"Show Data",style:"width:16px;height:16px; vertical-align:bottom;"})
]));
}
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
if (response){
try{
//convert to JSON
var data = JSON.parse(response.responseText);
//add new posts to graph.posts
if (exists(data.data)) {
//log("response contains data");
//alert(JSON.stringify(data.data));
//store posts
if (data.data.length) log("Graph.fetchPosts.onLoad: "+data.data.length+" posts received. Validating data...");
else log("Graph.fetchPosts.onLoad: facebook returned an empty data set.");
var gotMoreToDo=false;
if ((params.targetUntil||null) && (data.data.length) && (data.paging.next)) {
var lastPullOldestPost=data.paging.next.getUrlParam("until");
//2013/9/7: known facebook limit maximum is 500, but we are fetching in 250's
//have we maxed out AND is oldest returned post newer than what we asked for
gotMoreToDo = (data.data.length>=250) && (lastPullOldestPost > params.targetUntil);
}
if (data.data.length) for (var i=data.data.length-1;i>=0;i--) {
var post=data.data[i];
Graph.validatePost({
post:post,
callback:params.callback||null,
next:params.next
});
}
if (gotMoreToDo) {
log("Graph.fetchPosts.onload: was not able to get enough in one return, going back for more...");
//clone the last set of params
var newParams = mergeJSON(params);
newParams.range={since:0,until:0}; //new instance to prevent byRef errors
//update the range settings
//newParams.range.since=data.paging.previous.getUrlParam("since");
newParams.range.until=data.paging.next.getUrlParam("until");
//log([params.range.since,newParams.range.since,newParams.range.until,timeStampNoMS()]);
newParams.targetUntil = params.range.since; //remember the original passed oldest data to target
//make the next request
Graph.fetchPosts(newParams);
}
//start cleanup
if (params.callback) delete params.callback;
//capture the next and prev urls, but dont overwrite current known time boundaries
if (data.paging||null){
//if this is the first time we've used this object, remember its locations
if (!feed.filters[filter].next) feed.filters[filter].next = data.paging.next;
if (!feed.filters[filter].prev) feed.filters[filter].prev = data.paging.prev;
//if the current request did not get older posts, push the newer post bracket
if (!params.prev) feed.filters[filter].next = data.paging.next;
//if the current request did not get newer posts, push the older post bracket
if (!params.next) feed.filters[filter].prev = data.paging.previous;
} else {
log("Graph.fetchPosts.onLoad: facebook failed to return pagination data.")
}
} else if (data.error||null) {
//check for session expired
if ((data.error.message||"").find("Session has expired")){
//session expired, get a new token
Graph.authToken="";
params["retries_expToken"]=(params["retries_expToken"])?params["retries_expToken"]+1:1; //count retries
if (params["retries_expToken"]<3) {
Graph.requestAuthCodeB(function(){Graph.fetchPosts(params);} );
} else log("Graph.fetchPosts: cannot refresh expired fb auth token",{level:3});
}
else if (data.error.message||null) log("Graph.fetchPosts: "+data.error.message,{level:3});
} else log("Graph.fetchPosts: response was unrecognized",{level:3});
data=null;
} catch (e){log("Graph.fetchPosts: response error: "+e+": "+response);}
} else log("Graph.fetchPosts: response was empty",{level:3});
if(req)req=null;
}catch(e){log("Graph.fetchPosts.onload: "+e);}},
onabort: function(response) {try{
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPosts: aborted: "+response.responseText);
if(req)req=null;
}catch(e){log("Graph.fetchPosts.onabort: "+e);}},
ontimeout: function(response) {try{
//remove the memory that a request is out
params.timeouts++;
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPosts: timeout: retry="+(params.timeouts<3)+", "+response.responseText);
if(req)req=null;
if (params.timeouts<3) Graph.fetchPosts(params);
}catch(e){log("Graph.fetchPosts.ontimeout: "+e);}},
onerror: function(response) {try{
//remove the memory that a request is out
var r = Graph.matchRequest(params);
if (r!=-1) Graph.requests.remove(r);
log("Graph.fetchPosts: error: "+response.responseText);
if(req)req=null;
}catch(e){log("Graph.fetchPosts.onerror: "+e);}}
});
}catch(e){log("Graph.fetchPosts: "+e);}},
};
this.Graph2 = {
postData : {},
currentUser : {
authToken : null,
name : null,
id : null,
alias : null
},
friends : {},
friendLists : {},
groups : [],
fetchTimeout: 30,
getGraphExplorerAuthToken : function(callback){try{
//log("Graph.requestAuthCode()");
var req; req=GM_xmlhttpRequest({
method: "GET",
url: "http://developers.facebook.com/docs/reference/api/examples/",
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
var test=response.responseText;
var searchString='<a href="https://graph.facebook.com/me/home?access_token=';
var auth = test.indexOf(searchString),authEnd;
if (auth!=-1) {
authEnd = test.indexOf('">',auth);
var authCode = (test.substring(auth+(searchString.length), authEnd));
Graph2.currentUser.authToken = authCode;
log("Graph2.getGraphExplorerAuthToken: got token");
} else {
log("Graph2.getGraphExplorerAuthToken: "+response.responseText,{level:3});
}
if (callback) setTimeout(callback,0);
}catch(e){log("Graph2.getGraphExplorerAuthToken.onload: "+e);}},
onerror: function(response) {try{
Graph2.currentUser.authToken="";
log("Graph2.getGraphExplorerAuthToken: error:"+response.responseText+"\n.",{level:3});
}catch(e){log("Graph2.getGraphExplorerAuthToken.onerror: "+e);}},
onabort: function(response) {try{
Graph2.currentUser.authToken="";
log("Graph2.getGraphExplorerAuthToken: Request aborted",{level:3});
}catch(e){log("Graph2.getGraphExplorerAuthToken.onabort: "+e);}},
ontimeout: function(response) {try{
Graph2.currentUser.authToken="";
log("Graph.getGraphExplorerAuthToken: Request timeout",{level:3});
}catch(e){log("Graph2.getGraphExplorerAuthToken.ontimeout: "+e);}}
});
}catch(e){log("Graph2.getGraphExplorerAuthToken: "+e);}},
getAuthToken: function (callback){try{
getGraphExplorerAuthToken(callback);
}catch(e){log("Graph.getAuthToken: "+e);}},
likePost: function(params){try{
/*
postID
callback
post
responseText <--passback
*/
var req; req=GM_xmlhttpRequest({
method: "POST",
url: "https://graph.facebook.com/"+params.postID+"/likes?access_token="+Graph2.currentUser.authToken,
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
params.responseText = response.responseText
if (response.responseText=="true") {
if (params.callback) params.callback(params.post);
} else {
//log(response.responseText);
//hande in whatever called this function
}
}catch(e){log("Graph2.likePost.onload: "+e);}},
onerror: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.likePost.onerror: "+e);}},
onabort: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.likePost.onabort: "+e);}},
ontimeout: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.likePost.ontimeout: "+e);}}
});
}catch(e){log("Graph2.likePost: "+e);}},
unlikePost: function(params){try{
/*
postID
callback
post
responseText <--passback
*/
var req; req=GM_xmlhttpRequest({
method: "DELETE",
url: "https://graph.facebook.com/"+params.postID+"/likes?access_token="+Graph2.currentUser.authToken,
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
params.responseText = response.responseText
if (params.callback) params.callback(params.post);
}catch(e){log("Graph2.unlikePost.onload: "+e);}},
onerror: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.unlikePost.onerror: "+e);}},
onabort: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.unlikePost.onabort: "+e);}},
ontimeout: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.unlikePost.ontimeout: "+e);}}
});
}catch(e){log("Graph2.unlikePost: "+e);}},
commentPost: function(params){try{
/*
postID
callback
post
comment
responseText <--passback
*/
var req; req=GM_xmlhttpRequest({
method: "POST",
url: "https://graph.facebook.com/"+params.postID+"/comments?access_token="+Graph2.currentUser.authToken+"&message="+params.comment,
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
params.responseText = response.responseText
if (response.responseText=="true") {
if (params.callback) params.callback(params.post);
} else {
//log(response.responseText);
}
}catch(e){log("Graph2.commentPost.onload: "+e);}},
onerror: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.commentPost.onerror: "+e);}},
onabort: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.commentPost.onabort: "+e);}},
ontimeout: function(response) {try{
params.responseText = response.responseText
}catch(e){log("Graph2.commentPost.ontimeout: "+e);}}
});
}catch(e){log("Graph2.commentPost: "+e);}},
getCurrentUser : function(params){try{
/*
retires_noToken <-- counter for retries without successfully finding the token
responseText <--passback
*/
Graph2.getUser({
userID:"me",
callback:function(){Graph2.procCurrentUser(params);}
});
}catch(e){log("Graph2.getCurrentUser: "+e);}},
procCurrentUser : function(params){try{
/*
responseText
*/
var data = JSON.parse(params.responseText);
if (data["id"]||null){
//expected data exists
Graph2.currentUser.id=data["id"||null];
//Graph2.currentUser.alias=(data["username"]||null);
Graph2.currentUser.name=(data["name"]||null);
Graph2.currentUser.timezone=(data["timezone"]||null);
Graph2.currentUser.locale=(data["locale"]||null);
if (params.callback) setTimeout(function(){params.callback(Graph2.currentUser);},0);
} else if (data["error"]||null) {
var emsg=data.error.message||null;
//check for session expired
if (emsg.find("Session has expired")||emsg.find("session is invalid")){
//session expired or logged out, get a new token
Graph2.currentUser.authToken="";
params["retries_expToken"]=(params["retries_expToken"])?params["retries_expToken"]+1:1; //count retries
if (params["retries_expToken"]<3) {
setTimeout(function(){Graph2.getAuthToken({callback:Graph2.getCurrentUser});},0);
} else log("Graph2.procCurrentUser: cannot refresh expired fb auth token",{level:3});
} else if (emsg) log("Graph2.procCurrentUser: "+emsg,{level:3});
} else log("Graph2.procCurrentUser: response was unrecognized",{level:3});
}catch(e){log("Graph2.procCurrentUser: "+e);}},
getUser : function(params){try{
/*
userID <-- "me" for current user
callback
retires_noToken <-- counter for retries without successfully finding the token
responseText <--passback
*/
//log("Graph.getUser()");
params=params || {};
if (!Graph2.currentUser.authToken) {
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph2.getAuthToken(function(){Graph2.getUser(params);} );
} else {
log("Graph2.getUser: cannot get new fb auth token",{level:3});
return;
}
return;
}
var URL="https://graph.facebook.com/"+params.userID+"?access_token="+Graph2.currentUser.authToken;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
if (response){
params.responseText = response.responseText;
} else log("Graph2.getUser: response was empty",{level:3});
}catch(e){log("Graph2.getUser.onload: "+e);}},
onabort: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getUser: Request aborted");
}catch(e){log("Graph2.getUser.onabort: "+e);}},
ontimeout: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getUser: Request timeout");
}catch(e){log("Graph2.getUser.ontimeout: "+e);}},
onerror: function(response) {try{
params.responseText = response.responseText;
if (response.responseText=="") {
log("Graph2.getUser: responseText was empty. Check to make sure your browser is online.", {level:5});
} else {
log("Graph2.getUser: Request error");
}
}catch(e){log("Graph2.getUser.onerror: "+e);}}
});
}catch(e){log("Graph2.getUser: "+e);}},
getPost : function() {
},
getPosts : function() {
},
getIsFriend : function(userId) {
return ((Graph2.friends[userId]||null)!=null);
},
getFriends : function(params) {try{
params=params || {};
if (!Graph2.currentUser.authToken) {
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph2.getAuthToken(function(){Graph2.getFriends(params);} );
} else {
log("Graph2.getFriends: cannot get new fb auth token",{level:3});
return;
}
return;
}
var URL="https://graph.facebook.com/me/friends?limit=5000&access_token="+Graph2.currentUser.authToken;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
if (response){
params.responseText = response.responseText;
setTimeout(function(){Graph2.procFriends(params);},0);
} else log("Graph2.getFriends: response was empty",{level:3});
}catch(e){log("Graph2.getFriends.onload: "+e);}},
onabort: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getFriends: Request aborted");
}catch(e){log("Graph2.getFriends.onabort: "+e);}},
ontimeout: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getFriends: Request timeout");
}catch(e){log("Graph2.getFriends.ontimeout: "+e);}},
onerror: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getFriends: Request error");
}catch(e){log("Graph2.getFriends.onerror: "+e);}}
});
}catch(e){log("Graph2.getFriends: "+e);}},
procFriends : function(params){try{
/*
responseText
*/
var data = JSON.parse(params.responseText);
if (data["data"]||null){
//index friend user data
for (var user in data.data) {
Graph2.friends[user.id] = user;
}
if (params.callback) setTimeout(function(){params.callback(Graph2.friends);},0);
} else log("Graph2.procFriends: response was unrecognized",{level:3});
}catch(e){log("Graph2.procFriends: "+e);}},
getIsUserInFriendList : function() {
},
getFriendLists : function(params) {try{
params=params || {};
if (!Graph2.currentUser.authToken) {
params["retries_noToken"]=(params["retries_noToken"])?params["retries_noToken"]+1:1; //count retries
if (params["retries_noToken"]<3) {
Graph2.getAuthToken(function(){Graph2.getFriendLists(params);} );
} else {
log("Graph2.getFriendLists: cannot get new fb auth token",{level:3});
return;
}
return;
}
var URL="https://graph.facebook.com/me/friendlists?limit=5000&access_token="+Graph2.currentUser.authToken;
var req; req=GM_xmlhttpRequest({
method: "GET",
url: URL,
timeout: Graph2.fetchTimeout*1000,
onload: function(response) {try{
if (response){
params.responseText = response.responseText;
setTimeout(function(){Graph2.procFriend=Lists(params);},0);
} else log("Graph2.getFriendLists: response was empty",{level:3});
}catch(e){log("Graph2.getFriendLists.onload: "+e);}},
onabort: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getFriendLists: Request aborted");
}catch(e){log("Graph2.getFriendLists.onabort: "+e);}},
ontimeout: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getFriendLists: Request timeout");
}catch(e){log("Graph2.getFriendLists.ontimeout: "+e);}},
onerror: function(response) {try{
params.responseText = response.responseText;
log("Graph2.getFriendLists: Request error");
}catch(e){log("Graph2.getFriendLists.onerror: "+e);}}
});
}catch(e){log("Graph2.getFriendLists: "+e);}},
procFriendLists : function(params){try{
/*
responseText
*/
var data = JSON.parse(params.responseText);
if (data["data"]||null){
//index friend user data
for (var list in data.data) {
Graph2.friendLists[list.id] = list;
}
if (params.callback) setTimeout(function(){params.callback(Graph2.friendLists);},0);
} else log("Graph2.procFriendLists: response was unrecognized",{level:3});
}catch(e){log("Graph2.procFriendLists: "+e);}}
}
log("Graph initialized");
})();