Created
October 24, 2012 17:57
-
-
Save agustinhaller/3947708 to your computer and use it in GitHub Desktop.
twitter class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /****** STYLE GUIDES *****/ | |
| /* About parameters: */ | |
| /* | |
| To make it flexible, all parameters have to be optional (that's why it receives an array) but there are some that are hard to remember and could | |
| be the default for certain scenarios. So if the parameter needed is in the array $parameter use it, if not use | |
| the default fallback. | |
| */ | |
| class Twitter{ | |
| private $tmhOAuth; | |
| private $authenticated_user; | |
| // This function will receive an array with users, it will iterate that array and try | |
| // to init tmhOAuth | |
| public function __construct($CONSUMER_KEY, $CONSUMER_SECRET, $users=null) | |
| { | |
| $got_tokens = false; | |
| if($users!=null) | |
| { | |
| // Connect to db | |
| $conn = connect_db(); | |
| if($conn!=false) | |
| { | |
| foreach ($users as $user) | |
| { | |
| if(!$got_tokens) | |
| { | |
| if(isset($user['username']) && $user['username']!=null && $user['username']!="") | |
| { | |
| print_str("Try to authenticate with user '".$user['username']."'"); | |
| $q_a_t = "SELECT oauth_token, oauth_token_secret | |
| FROM users_accounts | |
| WHERE username = '".$user['username']."' | |
| AND social_network = 'TWITTER' | |
| ORDER BY date_created | |
| LIMIT 1"; | |
| $r_a_t = mysql_query($q_a_t); | |
| if($r_a_t) | |
| { | |
| if(mysql_num_rows($r_a_t) > 0) | |
| { | |
| $a_t = mysql_fetch_array($r_a_t); | |
| // We've got tokens! | |
| $USER_TOKEN = $a_t['oauth_token']; | |
| $USER_SECRET = $a_t['oauth_token_secret']; | |
| $this->authenticated_user = $user['username']; | |
| $got_tokens = true; | |
| print_str("Tokens for user '".$user['username']."' OK!"); | |
| } | |
| else | |
| { | |
| print_str("No user '".$user['username']."' in db"); | |
| } | |
| } | |
| else | |
| { | |
| print_str("Error when getting user '".$user['username']."' tokens from db"); | |
| } | |
| } | |
| }// END GOT TOKENS | |
| }// END FOREACH | |
| } | |
| else | |
| { | |
| // Error when connecting to mysql | |
| } | |
| // Destroy db connection | |
| disconnect_db($conn); | |
| } | |
| // If we couldn't get tokens for any user, then use own app tokens | |
| if(!$got_tokens) | |
| { | |
| $USER_TOKEN = TWITTER_APP_TOKEN; | |
| $USER_SECRET = TWITTER_APP_SECRET; | |
| $this->authenticated_user = 'SORTWIT_APP'; | |
| print_str("Couldn't authenticate with any user, using own app tokens"); | |
| } | |
| $this->tmhOAuth = new tmhOAuth(array( | |
| 'consumer_key' => $CONSUMER_KEY, | |
| 'consumer_secret' => $CONSUMER_SECRET, | |
| 'user_token' => $USER_TOKEN, | |
| 'user_secret' => $USER_SECRET | |
| )); | |
| } | |
| public function getRateLimits() | |
| { | |
| $resources_rate_limits = array(); | |
| $tmhOAuth = $this->tmhOAuth; | |
| $tmhOAuth->request('GET', $tmhOAuth->url('1.1/application/rate_limit_status'), array( | |
| 'resources' => "friendships,users,followers,search,statuses,friends" | |
| )); | |
| if($tmhOAuth->response['code'] == 200) | |
| { | |
| $data = json_decode($tmhOAuth->response['response'], true); | |
| $resources_rate_limits = $data['resources']; | |
| } | |
| return $resources_rate_limits; | |
| } | |
| // This function checks if the specified tweet still exists or not | |
| public function tweetExists($tweet_id) | |
| { | |
| $tweet = array( "exists"=>false, | |
| "object"=>null); | |
| $tmhOAuth = $this->tmhOAuth; | |
| $tmhOAuth->request('GET', $tmhOAuth->url('1.1/statuses/show'), array( | |
| 'id' => $tweet_id | |
| )); | |
| $result_aux = "NOT RUN"; | |
| if($tmhOAuth->response['code'] == 200) | |
| { | |
| $data = json_decode($tmhOAuth->response['response'], true); | |
| //var_dump($data); | |
| // Tweet object bridge | |
| $tweet_bridge_data = $data; | |
| $tweet_created_date_aux = strtotime($tweet_bridge_data['created_at']); | |
| $tweet_created_date = date("Y-m-d H:i:s", $tweet_created_date_aux); | |
| $tweet_user_id = $tweet_bridge_data['user']['id_str']; | |
| $tweet_bridge = array( | |
| "tweet_id" => $tweet_bridge_data['id_str'], | |
| "tweet_text" => $tweet_bridge_data['text'], | |
| "tweet_created_date" => $tweet_created_date, | |
| "tweet_user_id" => $tweet_user_id, | |
| "tweet_user_username" => $tweet_bridge_data['user']['screen_name'], | |
| "tweet_user_name" => $tweet_bridge_data['user']['name'], | |
| "tweet_user_profile_url" => "http://twitter.com/".$tweet_bridge_data['user']['screen_name'], | |
| "tweet_user_profile_image_url" => $tweet_bridge_data['user']['profile_image_url'] | |
| ); | |
| $tweet = array( "exists"=>true, | |
| "object"=>$tweet_bridge); | |
| $result_aux = "OK"; | |
| } | |
| else// Twitter call error | |
| { | |
| $tw_response = $tmhOAuth->response['response']; | |
| $tweet = array( "exists"=>false, | |
| "object"=>null, | |
| "tw_response"=>$tw_response); | |
| $result_aux = "ERROR: ".$tw_response; | |
| } | |
| // Get rate limits | |
| $resources_rate_limits = $this->getRateLimits(); | |
| // print_str($resources_rate_limits); | |
| $twitterManager = TwitterManager::getManager(); | |
| $twitterManager->newCall($this->authenticated_user, "/statuses/show/:id", $result_aux, $resources_rate_limits); | |
| return $tweet; | |
| } | |
| public function getAuthenticatedUser() | |
| { | |
| return $this->authenticated_user; | |
| } | |
| // TO TEST | |
| // This function retrives all the results for certain search | |
| public function getTwitterSearch($search_query, $since_id=null) | |
| { | |
| $tmhOAuth = $this->tmhOAuth; | |
| // Now perform the search | |
| $last_page = 1; | |
| $keep_searching = true; | |
| $total_results_count = 0; | |
| $total_results = array(); | |
| $max_id = null; | |
| while($last_page <= 20 && $keep_searching) | |
| { | |
| $search_args = array(); | |
| $search_args['q'] = $search_query; | |
| $search_args['rpp'] = 100; | |
| if($since_id!=null) | |
| { | |
| $search_args['since_id'] = $since_id; | |
| } | |
| if($max_id!=null) | |
| { | |
| $search_args['max_id'] = $max_id; | |
| } | |
| print_str($search_args, "search_args"); | |
| $result_aux = "NOT RUN"; | |
| $tmhOAuth->request('GET', $tmhOAuth->url('1.1/search/tweets'), $search_args); | |
| if($tmhOAuth->response['code'] == 200) | |
| { | |
| $data = json_decode($tmhOAuth->response['response'], true); | |
| $result_aux = "OK"; | |
| $page_results = $data['statuses']; | |
| $page_results_count = count($page_results); | |
| print_str($page_results_count, "page_results_count"); | |
| if($page_results_count>0) | |
| { | |
| $total_results_count += $page_results_count; | |
| // Merge page results with total results | |
| $total_results = array_merge($total_results, $page_results); | |
| $last_page++; | |
| $keep_searching = true; | |
| $max_id = $page_results[$page_results_count-1]['id_str']; | |
| } | |
| else | |
| { | |
| $keep_searching = false; | |
| } | |
| } | |
| else// Twitter call error | |
| { | |
| $keep_searching = false; | |
| $tw_response = $tmhOAuth->response['response']; | |
| $result_aux = "ERROR: ".$tw_response; | |
| } | |
| // Get rate limits | |
| $resources_rate_limits = $this->getRateLimits(); | |
| // print_str($resources_rate_limits); | |
| $twitterManager = TwitterManager::getManager(); | |
| $twitterManager->newCall($this->authenticated_user, "/search/tweets", $result_aux, $resources_rate_limits); | |
| }// END WHILE | |
| // Now we have the complete search space in $total_results, lets return it | |
| return $total_results; | |
| } | |
| // TO TEST | |
| // This function is not in use in SORTWIT | |
| public function twitterLookup($all_participants_ids, $results_qty) | |
| { | |
| // Let's first sort the ids | |
| sort($all_participants_ids); | |
| $all_participants_qty = $results_qty; | |
| $results_per_page = 100; | |
| $all_participants = array(); | |
| if($all_participants_qty>0) | |
| { | |
| // We have to calculate how many pages are we going to bring (i mean how many calls to "getTwitterData" function do we need) | |
| $complete_pages = floor($all_participants_qty/$results_per_page); | |
| $pages_mod = $all_participants_qty % $results_per_page; | |
| $max_page = ($pages_mod > 0) ? $complete_pages + 1 : $complete_pages; | |
| $page_index = 1; | |
| while($page_index <= $max_page) | |
| { | |
| $page_offset = ((($page_index-1)*$results_per_page)+1); | |
| // Chop array to get 100's id to make the call to getTwitterData function | |
| $page_ids = array_slice($all_participants_ids, ($page_offset-1), $results_per_page); | |
| // Make call to getTwitterData function and append result to array | |
| $page_participants = getTwitterData($page_ids); | |
| // Merge | |
| $all_participants = array_merge($all_participants, $page_participants); | |
| $page_index++; | |
| } | |
| // As the function getTwitterData retrives a maximum of 100 records, it may happend that if we have | |
| // 610 ids and we request 550, we will get 600 instead (es multiplo de 100), so we need to slice the array in that case | |
| if(count($all_participants)>$all_participants_qty) | |
| { | |
| $all_participants_aux = array_slice($all_participants, 0, $all_participants_qty); | |
| $all_participants = $all_participants_aux; | |
| } | |
| } | |
| return $all_participants; | |
| } | |
| public function user_lookup($params = array()){ | |
| $this->tmhOAuth->request('GET', $this->tmhOAuth->url('1.1/users/lookup'), $params); | |
| if($this->tmhOAuth->response['code'] == 200) | |
| { | |
| $data = json_decode($this->tmhOAuth->response['response'], true); | |
| return $data; | |
| }else{ | |
| return false; | |
| } | |
| } | |
| public function tweet($params = array()){ | |
| /*** THIS ALLOW US TO PASS ONLY THE TEXT AS PARAMETER, OF AN ARRAY OF PARAMETERS TO BE MORE EXPLICIT ***/ | |
| if(!is_array($params)) $params = array("status"=>$params); | |
| $this->tmhOAuth->request('POST', $this->tmhOAuth->url('1.1/statuses/update'), $params); | |
| if($this->tmhOAuth->response['code'] == 200) | |
| { | |
| $data = json_decode($this->tmhOAuth->response['response'], true); | |
| return $data; | |
| }else{ | |
| return false; | |
| } | |
| } | |
| } | |
| // Class to manage Twitter calls flow | |
| // Instantiate it like this -> $pepe = TwitterManager::getManager(); | |
| Class TwitterManager | |
| { | |
| private static $manager; | |
| public $lookup_counter = 0; | |
| public $tweets_counter = 0; | |
| public $followers_counter = 0; | |
| public $friendships_counter = 0; | |
| public function __construct() | |
| { | |
| } | |
| // This is the singleton function | |
| public static function getManager() | |
| { | |
| if(!isset(self::$manager)) | |
| { | |
| self::$manager = new TwitterManager(); | |
| } | |
| return self::$manager; | |
| } | |
| // Manage API calls flow | |
| // This function adds 1 to $calls_counter and checks if it should trigger a sleep() or not | |
| public function newCall($tw_username, $endpoint, $result, $resources_rate_limits) | |
| { | |
| // First check if we have to trigger a sleep or not, we will only trigger sleeps for | |
| // "/users/lookup", "/search/tweets", "/followers/ids", "/friendships/show" | |
| $try_sleep = false; | |
| switch ($endpoint) | |
| { | |
| case '/users/lookup': | |
| $try_sleep = true; | |
| $this->lookup_counter++; | |
| $calls_counter_aux = $this->lookup_counter; | |
| $consecutive_calls = 5; | |
| break; | |
| case '/search/tweets': | |
| $try_sleep = true; | |
| $this->tweets_counter++; | |
| $calls_counter_aux = $this->tweets_counter; | |
| $consecutive_calls = 5; | |
| break; | |
| case '/followers/ids': | |
| $try_sleep = true; | |
| $this->followers_counter++; | |
| $calls_counter_aux = $this->followers_counter; | |
| $consecutive_calls = 5; | |
| break; | |
| case '/friendships/show': | |
| $try_sleep = true; | |
| $this->friendships_counter++; | |
| $calls_counter_aux = $this->friendships_counter; | |
| $consecutive_calls = 5; | |
| break; | |
| default: | |
| break; | |
| } | |
| if($try_sleep) | |
| { | |
| // Each five calls we trigger a sleep of 2 seconds | |
| if(($calls_counter_aux%$consecutive_calls)==0) | |
| { | |
| sleep(2); | |
| echo("<br/><br/>"); | |
| echo("sleeping"); | |
| echo("<br/><br/>"); | |
| } | |
| } | |
| // Now lets store this call in the db | |
| $possible_endpoints = array("/statuses/show/:id", "/search/tweets", "/statuses/retweets/:id", "/followers/ids", "/friendships/show", "/users/lookup", "/statuses/user_timeline/:id"); | |
| $endpoint_limits = array(); | |
| foreach ($resources_rate_limits as $resource_type) | |
| { | |
| foreach ($resource_type as $endpoint_name => $endpoint_values) | |
| { | |
| $is_wanted_endpoint = in_array($endpoint_name, $possible_endpoints); | |
| if($is_wanted_endpoint) | |
| { | |
| $endpoint_limits[] = array( | |
| "endpoint" => $endpoint_name, | |
| "remaining" => $endpoint_values['remaining'] | |
| ); | |
| } | |
| if($endpoint_name == $endpoint) | |
| { | |
| // Connect to db | |
| $conn = connect_db(); | |
| if($conn!=false) | |
| { | |
| // Then store data in db | |
| $q_irlt = " INSERT INTO twitter_rate_limits | |
| SET user = '".mysql_real_escape_string($tw_username)."', | |
| endpoint = '".mysql_real_escape_string($endpoint_name)."', | |
| date = '".date("Y-m-d H:i:s")."', | |
| result = '".mysql_real_escape_string($result)."', | |
| remaining = ".mysql_real_escape_string($endpoint_values['remaining']); | |
| $r_irlt = mysql_query($q_irlt); | |
| if($r_irlt) | |
| { | |
| // Insert OK | |
| print_str("Rate limits checked for endpoint '".$endpoint_name."' - OK"); | |
| } | |
| else// Error when saving to db | |
| { | |
| } | |
| } | |
| // Destroy db connection | |
| disconnect_db($conn); | |
| } | |
| }// END FOREACH 1 | |
| }// END FOREACH RESOURCES | |
| }// END METHOD | |
| public function getCallsCounter() | |
| { | |
| return $this->calls_counter; | |
| } | |
| } | |
| ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment