Skip to content

Instantly share code, notes, and snippets.

@agustinhaller
Created October 24, 2012 17:57
Show Gist options
  • Select an option

  • Save agustinhaller/3947708 to your computer and use it in GitHub Desktop.

Select an option

Save agustinhaller/3947708 to your computer and use it in GitHub Desktop.
twitter class
<?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