Skip to content

Instantly share code, notes, and snippets.

@ddimitrioglo
Last active October 6, 2016 15:15
Show Gist options
  • Select an option

  • Save ddimitrioglo/dfe3b0f049567c3541ee97262d999470 to your computer and use it in GitHub Desktop.

Select an option

Save ddimitrioglo/dfe3b0f049567c3541ee97262d999470 to your computer and use it in GitHub Desktop.
Since twitter has switched to streaming his API, we have to collect the data by ourselves. So I investigated a bit Tweeter's GNIP api and wrote a helper class. I hope it will be helpful for someone!
<?php
use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
class TwitterGnipClient
{
const RULES_ENDPOINT = 'https://api.gnip.com...';
const STREAM_ENDPOINT = 'https://stream.gnip.com...';
/**
* @var string
*/
protected $user;
/**
* @var string
*/
protected $password;
/**
* @var HttpClient
*/
protected $httpClient;
/**
* TwitterGnipClient constructor.
* @param array $params
*/
public function __construct(array $params)
{
$this->user = $params['user'];
$this->password = $params['password'];
$this->httpClient = new HttpClient();
}
/**
* Auth username
* @return string
*/
protected function getUser()
{
return $this->user;
}
/**
* Auth password
* @return string
*/
protected function getPassword()
{
return $this->password;
}
/**
* Get Stream connection endpoint url
* @return string
*/
protected function getStreamUrl()
{
return self::STREAM_ENDPOINT;
}
/**
* Get rules endpoint url
* @return string
*/
protected function getRulesUrl()
{
return self::RULES_ENDPOINT;
}
/**
* Add rules to PowerTrack stream’s ruleset.
* @example ['id' => 'url', ...]
* @param array $data
*/
public function addRules(array $data)
{
$rules = [];
foreach ($data as $id => $url) {
$rules[] = $this->buildRuleForUrl($url, $id);
}
$this->httpClient->post($this->getRulesUrl(), [
'auth' => [$this->getUser(), $this->getPassword()],
'json' => ['rules' => $rules]
]);
}
/**
* Retrieves all existing rules for a stream.
* @return \Generator
*/
public function getRules()
{
$response = $this->httpClient->get($this->getRulesUrl(), [
'auth' => [$this->getUser(), $this->getPassword()]
]);
$batchStr = '';
$body = $response->getBody();
while (!$body->eof()) {
$batchStr .= $body->read(1024);
}
$batchArray = explode(PHP_EOL, $batchStr);
unset($batchStr);
foreach ($batchArray as $itemJson) {
yield $this->unpackJson($itemJson);
}
}
/**
* Removes the specified rules from the stream.
* @param $data
*/
public function deleteRules($data)
{
$rules = [];
foreach ($data as $id => $url) {
$rules[] = $this->buildRuleForUrl($url, $id);
}
$this->httpClient->delete($this->getRulesUrl(), [
'auth' => [$this->getUser(), $this->getPassword()],
'json' => ['rules' => array_values($rules)]
]);
}
/**
* Open stream through which the social data will be delivered.
* @return \Generator
*/
public function listenStream()
{
$response = $this->httpClient->get($this->getStreamUrl(), [
'auth' => [$this->getUser(), $this->getPassword()],
'stream' => true
]);
$batchStr = '';
$body = $response->getBody();
while (!$body->eof()) {
$batchStr .= $body->read(1024);
$batchArray = explode(PHP_EOL, $batchStr);
// leave the last piece of response as it can be incomplete
$batchStr = array_pop($batchArray);
foreach ($batchArray as $itemJson) {
yield $this->processBroadcastItem($this->unpackJson($itemJson));
}
}
$body->close();
}
/**
* Process broadcast item data
* @param $data
* @return array
*/
protected function processBroadcastItem($data)
{
if (is_array($data)) {
$url = str_replace('url_contains:', '', $data['gnip']['matching_rules'][0]['value']);
switch ($data['verb']) {
// Occurs when a user posts a new Tweet.
case 'post':
return $this->getMappedResponse($url, 'tweet', 1);
break;
// Occurs when a user Retweets another user's Tweet
case 'share':
return $this->getMappedResponse($url, 'retweet', $data['retweetCount']);
break;
}
}
return [];
}
/**
* Get mapped response
* @param string $url
* @param string $type
* @param int $value
* @return array
*/
protected function getMappedResponse($url, $type, $value)
{
$test = [
'url' => rtrim($url, '/'),
'tweets' => $type == 'tweet' ? (int) $value : 0,
'retweets' => $type == 'retweet' ? (int) $value : 0
];
return $test;
}
/**
* Build rule by url and tag
* @param string $url
* @param $tag
* @return array
*/
protected function buildRuleForUrl($url, $tag)
{
$ruleValue = preg_replace('/^https?:\/\//i', '', $url);
return [
'value' => sprintf('url_contains:%s', trim($ruleValue, '/')),
'tag' => (string) $tag
];
}
/**
* Get unpacked json
* @return mixed
*/
protected function unpackJson($json)
{
return json_decode($json, true);
}
/**
* Debug what request is sent over the wire.
* @example 'handler' => $this->requestDebugger()
* @return mixed
*/
private function requestDebugger()
{
$handler = $this->httpClient->getConfig('handler');
$middleware = Middleware::tap(function ($request) {
/** @var RequestInterface $request */
echo $request->getHeader('Content-Type');
});
return $middleware($handler);
}
}
@ddimitrioglo
Copy link
Copy Markdown
Author

Note that this helper woks with API v1.0

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