Skip to content
This repository has been archived by the owner on Nov 28, 2017. It is now read-only.

Commit

Permalink
Merge pull request #4 from tjournal/feature-several-pages
Browse files Browse the repository at this point in the history
Запрос нескольких страниц
  • Loading branch information
Ilya Chekalskiy committed May 16, 2015
2 parents e0f2ca6 + 2206d81 commit f3dbdfa
Showing 1 changed file with 110 additions and 67 deletions.
177 changes: 110 additions & 67 deletions src/Reviewer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Flintstone\Flintstone;
use Flintstone\FlintstoneException;
use GuzzleHttp\Client as Guzzle;
use GuzzleHttp\Pool as Pool;
use Maknz\Slack\Client as Slack;
use Psr\Log\LoggerInterface;

Expand All @@ -18,7 +19,7 @@ class Reviewer
*
* @var array
*/
public $countries = [ 'ru' => 'Russia', 'us' => 'US', 'ua' => 'Ukraine', 'by' => 'Belarus' ];
public $countries = ['ru' => 'Russia', 'us' => 'US', 'ua' => 'Ukraine', 'by' => 'Belarus'];

/**
* Application id
Expand All @@ -27,6 +28,13 @@ class Reviewer
*/
protected $appId;

/**
* Max pages to request from itunes, default is 3
*
* @var integer
*/
protected $maxPages;

