a02dad7a27fe7031f0a2906f7d86015acf536614
[stouyapi.git] / bin / import-game-data.php
1 #!/usr/bin/env php
2 <?php
3 /**
4  * Import games from a OUYA game data repository
5  *
6  * @link https://github.com/cweiske/ouya-game-data/
7  * @author Christian Weiske <cweiske@cweiske.de>
8  */
9 if (!isset($argv[1])) {
10     error('Pass the path to a directory with game data json files');
11 }
12 $gameDataDir = $argv[1];
13 if (!is_dir($gameDataDir)) {
14     error('Given path is not a directory: ' . $gameDataDir);
15 }
16
17 $wwwDir = __DIR__ . '/../www/';
18
19 $gameFiles = glob($gameDataDir . '/*.json');
20 $games = [];
21 foreach ($gameFiles as $gameFile) {
22     $game = json_decode(file_get_contents($gameFile));
23     if ($game === null) {
24         error('JSON invalid at ' . $gameFile);
25     }
26     addMissingGameProperties($game);
27     //FIXME: add missing properties?
28     $games[$game->package] = $game;
29     writeJson(
30         'api/v1/apps/' . $game->package,
31         buildApps($game)
32     );
33     writeJson(
34         'api/v1/details-data/' . $game->package . '.json',
35         buildDetails($game)
36     );
37     //exit(2);
38     
39 }
40
41 //FIXME: build discover section
42
43 /**
44  * Build api/v1/apps/$package
45  */
46 function buildApps($game)
47 {
48     $latestRelease = getLatestRelease($game);
49     
50     // http://cweiske.de/ouya-store-api-docs.htm#get-https-devs-ouya-tv-api-v1-apps-xxx
51     return [
52         'app' => [
53             'uuid'          => $game->uuid,
54             'title'         => $game->title,
55             'overview'      => $game->overview,
56             'description'   => $game->description,
57             'gamerNumbers'  => $game->players,
58             'genres'        => $game->genres,
59             
60             'website'       => $game->website,
61             'contentRating' => $game->contentRating,
62             'premium'       => $game->premium,
63             'firstPublishedAt' => $game->firstPublishedAt,
64             
65             'likeCount'     => $game->rating->likeCount,
66             'ratingAverage' => $game->rating->average,
67             'ratingCount'   => $game->rating->count,
68
69             'versionNumber' => $latestRelease->name,
70             'latestVersion' => $latestRelease->uuid,
71             'md5sum'        => $latestRelease->md5sum,
72             'apkFileSize'   => $latestRelease->size,
73             'publishedAt'   => $latestRelease->date,
74             'publicSize'    => $latestRelease->publicSize,
75             'nativeSize'    => $latestRelease->nativeSize,
76
77             'mainImageFullUrl' => $game->media->large,
78             'videoUrl'         => $game->media->video,
79             'filepickerScreenshots' => $game->media->screenshots,
80             'mobileAppIcon'    => null,
81
82             'developer'           => $game->developer->name,
83             'supportEmailAddress' => $game->developer->supportEmail,
84             'supportPhone'        => $game->developer->supportPhone,
85             'founder'             => $game->developer->founder,
86
87             'promotedProduct' => null,
88         ],
89     ];
90 }
91
92 /**
93  * Build /app/v1/details?app=org.example.game
94  */
95 function buildDetails($game)
96 {
97     $latestRelease = getLatestRelease($game);
98
99     $mediaTiles = [];
100     if ($game->media->large) {
101         $mediaTiles[] = [
102             'type' => 'image',
103             'urls' => [
104                 'thumbnail' => $game->media->large,
105                 'full'      => $game->media->large,
106             ],
107             'fp_url' => $game->media->large,
108         ];
109     }
110     if ($game->media->video) {
111         $mediaTiles[] = [
112             'type' => 'video',
113             'url'  => $game->media->video,
114         ];
115     }
116     foreach ($game->media->screenshots as $screenshot) {
117         $mediaTiles[] = [
118             'type' => 'image',
119             'urls' => [
120                 'thumbnail' => $screenshot,
121                 'full'      => $screenshot,
122             ],
123             'fp_url' => $screenshot,
124         ];
125     }
126     
127     // http://cweiske.de/ouya-store-api-docs.htm#get-https-devs-ouya-tv-api-v1-details
128     return [
129         'type'             => 'Game',
130         'title'            => $game->title,
131         'description'      => $game->description,
132         'gamerNumbers'     => $game->players,
133         'genres'           => $game->genres,
134
135         'suggestedAge'     => $game->contentRating,
136         'premium'          => $game->premium,
137         'inAppPurchases'   => $game->inAppPurchases,
138         'firstPublishedAt' => strtotime($game->firstPublishedAt),
139         'ccUrl'            => null,
140
141         'rating' => [
142             'count'   => $game->rating->count,
143             'average' => $game->rating->average,
144         ],
145
146         'apk' => [
147             'fileSize'    => $latestRelease->size,
148             'nativeSize'  => $latestRelease->nativeSize,
149             'publicSize'  => $latestRelease->publicSize,
150             'md5sum'      => $latestRelease->md5sum,
151             'filename'    => 'FIXME',
152             'errors'      => '',
153             'package'     => $game->package,
154             'versionCode' => $latestRelease->versionCode,
155             'state'       => 'complete',
156         ],
157
158         'version' => [
159             'number'      => $latestRelease->name,
160             'publishedAt' => strtotime($latestRelease->date),
161             'uuid'        => $latestRelease->uuid,
162         ],
163
164         'developer' => [
165             'name'    => $game->developer->name,
166             'founder' => $game->developer->founder,
167         ],
168
169         'metaData' => [
170             'key:rating.average',
171             'key:developer.name',
172             'key:suggestedAge',
173             number_format($latestRelease->size / 1024 / 1024, 2, '.', '') . ' MiB',
174         ],
175
176         'tileImage'     => $game->media->discover,
177         'mediaTiles'    => $mediaTiles,
178         'mobileAppIcon' => null,
179         'heroImage'     => [
180             'url' => null,
181         ],
182         
183         'promotedProduct' => null,
184     ];             
185 }
186
187 function addMissingGameProperties($game)
188 {
189     if (!isset($game->overview)) {
190         $game->overview = null;
191     }
192     if (!isset($game->description)) {
193         $game->description = '';
194     }
195     if (!isset($game->players)) {
196         $game->players = [1];
197     }
198     if (!isset($game->genres)) {
199         $game->genres = ['Unsorted'];
200     }
201     if (!isset($game->website)) {
202         $game->website = null;
203     }
204     if (!isset($game->contentRating)) {
205         $game->contentRating = 'Everyone';
206     }
207     if (!isset($game->premium)) {
208         $game->premium = false;
209     }
210     if (!isset($game->firstPublishedAt)) {
211         $game->firstPublishedAt = gmdate('c');
212     }
213     
214     if (!isset($game->rating)) {
215         $game->rating = new stdClass();
216     }
217     if (!isset($game->rating->likeCount)) {
218         $game->rating->likeCount = 0;
219     }
220     if (!isset($game->rating->average)) {
221         $game->rating->average = 0;
222     }
223     if (!isset($game->rating->count)) {
224         $game->rating->count = 0;
225     }
226
227     foreach ($game->releases as $release) {
228         if (!isset($release->publicSize)) {
229             $release->publicSize = 0;
230         }
231         if (!isset($release->nativeSize)) {
232             $release->nativeSize = 0;
233         }
234     }
235
236     if (!isset($game->media->video)) {
237         $game->media->video = null;
238     }
239     if (!isset($game->media->screenshots)) {
240         $game->media->screenshots = [];
241     }
242     if (!isset($game->developer->uuid)) {
243         $game->developer->uuid = null;
244     }
245     if (!isset($game->developer->name)) {
246         $game->developer->name = 'unknown';
247     }
248     if (!isset($game->developer->supportEmail)) {
249         $game->developer->supportEmail = null;
250     }
251     if (!isset($game->developer->supportPhone)) {
252         $game->developer->supportPhone = null;
253     }
254     if (!isset($game->developer->founder)) {
255         $game->developer->founder = false;
256     }
257 }
258
259 function getLatestRelease($game)
260 {
261     $latestRelease = null;
262     foreach ($game->releases as $release) {
263         if ($release->latest ?? false) {
264             $latestRelease = $release;
265             break;
266         }
267     }
268     if ($latestRelease === null) {
269         error('No latest release for ' . $game->package);
270     }
271     return $latestRelease;
272 }
273
274 function writeJson($path, $data)
275 {
276     global $wwwDir;
277     $fullPath = $wwwDir . $path;
278     $dir = dirname($fullPath);
279     if (!is_dir($dir)) {
280         mkdir($dir, 0777, true);
281     }
282     file_put_contents(
283         $fullPath,
284         json_encode($data, JSON_PRETTY_PRINT) . "\n"
285     );
286 }
287
288 function error($msg)
289 {
290     fwrite(STDERR, $msg . "\n");
291     exit(1);
292 }
293 ?>