<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"
>

<channel>
	<title>NuBlog &#187; Twitter</title>
	<atom:link href="http://blog.nuit.dk/category/twitter/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.nuit.dk</link>
	<description>Jens Ulrik Lange on Web technology, blogging, programming, Linux and IT project management</description>
	<lastBuildDate>Wed, 22 Sep 2010 20:56:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Twitter OAuth with PHP and cURL multi</title>
		<link>http://blog.nuit.dk/twitter-oauth-with-php-and-curl-multi/</link>
		<comments>http://blog.nuit.dk/twitter-oauth-with-php-and-curl-multi/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 19:33:25 +0000</pubDate>
		<dc:creator>jul</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[Software design]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.nuit.dk/?p=116</guid>
		<description><![CDATA[I am maintaining a website that aggregate a large number of Twitter accounts&#8217; tweets. For this purpose we&#8217;ve been given one of the accounts with the high API request rate limit &#8211; usually it is possible to call the Twitter API&#8217;s 150 times every hour. We have a rate limit of 20.000 hourly requests and [...]]]></description>
			<content:encoded><![CDATA[<img style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=21a11738f6a3b0696645fe12a6af6440&amp;default=http://use.perl.org/images/pix.gif' alt='No Gravatar' width=40 height=40/><p>I am maintaining a website that aggregate a large number of Twitter accounts&#8217; tweets. For this purpose we&#8217;ve been given one of the accounts with the high API request rate limit &#8211; usually it is possible to call the Twitter API&#8217;s 150 times every hour. We have a rate limit of 20.000 hourly requests and we use most of them to keep up a near real time picture of the activity of the user base.</p>
<p>Recently Twitter disabled regular basic HTTP authentication supporting only OAuth &#8211; which generally is a good thing, In this case we simply read the <a title="Twitter API docs" href="http://dev.twitter.com/doc/get/statuses/user_timeline">RSS-version of the user_timeline</a> and OAuth seems overkill for reading a simple public time line. Aaaanyways &#8211; we are using PHP with cURL multi and OAuth introduces a bit of extra code. Sure &#8211; there are plenty of OAuth API&#8217;s and OAuth API&#8217;s for Twitter out there, but the specific combination of PHP cURL multi and GET&#8217;ing user_timelines required a combination of Google&#8217;ing and a bit of guesswork.</p>
<h2 style="font-size: 1.5em;">Preparations</h2>
<p>- First <a title="Register your Twitter application" href="http://developer.twitter.com/apps/new">Register your application with Twitter</a> &#8211; You&#8217;ll need a couple of tokens and secrets from your app-page and from the specific token page.<br />
- If you need to make more than 150 requests per hour, apply for <a title="Twitter whitelisting application form" href="http://twitter.com/help/request_whitelisting">whitelisting here</a>.  It&#8217;ll take a while for Twitter to process your request.<br />
- Make sure you have cURL for PHP installed</p>
<p>Specifically preparing the GET connections for cURL presented a challenge &#8211; this piece of code did the trick for us:</p>
<pre>&lt;?php
// $url_array is an array of Twitter RSS-feed URL's that we need to read
$mh = curl_multi_init();
foreach($url_array as $i =&gt; $item) {
	// Keys and secrets from http://dev.twitter.com/apps/
	$consumer_secret = '&lt;get your own from http://dev.twitter.com/apps/_your_app_id_/&gt;';
	$token_secret = '&lt;get your own from http://dev.twitter.com/apps/_your_app_id_/my_token&gt;';

	// Build ud an array of OAuth parameters
	$params = Array();
	$params['oauth_consumer_key'] = '&lt;get your own from http://dev.twitter.com/apps/_your_app_id_/&gt;';
	$params['oauth_token'] = '&lt;get your own from http://dev.twitter.com/apps/_your_app_id_/my_token&gt;';
	$params['oauth_signature_method'] = 'HMAC-SHA1';
	$thetime = time();
	$params['oauth_timestamp'] = $thetime;
	$params['oauth_nonce'] = SHA1($thetime);
	$params['oauth_version'] = '1.0';

	// Sort the array alphabetically
	ksort($params);

	// Build the paramter string for the GET request
	$concatenatedParams = '';
	foreach($params as $k =&gt; $v)
	{
	  $k = urlencode($k);
	  $v = urlencode($v);
	  $concatenatedParams .= "{$k}={$v}&amp;";
	}
	$unencodedParams = substr($concatenatedParams,0,-1);
	// URL-encode the parameters for signature use
	$concatenatedParams = urlencode(substr($concatenatedParams,0,-1));
	$signatureBaseString = "GET&amp;".urlencode($item['url'])."&amp;".$concatenatedParams;

	$params['oauth_signature'] = base64_encode( hash_hmac('sha1', $signatureBaseString, $consumer_secret."&amp;".$token_secret, true) );

	// Initiate a new cURL connection and set up it's URL
	$conn[$i] = curl_init();
	curl_setopt($conn[$i], CURLOPT_URL, $item['url'] . '?' . $unencodedParams);
	curl_setopt($conn[$i], CURLINFO_HEADER_OUT, 1);

	// Build the HTTP header for the request
	$curlheader = Array();
	$curlheader[]='Content-Type: application/x-www-form-urlencoded';
	$curlheader[] = 'Authorization: OAuth';
	foreach($params as $ky=&gt;$va) {
		$curlheader[] = "$ky=$va,\n";
	}

	// Initiate a new cURL connection and assign URL + HTTP header to it
	$conn[$i] = curl_init($item['url']);
	curl_setopt($conn[$i], CURLOPT_HTTPHEADER, $curlheader);
	curl_setopt($conn[$i], CURLOPT_HTTPGET, 1);

	// Add the connection to the cURL multi handle
	curl_multi_add_handle ($mh,$conn[$i]);
}

// Now execute curl_multi_exec on the $mh handle</pre>
<div id="_mcePaste">This can no doubt be improved and secured in many ways, but since this specific example runs from as a cron-job/a PHP CLI &#8211; not on a server that replies to  inbound connections &#8211; the keys are not secured any further in this implementation.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nuit.dk/twitter-oauth-with-php-and-curl-multi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter is..</title>
		<link>http://blog.nuit.dk/twitter-is/</link>
		<comments>http://blog.nuit.dk/twitter-is/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 07:14:14 +0000</pubDate>
		<dc:creator>jul</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.nuit.dk/2009/04/24/twitter-er/</guid>
		<description><![CDATA[Twitter explained by Evan Williams.. Also &#8211; at Overskrift.dk, we launched TwitterValg today &#8211; a site to track tweets from candidates for the EU parliament election on June 7th.]]></description>
			<content:encoded><![CDATA[<img style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=21a11738f6a3b0696645fe12a6af6440&amp;default=http://use.perl.org/images/pix.gif' alt='No Gravatar' width=40 height=40/><p>Twitter explained by Evan Williams..</p>
<div class="youtube-video"><object width="446" height="326" data="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" /><param name="bgColor" value="#ffffff" /><param name="flashvars" value="vu=http://video.ted.com/talks/embed/EvanWilliams_2009-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/EvanWilliams-2009.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=473" /><param name="src" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" /><param name="bgcolor" value="#ffffff" /><param name="allowfullscreen" value="true" /></object></div>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" src="http://img.zemanta.com/pixy.gif?x-id=62ab265f-5a76-8d12-986f-c75b7ae93776" alt="" /></div>
<p>Also &#8211; at <a href="http://www.overskrift.dk">Overskrift.dk</a>, we launched <a href="http://www.twittervalg.dk">TwitterValg</a> today &#8211; a site to track tweets from candidates for the EU parliament election on June 7th.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nuit.dk/twitter-is/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

