[AppleAppStoreBridge] Add new bridge (#1316)
This bridge allows you to follow iOS/iPad application updates directly over RSS. This allows you to get notified of an application update even if you don't have a iDevice. This may be useful in cases where you want to be notified of a competitor's application for eg. I built this after I got tired of waiting for WhatsApp to push their security release on iOS. It shows up on the AppStore 7 days later
This commit is contained in:
parent
3bc8c9468a
commit
7f35fc9f6b
1 changed files with 149 additions and 0 deletions
149
bridges/AppleAppStoreBridge.php
Normal file
149
bridges/AppleAppStoreBridge.php
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class AppleAppStoreBridge extends BridgeAbstract {
|
||||||
|
|
||||||
|
const MAINTAINER = 'captn3m0';
|
||||||
|
const NAME = 'Apple App Store';
|
||||||
|
const URI = 'https://apps.apple.com/';
|
||||||
|
const CACHE_TIMEOUT = 3600; // 1h
|
||||||
|
const DESCRIPTION = 'Returns version updates for a specific application';
|
||||||
|
|
||||||
|
const PARAMETERS = array(array(
|
||||||
|
'id' => array(
|
||||||
|
'name' => 'Application ID',
|
||||||
|
'required' => true,
|
||||||
|
'exampleValue' => '310633997'
|
||||||
|
),
|
||||||
|
'p' => array(
|
||||||
|
'name' => 'Platform',
|
||||||
|
'type' => 'list',
|
||||||
|
'values' => array(
|
||||||
|
'iPad' => 'ipad',
|
||||||
|
'iPhone' => 'iphone',
|
||||||
|
'Mac' => 'mac',
|
||||||
|
|
||||||
|
// The following 2 are present in responses
|
||||||
|
// but not yet tested
|
||||||
|
'Web' => 'web',
|
||||||
|
'Apple TV' => 'appletv',
|
||||||
|
),
|
||||||
|
'defaultValue' => 'iphone',
|
||||||
|
),
|
||||||
|
'country' => array(
|
||||||
|
'name' => 'Store Country',
|
||||||
|
'type' => 'list',
|
||||||
|
'values' => array(
|
||||||
|
'US' => 'US',
|
||||||
|
'India' => 'IN',
|
||||||
|
'Canada' => 'CA'
|
||||||
|
),
|
||||||
|
'defaultValue' => 'US',
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
const PLATFORM_MAPPING = array(
|
||||||
|
'iphone' => 'ios',
|
||||||
|
'ipad' => 'ios',
|
||||||
|
);
|
||||||
|
|
||||||
|
private function makeHtmlUrl($id, $country){
|
||||||
|
return 'https://apps.apple.com/' . $country . '/app/id' . $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function makeJsonUrl($id, $platform, $country){
|
||||||
|
return "https://amp-api.apps.apple.com/v1/catalog/$country/apps/$id?platform=$platform&extend=versionHistory";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(){
|
||||||
|
if (isset($this->name)) {
|
||||||
|
return $this->name . ' - AppStore Updates';
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case of some platforms, the data is present in the initial response
|
||||||
|
*/
|
||||||
|
private function getDataFromShoebox($id, $platform, $country){
|
||||||
|
$uri = $this->makeHtmlUrl($id, $country);
|
||||||
|
$html = getSimpleHTMLDOMCached($uri, 3600);
|
||||||
|
$script = $html->find('script[id="shoebox-ember-data-store"]', 0);
|
||||||
|
|
||||||
|
$json = json_decode($script->innertext, true);
|
||||||
|
return $json['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getJWTToken($id, $platform, $country){
|
||||||
|
$uri = $this->makeHtmlUrl($id, $country);
|
||||||
|
|
||||||
|
$html = getSimpleHTMLDOMCached($uri, 3600);
|
||||||
|
|
||||||
|
$meta = $html->find('meta[name="web-experience-app/config/environment"]', 0);
|
||||||
|
|
||||||
|
$json = urldecode($meta->content);
|
||||||
|
|
||||||
|
$json = json_decode($json);
|
||||||
|
|
||||||
|
return $json->MEDIA_API->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAppData($id, $platform, $country, $token){
|
||||||
|
$uri = $this->makeJsonUrl($id, $platform, $country);
|
||||||
|
|
||||||
|
$headers = array(
|
||||||
|
"Authorization: Bearer $token",
|
||||||
|
);
|
||||||
|
|
||||||
|
$json = json_decode(getContents($uri, $headers), true);
|
||||||
|
|
||||||
|
return $json['data'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the version history from the data received
|
||||||
|
* @return array list of versions with details on each element
|
||||||
|
*/
|
||||||
|
private function getVersionHistory($data, $platform){
|
||||||
|
switch($platform) {
|
||||||
|
case 'mac':
|
||||||
|
return $data['relationships']['platforms']['data'][0]['attributes']['versionHistory'];
|
||||||
|
default:
|
||||||
|
$os = self::PLATFORM_MAPPING[$platform];
|
||||||
|
return $data['attributes']['platformAttributes'][$os]['versionHistory'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function collectData() {
|
||||||
|
$id = $this->getInput('id');
|
||||||
|
$country = $this->getInput('country');
|
||||||
|
$platform = $this->getInput('p');
|
||||||
|
|
||||||
|
switch ($platform) {
|
||||||
|
case 'mac':
|
||||||
|
$data = $this->getDataFromShoebox($id, $platform, $country);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$token = $this->getJWTToken($id, $platform, $country);
|
||||||
|
$data = $this->getAppData($id, $platform, $country, $token);
|
||||||
|
}
|
||||||
|
|
||||||
|
$versionHistory = $this->getVersionHistory($data, $platform);
|
||||||
|
$name = $this->name = $data['attributes']['name'];
|
||||||
|
$author = $data['attributes']['artistName'];
|
||||||
|
|
||||||
|
foreach ($versionHistory as $row) {
|
||||||
|
$item = array();
|
||||||
|
|
||||||
|
$item['content'] = nl2br($row['releaseNotes']);
|
||||||
|
$item['title'] = $name . ' - ' . $row['versionDisplay'];
|
||||||
|
$item['timestamp'] = $row['releaseDate'];
|
||||||
|
$item['author'] = $author;
|
||||||
|
|
||||||
|
$item['uri'] = $this->makeHtmlUrl($id, $country);
|
||||||
|
|
||||||
|
$this->items[] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue