diff --git a/bridges/AppleAppStoreBridge.php b/bridges/AppleAppStoreBridge.php new file mode 100644 index 00000000..c1403fe0 --- /dev/null +++ b/bridges/AppleAppStoreBridge.php @@ -0,0 +1,149 @@ + 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; + } + } +}