/**
* Is sending fired for a first time
*
Expand All @@ -35,7 +43,7 @@ class Reviewer
protected $firstTime = false;

/**
* Exception cathced during the initialization
* Exception caught during the initialization
*
* @var Exception
*/
Expand Down Expand Up @@ -75,12 +83,14 @@ class Reviewer
/**
* Create Guzzle and Flintstone objects
*
* @param integer $appId application App Store id
* @param integer $appId application App Store id
* @param integer $maxPages max pages count to check
* @throws Exception when DB directory is not writable
*/
public function __construct($appId)
public function __construct($appId, $maxPages = 3)
{
$this->appId = intval($appId);
$this->maxPages = max(1, intval($maxPages));
$this->client = new Guzzle(['defaults' => ['timeout' => 20, 'connect_timeout' => 10]]);

$databaseDir = realpath(__DIR__ . '/..') . '/storage';
Expand All @@ -103,7 +113,7 @@ public function __construct($appId)
/**
* Slack options setter
*
* @param array $slackSettings e.g. [ 'endpoint' => 'https://hook.slack.com/...', 'channel' => '#reviews' ]
* @param array $slackSettings e.g. [ 'endpoint' => 'https://hook.slack.com/...', 'channel' => '#reviews' ]
* @return TJ\Reviewer
*/
public function setSlackSettings($slackSettings)
Expand All @@ -116,78 +126,113 @@ public function setSlackSettings($slackSettings)
/**
* PSR-3 compatible logger setter
*
* @param LoggerInterface $logger
* @param LoggerInterface $logger
* @return TJ\Reviewer
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;

if ($this->initException && $this->logger) {
$this->logger->error('Reviewer: exception while init', [ 'exception' => $this->initException ]);
$this->logger->error('Reviewer: exception while init', ['exception' => $this->initException]);
$this->initException = null;
}

return $this;
}

/**
* Get new reviews of the app
* Get reviews from country App Store
*
* @return array list of reviews
* @param integer $appId
* @param string $countryCode
* @param string $countryName
* @return array list of reviews
*/
public function getReviews()
public function getReviewsByCountry($appId, $countryCode, $countryName)
{
$appId = $this->appId;

$reviews = [];
foreach ($this->countries as $countryCode => $countryName) {
try {
$response = $this->client->get("https://itunes.apple.com/{$countryCode}/rss/customerreviews/id={$appId}/sortBy=mostRecent/json");
$reviewsData = $response->json();

// todo проверять несколько страниц
$requests = [];
for ($i = 1; $i <= $this->maxPages; $i++) {
array_push($requests, $this->client->createRequest("GET", "https://itunes.apple.com/{$countryCode}/rss/customerreviews/page={$i}/id={$appId}/sortBy=mostRecent/json"));
}

try {
$responses = Pool::batch($this->client, $requests);

foreach ($responses->getSuccessful() as $page => $response) {
$realPage = $page + 1;
$reviewsData = $response->json();

if (!isset($reviewsData['feed']) || !isset($reviewsData['feed']['entry']) || count($reviewsData['feed']['entry']) == 0) {
continue;
}
// Received empty page
if ($this->logger) {
$this->logger->debug('Empty page received for page ' . $realPage . ' and country ' . $countryCode);
}
} else {
if ($this->logger) {
$this->logger->debug('Received ' . count($reviewsData['feed']['entry']) . ' entries for page ' . $realPage . ' in country ' . $countryCode);
}

$applicationData = [];
foreach ($reviewsData['feed']['entry'] as $reviewEntry) {
if (isset($reviewEntry['im:name']) && isset($reviewEntry['im:image'])) {
// First element is always an app metadata
$applicationData = [
'name' => $reviewEntry['im:name']['label'],
'image' => end($reviewEntry['im:image'])['label'],
$applicationData = [];
foreach ($reviewsData['feed']['entry'] as $reviewEntry) {
if (isset($reviewEntry['im:name']) && isset($reviewEntry['im:image'])) {
// First element is always an app metadata
$applicationData = [
'name' => $reviewEntry['im:name']['label'],
'image' => end($reviewEntry['im:image'])['label']
];
continue;
}

$reviewId = intval($reviewEntry['id']['label']);
if ($this->storage->get("r{$reviewId}")) {
continue;
}

$review = [
'id' => $reviewId,
'author' => [
'uri' => $reviewEntry['author']['uri']['label'],
'name' => $reviewEntry['author']['name']['label']
],
'title' => $reviewEntry['title']['label'],
'content' => $reviewEntry['content']['label'],
'rating' => intval($reviewEntry['im:rating']['label']),
'country' => $countryName,
'application' => array_merge($applicationData, ['version' => $reviewEntry['im:version']['label']])
];

continue;
array_push($reviews, $review);
}
}
}
} catch (Exception $e) {
if ($this->logger) {
$this->logger->error('Reviewer: exception while getting reviews', ['exception' => $e]);
}
}

$reviewId = intval($reviewEntry['id']['label']);
if ($this->storage->get("r{$reviewId}")) {
continue;
}
return $reviews;

$review = [
'id' => $reviewId,
'author' => [
'uri' => $reviewEntry['author']['uri']['label'],
'name' => $reviewEntry['author']['name']['label']
],
'title' => $reviewEntry['title']['label'],
'content' => $reviewEntry['content']['label'],
'rating' => intval($reviewEntry['im:rating']['label']),
'country' => $countryName,
'application' => array_merge($applicationData, ['version' => $reviewEntry['im:version']['label']])
];

array_push($reviews, $review);
}
} catch (Exception $e) {
if ($this->logger) {
$this->logger->error('Reviewer: exception while getting reviews', [ 'exception' => $e ]);
}
}

/**
* Get new reviews of the app
*
* @return array list of reviews
*/
public function getReviews()
{
$appId = $this->appId;
$reviews = [];

foreach ($this->countries as $countryCode => $countryName) {
$reviewsByCountry = $this->getReviewsByCountry($appId, $countryCode, $countryName);

if (is_array($reviewsByCountry) && count($reviewsByCountry)) {
$reviews = array_merge($reviews, $reviewsByCountry);
}
}

Expand All @@ -197,8 +242,7 @@ public function getReviews()
/**
* Send reviews to Slack
*
* @param array $reviews list of reviews to send
*
* @param array $reviews list of reviews to send
* @return boolean successful sending
*/
public function sendReviews($reviews)
Expand Down Expand Up @@ -232,26 +276,25 @@ public function sendReviews($reviews)

try {
$slack = new Slack($this->slackSettings['endpoint']);
$slack->attach([
'fallback' => "{$ratingText} {$review['author']['name']}: {$review['title']}{$review['content']}",
'color' => ($review['rating'] >= 4) ? 'good' : (($review['rating'] == 3) ? 'warning' : 'danger'),
'pretext' => "{$ratingText} Review for {$review['application']['version']} from <{$review['author']['uri']}|{$review['author']['name']}>",
'fields' => [
[
'title' => $review['title'],
'value' => $review['content']
]
]
]);

if ($this->firstTime === true) {
$slack->send();
if ($this->firstTime === false) {
$slack->attach([
'fallback' => "{$ratingText} {$review['author']['name']}: {$review['title']}{$review['content']}",
'color' => ($review['rating'] >= 4) ? 'good' : (($review['rating'] == 3) ? 'warning' : 'danger'),
'pretext' => "{$ratingText} Review for {$review['application']['version']} from <{$review['author']['uri']}|{$review['author']['name']} ({$review['country']})>",
'fields' => [
[
'title' => $review['title'],
'value' => $review['content']
]
]
])->send();
}

$this->storage->set("r{$review['id']}", 1);
} catch (Exception $e) {
if ($this->logger) {
$this->logger->error('Reviewer: exception while sending reviews', [ 'exception' => $e ]);
$this->logger->error('Reviewer: exception while sending reviews', ['exception' => $e]);
}
}
}
Expand All @@ -273,4 +316,4 @@ public function start()
$this->logger->debug('Sent ' . count($reviews) . ' reviews');
}
}
}
}

0 comments on commit f3dbdfa

Please sign in to comment.