Skip to content

Instantly share code, notes, and snippets.

@johnraff
Forked from russellbeattie/twitterfeed.php
Last active July 10, 2018 05:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnraff/6138936 to your computer and use it in GitHub Desktop.
Save johnraff/6138936 to your computer and use it in GitHub Desktop.
Access Twitter with OAuth, get json feed and output html for embedding in web page.
<?php
/**
* tweets2html.php
*
* Modified by John Crawley 2013/07/24
* to output html from Twitter feed for embedding in web page.
*
* Based on twitterfeed.php by Russell Beattie (2012-10-16)
* (http://www.russellbeattie.com/blog/twitterfeedphp-get-your-authenticated-twitter-stream-as-an-atom-feed)
*
* Also incorporates code adapted from:
* Yiming Liu's version:
* (http://blog.yimingliu.com/2013/02/07/a-twitter-timeline-to-atom-feed-proxy/)
* Twitterfeed+ by Patrick Nagel, 2013-04-06
* (https://patrick-nagel.net/scripts/twitterfeedplus/twitterfeedplus.php)
* and URL un-shortening by Marty (2012-11-12)
* (http://www.internoetics.com/2012/11/12/resolve-short-urls-to-their-destination-url-php-api/)
*
*
* Timestamps are simplified and relative.
* Short links are expanded: t.co from Twitter entities,
* and one further step if necessary.
* Long URLs are truncated for display.
* Links are added to @mentions and #hashtags
* HTML (ul) is wrapped in variable $tweetlist for embedding in web page,
* and cached to avoid multiple calls to Twitter.
* Licence: new material GPL3, other as per original authors.
*
* Usage instructions:
* 1) Go to https://dev.twitter.com/apps and create a new App.
* 2) Use the Authentication button to create the tokens/secrets needed.
* 3) Copy the results into the appropriate spots below.
* 4) The script is currently set to output a user timeline.
* Check the Twitter api docs: https://dev.twitter.com/docs/api/1.1
* and adjust $api_url and $api_params to suit your needs.
* ( Do not set 'include_entities' => 'false' )
* 5) Set $cache_path, make sure the directory exists, is writable
* by the server and outside the web root.
* 6) Adjust any other settings to taste.
* 7) Put this file in your include path, and include it somewhere near
* the start of your php with: require_once('tweets2html.php');
* NB This file contains your twitter app keys and secrets so be sure
* to put it above your web root, and give it minimum read permissions.
* 8) Call the html where you need it with: <?php echo($tweetlist); ?>
*
*/
// Twitter App Settings (https://dev.twitter.com/apps):
// FILL THESE IN
$settings = array(
'consumer_key' => '*REPLACEME*',
'consumer_secret' => '*REPLACEME*',
'access_token' => '*REPLACEME*',
'access_token_secret' => '*REPLACEME*'
);
// API docs: https://dev.twitter.com/docs/api/1.1
$api_url = 'https://api.twitter.com/1.1/statuses/user_timeline.json';
$api_params = array(
'screen_name' => '*REPLACEME*',
'count' => 7,
'exclude_replies' => 'true',
'include_rts' => 'false',
'contributor_details' => 'false',
'trim_user' => 'true',
'include_entities' => 'true'
);
// Other settings:
// date_default_timezone_set('Asia/Tokyo'); // may (should?) be set elsewhere in your site
$url_max_display_length = 25; // long urls will be truncated to this
$error_message = 'Unable to display tweets.'; // display if getting tweets fails
$timestamp_title = 'View on Twitter'; // title for tweet's timestamp link
// Makes relative timestamps for tweets - edit to taste
function reltime($datetime)
{
$diff=(time() - $datetime);
$day=60*60*24;
if ($diff<$day) //Under a day
{
$reltime = 'Today';
}else{
$reltime = round($diff/$day) . ' days ago';
}
return $reltime;
}
// Caching - set path to cache directory:
// Make sure this folder exists, is writable by server and
// preferably outside the web root.
$cache_path = '../cache'; // path relative to web root.
$cache_life = 60*60; // (seconds)
// cache will be used if newer than 1 hr
// settings end here //
//////////////////////////////////////////////////////////////////////
$cache_file = $_SERVER['DOCUMENT_ROOT'].'/'.$cache_path.'/tweetlist.html';
if (file_exists($cache_file)) {
$timediff = (time() - filemtime($cache_file));
if ($timediff < $cache_life) {
$tweetlist = file_get_contents($cache_file);
return; // do not run rest of script
}
}
// OAuth:
function oauth_encode($data){
if(is_array($data)){
return array_map('oauth_encode', $data);
} else if(is_scalar($data)) {
return str_ireplace(array('+', '%7E'), array(' ', '~'), rawurlencode($data));
} else {
return '';
}
}
// OAuth base settings
$oauth_params = array(
'oauth_consumer_key' => $settings['consumer_key'],
'oauth_nonce' => md5(microtime() . mt_rand()),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_token' => $settings['access_token'],
'oauth_version' => '1.0',
);
// Sign OAuth params
$sign_params = array_merge($oauth_params, $api_params);
uksort($sign_params, 'strcmp');
foreach ($sign_params as $k => $v) {
$sparam[] = oauth_encode($k) . '=' . oauth_encode($v);
}
$sparams = implode('&', $sparam);
$base_string = 'GET&' . oauth_encode($api_url) . '&' . oauth_encode($sparams);
$signing_key = oauth_encode($settings['consumer_secret']) . '&' . oauth_encode($settings['access_token_secret']);
$oauth_params['oauth_signature'] = oauth_encode(base64_encode(hash_hmac('sha1', $base_string, $signing_key, TRUE)));
// Set Authorization header:
uksort($oauth_params, 'strcmp');
foreach ($oauth_params as $k => $v) {
$hparam[] = $k . '="' . $v . '"';
}
$hparams = implode(', ', $hparam);
$headers = array();
$headers['Expect'] = '';
$headers['Authorization'] = 'OAuth ' . $hparams;
foreach ($headers as $k => $v) {
$curlheaders[] = trim($k . ': ' . $v);
}
// Format params:
foreach ($api_params as $k => $v) {
$rparam[] = $k . '=' . $v;
}
$rparams = implode('&', $rparam);
//////////////////////////////////////////////////////////////////////////
// Un-shorten URL
function resolveShortURL($url) {
$ch = curl_init("$url");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5 );
$yy = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpCode == 404) {
return "";
}
$w = explode("\n",$yy);
$Redirect = array_values( preg_grep( '/[Ll]ocation/', $w ) );
if(count($Redirect) > 0) {
$url = $Redirect[0];
$url = str_ireplace("Location:", "", "$url");
$url = trim("$url");
return $url;
}
return "";
}
// Get domain from URL
function getdomain($url) {
$url = trim($url);
$url = preg_replace("/^(http(s)?:\/\/)*(www.)*/is", "", $url);
$url = preg_replace("/\/.*$/is" , "" ,$url);
return $url;
}
// Array of top URL shorteners
$shorteners = array( "tiny.cc", "is.gd", "own.ly", "rubyurl.com", "bit.ly", "tinyurl.com",
"moourl.com", "cli.gs", "ka.lm", "u.nu", "yep.it", "shrten.com", "miniurl.com", "snipurl.com",
"short.ie", "idek.net", "w3t.org", "shiturl.com", "dwarfurl.com", "doiop.com", "smallurl.in",
"notlong.com", "fyad.org", "safe.mn", "hex.io", "own.ly", "lnkd.in", "fb.me", "amzn.to",
"goo.gl", "j.mp", "mcaf.ee", "lnk.ms", "youtu.be", "wp.me", "fwd4.me", "su.pr", "t.co",
"snurl.com", "tr.im", "twurl.cc", "fat.ly", "ow.ly", "bbc.in");
// Truncate url for display
function truncate_url($url, $maxlength)
{
$url = preg_replace('/^https?:\/\//','',$url,1);
if (strlen($url) > $maxlength)
{
$url = substr($url,0,($maxlength -1)) . '…';
}
return $url;
}
//////////////////////////////////////////////////////////////////////////
// GET:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url . '?' . $rparams);
curl_setopt($ch, CURLOPT_HTTPHEADER, $curlheaders);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10 );
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$info = curl_getinfo($ch);
$error = curl_error($ch);
$errno = curl_errno($ch);
curl_close($ch);
if($code != 200){
error_log( "Error\n$code" );
error_log(print_r($response,TRUE));
error_log(print_r($info,TRUE));
$tweetlist = "<ul><li>$error_message</li></ul>";
return;
}
$all = json_decode($response, TRUE);
$tweetlist = "<ul>\n";
foreach($all as $tweet){
$id = $tweet['id_str'];
$text = htmlspecialchars($tweet['text']);
// $tweeter_name = htmlspecialchars($tweet['user']['name']);
// $tweeter_screen_name = $tweet['user']['screen_name'];
$tweeter_id = $tweet['user']['id_str'];
// $tweeter_url = $tweet['user']['url'];
// $tweeter_profile_image_url = $tweet['user']['profile_image_url'];
$source = htmlspecialchars($tweet['source']);
$created_time = strtotime($tweet['created_at']);
if(isset($tweet['entities'])){
if(isset($tweet['entities']['urls'])){
// expand t.co URLs, and possible second shortened URL after that.
$urls = $tweet['entities']['urls'];
foreach($urls as $url){
$url_orig = $url['url'];
$url_expanded = $url['expanded_url'];
if(in_array(getdomain($url_expanded), $shorteners)) {
$url_reexpanded = resolveShortURL($url_expanded);
if($url_reexpanded) {
$url_expanded = $url_reexpanded;
}
}
$url_expanded_tagged = '<a href="'.$url_expanded.'">'.truncate_url($url_expanded,$url_max_display_length).'</a>';
$text = str_replace($url_orig, $url_expanded_tagged, $text);
}
}
if(isset($tweet['entities']['user_mentions'])){
// add link to @ mentions
$mentions = $tweet['entities']['user_mentions'];
foreach($mentions as $mention){
$mention_name = htmlspecialchars($mention['name']);
$mention_screen_name = $mention['screen_name'];
$mention_tagged = '<a href="http://twitter.com/'.$mention_screen_name.'" title="'.$mention_name.'">@'.$mention_screen_name.'</a>';
$text = str_replace("@$mention_screen_name", $mention_tagged, $text);
}
}
if(isset($tweet['entities']['hashtags'])){
// add link to # hashtags
$hashtags = $tweet['entities']['hashtags'];
foreach($hashtags as $hashtag){
$hashtext_orig = $hashtag['text'];
$hashtext = htmlspecialchars($hashtext_orig);
$hashtag_tagged = '<a href="http://twitter.com/search?q=%23'.$hashtext.'&src=hash">#'.$hashtext.'</a>';
$text = str_replace("#$hashtext_orig", $hashtag_tagged, $text);
}
}
}
$timestamp = '<span class="tweet_time"><a href="http://twitter.com/'.$tweeter_id.'/status/'.$id.'" title="'.$timestamp_title.'">'.reltime($created_time).'</a></span>';
$text = '<span class="tweet_text">'.$text.'</span>';
$tweetlist .= '<li>'.$timestamp.' '.$text."</li>\n";
}
$tweetlist .= "</ul>\n";
//$tweetlist .= "<!--\n".print_r($all,TRUE)."\n-->"; // for debugging
file_put_contents($cache_file, $tweetlist, LOCK_EX);
@johnraff
Copy link
Author

johnraff commented Aug 2, 2013

Based on Russell Beattie's twitterfeed.php : https://gist.github.com/russellbeattie/3898467
and Liu Yiming's adaptation to use Twitter entities: https://gist.github.com/yimingliu/4735445
with material from Patrick Nagel:https://patrick-nagel.net/scripts/twitterfeedplus/twitterfeedplus.php
and Marty: http://www.internoetics.com/2012/11/12/resolve-short-urls-to-their-destination-url-php-api/

Creates a variable $tweetlist which holds an html <ul> containing the tweets for embedding in a web page as a customizable widget.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment