Last active
October 6, 2016 15:15
-
-
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!
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 | |
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that this helper woks with API v1.0