您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Creates a low-access, read-only interface to the FB Graph API.
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/420/26698/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.3 // @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/v1.0/POST_ID/likes?access_token= var req; req=GM_xmlhttpRequest({ method: "POST", url: "https://graph.facebook.com/v1.0/"+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/v1.0/"+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/v1.0/"+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?method=GET&path=me%3Ffields%3Did%2Cname&version=v1.0", timeout: Graph.fetchTimeout*1000, onload: function(response) {try{ var test=response.responseText; var auth=test.longestQuoteWithin(matchFunc_OnlyAlphaNumeric); if (auth!="") { Graph.authToken = auth; log("Graph.requestAuthCodeB: got token"); //log("TOKEN: " + auth); 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/v1.0/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/v1.0/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(",")); //use single friend passes, not multi friend queries URL=URL.replace("{3}",params.friends); } else { URL=URL.replace("{3}","SELECT uid2 FROM friend WHERE uid1=me() LIMIT 5000"); } //as of FQL 2.1, WM can no longer request data by specific friend UID //so by default we now ALWAYS just use a list of all of our friends //URL=URL.replace("{3}","SELECT uid2 FROM friend WHERE uid1=me() LIMIT 5000"); //reinstated above params.friends parameter //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 URL=URL.replace("{1}",""); //temp fix, no app filtering ever /*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||5000)); //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.fetchPostsFQL_B(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.fetchPostsFQL: "+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.fetchPostsFQL_B(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/v1.0/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.fetchPostsFQL("+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" URL=URL.replace("{1}","");//temp fix /*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.fetchPostsFQL(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.fetchPostsFQL(params);} ); } else log("Graph.fetchPostsFQL: cannot refresh expired fb auth token",{level:3}); } else if (data.error.message||null) log("Graph.fetchPostsFQL: "+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.fetchPostsFQL(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/v1.0/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/v1.0/"+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/v1.0/"+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/v1.0/"+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/v1.0/"+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/v1.0/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/v1.0/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"); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址