Skip to content

Commit b2a5357

Browse files
authored
Merge pull request #21 from IzzySoft/privacy
add method parsePrivacy() to obtain Data Safety details for a given app
2 parents e809f5a + 9db1cef commit b2a5357

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

google-play.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,71 @@ public function parseSearch($query) {
408408
}
409409
else return ['success'=>0, 'message'=>$this->lastError, 'data'=>$data];
410410
}
411+
412+
/* Obtain Data Safety details for a given app
413+
* @method public parsePrivacy
414+
* @param string packageName identifier for the app, e.g. 'com.example.app'
415+
* @param optional string lang language for translations. Should be ISO 639-1 two-letter code. Default: en
416+
* @return array privacy details on the app on success, details on the error otherwise
417+
*/
418+
public function parsePrivacy($packageName, $lang='en') {
419+
$link = sprintf('https://play.google.com/store/apps/datasafety?id=%s&hl=%s', $packageName, $lang);
420+
if ( $this->input = @file_get_contents($link) ) {
421+
preg_match("!HTTP/1\.\d\s+(\d{3})\s+(.+)$!i", $http_response_header[0], $match);
422+
$response_code = $match[1];
423+
switch ($response_code) {
424+
case "200" : // HTTP/1.0 200 OK
425+
break;
426+
case "400" : // echo "! No XHR for '$pkg'\n";
427+
case "404" : // app no longer on play
428+
default:
429+
$this->lastError = $http_response_header[0];
430+
return ['success'=>0, 'values'=>[], 'message'=>$http_response_header[0]];
431+
break;
432+
}
433+
} else { // network error (e.g. "failed to open stream: Connection timed out")
434+
$this->lastError = 'network error';
435+
return ['success'=>0, 'values'=>[], 'message'=>'network error'];
436+
}
437+
438+
$doc = new DOMDocument();
439+
@$doc->loadHTML($this->input);
440+
$xp = new DOMXPath($doc);
441+
442+
$nlh = $xp->query("//div[@class='Mf2Txd']/h2"); // node list of headers
443+
if ($this->debug) echo "Privacy sections: ".$nlh->length."\n";
444+
445+
$sections = [];
446+
foreach($nlh as $section) {
447+
$sname = trim ($section->nodeValue);
448+
$node = $section->nextSibling;
449+
$desc = ''; $extras = [];
450+
switch ( $node->getAttribute('class') ) {
451+
case 'ivTO9c': $desc = $node->firstChild->textContent; break;
452+
case 'XgPdwe':
453+
$desc = 'see extras';
454+
foreach ($node->childNodes as $child) {
455+
$ex = $child->firstChild->nextSibling->firstChild; // the extra detail's header
456+
$eh = $ex->nodeValue;
457+
$ex = $ex->nextSibling; // the extra's details
458+
$ed = $ex->nodeValue;
459+
$extras[] = ['name'=>$eh, 'desc'=>$ed];
460+
}
461+
break;
462+
default: if ($this->debug) echo "Got unknown class '". strtolower($node->getAttribute('class'))."' for section description\n"; break;
463+
}
464+
$node = $node->nextSibling;
465+
if ( empty($extras) ) {
466+
foreach ($node->childNodes as $child) {
467+
$ex = $child->firstChild->firstChild->firstChild->firstChild->firstChild->nextSibling->firstChild; // the extra detail's header
468+
$eh = $ex->nodeValue;
469+
$ex = $ex->nextSibling; // the extra's details
470+
$ed = $ex->nodeValue;
471+
$extras[] = ['name'=>$eh, 'desc'=>$ed];
472+
}
473+
}
474+
$sections[] = ['name'=>$sname, 'desc'=>$desc, 'extras' => $extras];
475+
}
476+
return ['success'=>1, 'values'=>$sections, 'message'=>''];
477+
}
411478
}

0 commit comments

Comments
 (0)