summaryrefslogtreecommitdiff
path: root/bridges/AppleAppStoreBridge.php
blob: c1403fe04a61d7a5a4b4e7768430968632ef9a6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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;
		}
	}
}