diff options
Diffstat (limited to 'bridges/FDroidRepoBridge.php')
-rw-r--r-- | bridges/FDroidRepoBridge.php | 370 |
1 files changed, 193 insertions, 177 deletions
diff --git a/bridges/FDroidRepoBridge.php b/bridges/FDroidRepoBridge.php index c26bbacf..74147310 100644 --- a/bridges/FDroidRepoBridge.php +++ b/bridges/FDroidRepoBridge.php @@ -1,150 +1,162 @@ <?php -class FDroidRepoBridge extends BridgeAbstract { - const NAME = 'F-Droid Repository Bridge'; - const URI = 'https://f-droid.org/'; - const DESCRIPTION = 'Query any F-Droid Repository for its latest updates.'; - - const ITEM_LIMIT = 50; - - const PARAMETERS = array( - 'global' => array( - 'url' => array( - 'name' => 'Repository URL', - 'title' => 'Usually ends with /repo/', - 'required' => true, - 'exampleValue' => 'https://srv.tt-rss.org/fdroid/repo' - ) - ), - 'Latest Updates' => array( - 'sorting' => array( - 'name' => 'Sort By', - 'type' => 'list', - 'values' => array( - 'Latest added apps' => 'added', - 'Latest updated apps' => 'lastUpdated' - ) - ), - 'locale' => array( - 'name' => 'Locale', - 'defaultValue' => 'en-US' - ) - ), - 'Follow Package' => array( - 'package' => array( - 'name' => 'Package Identifier', - 'required' => true, - 'exampleValue' => 'org.fox.ttrss' - ) - ) - ); - - // Stores repo information - private $repo; - - public function getURI() { - if (empty($this->queriedContext)) - return parent::getURI(); - - $url = rtrim($this->GetInput('url'), '/'); - return strstr($url, '?', true) ?: $url; - } - - public function getName() { - if (empty($this->queriedContext)) - return parent::getName(); - - $name = $this->repo['repo']['name']; - switch($this->queriedContext) { - case 'Latest Updates': - return $name; - case 'Follow Package': - return $this->getInput('package') . ' - ' . $name; - default: - returnServerError('Unimplemented Context (getName)'); - } - } - - public function collectData() { - $this->repo = $this->getRepo(); - switch($this->queriedContext) { - case 'Latest Updates': - $this->getAllUpdates(); - break; - case 'Follow Package': - $this->getPackage($this->getInput('package')); - break; - default: - returnServerError('Unimplemented Context (collectData)'); - } - } - - private function getRepo() { - $url = $this->getURI(); - - // Get repo information (only available as JAR) - $jar = getContents($url . '/index-v1.jar'); - $jar_loc = tempnam(sys_get_temp_dir(), ''); - file_put_contents($jar_loc, $jar); - - // JAR files are specially formatted ZIP files - $jar = new ZipArchive; - if ($jar->open($jar_loc) !== true) { - returnServerError('Failed to extract archive'); - } - - // Get file pointer to the relevant JSON inside - $fp = $jar->getStream('index-v1.json'); - if (!$fp) { - returnServerError('Failed to get file pointer'); - } - - $data = json_decode(stream_get_contents($fp), true); - fclose($fp); - $jar->close(); - return $data; - } - - private function getAllUpdates() { - $apps = $this->repo['apps']; - usort($apps, function($a, $b) { - return $b[$this->getInput('sorting')] <=> $a[$this->getInput('sorting')]; - }); - $apps = array_slice($apps, 0, self::ITEM_LIMIT); - foreach($apps as $app) { - $latest = reset($this->repo['packages'][$app['packageName']]); - - if (isset($app['localized'])) { - // Try provided locale, then en-US, then any - $lang = $app['localized']; - $lang = $lang[$this->getInput('locale')] ?? $lang['en-US'] ?? reset($lang); - } else - $lang = array(); - - $item = array(); - $item['uri'] = $this->getURI() . '/' . $latest['apkName']; - $item['title'] = $lang['name'] ?? $app['packageName']; - $item['title'] .= ' ' . $latest['versionName']; - $item['timestamp'] = date(DateTime::ISO8601, (int) ($app['lastUpdated'] / 1000)); - if (isset($app['authorName'])) - $item['author'] = $app['authorName']; - if (isset($app['categories'])) - $item['categories'] = $app['categories']; - - // Adding Content - $icon = $app['icon'] ?? ''; - if (!empty($icon)) { - $icon = $this->getURI() . '/icons-320/' . $icon; - $item['enclosures'] = array($icon); - $icon = '<img src="' . $icon . '">'; - } - $summary = $lang['summary'] ?? $app['summary'] ?? ''; - $description = markdownToHtml(trim($lang['description'] ?? $app['description'] ?? 'None')); - $whatsNew = markdownToHtml(trim($lang['whatsNew'] ?? 'None')); - $website = $this->link($lang['webSite'] ?? $app['webSite'] ?? $app['authorWebSite'] ?? null); - $source = $this->link($app['sourceCode'] ?? null); - $issueTracker = $this->link($app['issueTracker'] ?? null); - $license = $app['license'] ?? 'None'; - $item['content'] = <<<EOD + +class FDroidRepoBridge extends BridgeAbstract +{ + const NAME = 'F-Droid Repository Bridge'; + const URI = 'https://f-droid.org/'; + const DESCRIPTION = 'Query any F-Droid Repository for its latest updates.'; + + const ITEM_LIMIT = 50; + + const PARAMETERS = [ + 'global' => [ + 'url' => [ + 'name' => 'Repository URL', + 'title' => 'Usually ends with /repo/', + 'required' => true, + 'exampleValue' => 'https://srv.tt-rss.org/fdroid/repo' + ] + ], + 'Latest Updates' => [ + 'sorting' => [ + 'name' => 'Sort By', + 'type' => 'list', + 'values' => [ + 'Latest added apps' => 'added', + 'Latest updated apps' => 'lastUpdated' + ] + ], + 'locale' => [ + 'name' => 'Locale', + 'defaultValue' => 'en-US' + ] + ], + 'Follow Package' => [ + 'package' => [ + 'name' => 'Package Identifier', + 'required' => true, + 'exampleValue' => 'org.fox.ttrss' + ] + ] + ]; + + // Stores repo information + private $repo; + + public function getURI() + { + if (empty($this->queriedContext)) { + return parent::getURI(); + } + + $url = rtrim($this->GetInput('url'), '/'); + return strstr($url, '?', true) ?: $url; + } + + public function getName() + { + if (empty($this->queriedContext)) { + return parent::getName(); + } + + $name = $this->repo['repo']['name']; + switch ($this->queriedContext) { + case 'Latest Updates': + return $name; + case 'Follow Package': + return $this->getInput('package') . ' - ' . $name; + default: + returnServerError('Unimplemented Context (getName)'); + } + } + + public function collectData() + { + $this->repo = $this->getRepo(); + switch ($this->queriedContext) { + case 'Latest Updates': + $this->getAllUpdates(); + break; + case 'Follow Package': + $this->getPackage($this->getInput('package')); + break; + default: + returnServerError('Unimplemented Context (collectData)'); + } + } + + private function getRepo() + { + $url = $this->getURI(); + + // Get repo information (only available as JAR) + $jar = getContents($url . '/index-v1.jar'); + $jar_loc = tempnam(sys_get_temp_dir(), ''); + file_put_contents($jar_loc, $jar); + + // JAR files are specially formatted ZIP files + $jar = new ZipArchive(); + if ($jar->open($jar_loc) !== true) { + returnServerError('Failed to extract archive'); + } + + // Get file pointer to the relevant JSON inside + $fp = $jar->getStream('index-v1.json'); + if (!$fp) { + returnServerError('Failed to get file pointer'); + } + + $data = json_decode(stream_get_contents($fp), true); + fclose($fp); + $jar->close(); + return $data; + } + + private function getAllUpdates() + { + $apps = $this->repo['apps']; + usort($apps, function ($a, $b) { + return $b[$this->getInput('sorting')] <=> $a[$this->getInput('sorting')]; + }); + $apps = array_slice($apps, 0, self::ITEM_LIMIT); + foreach ($apps as $app) { + $latest = reset($this->repo['packages'][$app['packageName']]); + + if (isset($app['localized'])) { + // Try provided locale, then en-US, then any + $lang = $app['localized']; + $lang = $lang[$this->getInput('locale')] ?? $lang['en-US'] ?? reset($lang); + } else { + $lang = []; + } + + $item = []; + $item['uri'] = $this->getURI() . '/' . $latest['apkName']; + $item['title'] = $lang['name'] ?? $app['packageName']; + $item['title'] .= ' ' . $latest['versionName']; + $item['timestamp'] = date(DateTime::ISO8601, (int) ($app['lastUpdated'] / 1000)); + if (isset($app['authorName'])) { + $item['author'] = $app['authorName']; + } + if (isset($app['categories'])) { + $item['categories'] = $app['categories']; + } + + // Adding Content + $icon = $app['icon'] ?? ''; + if (!empty($icon)) { + $icon = $this->getURI() . '/icons-320/' . $icon; + $item['enclosures'] = [$icon]; + $icon = '<img src="' . $icon . '">'; + } + $summary = $lang['summary'] ?? $app['summary'] ?? ''; + $description = markdownToHtml(trim($lang['description'] ?? $app['description'] ?? 'None')); + $whatsNew = markdownToHtml(trim($lang['whatsNew'] ?? 'None')); + $website = $this->link($lang['webSite'] ?? $app['webSite'] ?? $app['authorWebSite'] ?? null); + $source = $this->link($app['sourceCode'] ?? null); + $issueTracker = $this->link($app['issueTracker'] ?? null); + $license = $app['license'] ?? 'None'; + $item['content'] = <<<EOD {$icon} <p>{$summary}</p> <h1>Description</h1> @@ -157,40 +169,44 @@ class FDroidRepoBridge extends BridgeAbstract { <p>Issue Tracker: {$issueTracker}</p> <p>license: {$app['license']}</p> EOD; - $this->items[] = $item; - } - } - - private function getPackage($package) { - if (!isset($this->repo['packages'][$package])) { - returnClientError('Invalid Package Name'); - } - $package = $this->repo['packages'][$package]; - - $count = self::ITEM_LIMIT; - foreach($package as $version) { - $item = array(); - $item['uri'] = $this->getURI() . '/' . $version['apkName']; - $item['title'] = $version['versionName']; - $item['timestamp'] = date(DateTime::ISO8601, (int) ($version['added'] / 1000)); - $item['uid'] = $version['versionCode']; - $size = round($version['size'] / 1048576, 1); // Bytes -> MB - $sdk_link = 'https://developer.android.com/studio/releases/platforms'; - $item['content'] = <<<EOD + $this->items[] = $item; + } + } + + private function getPackage($package) + { + if (!isset($this->repo['packages'][$package])) { + returnClientError('Invalid Package Name'); + } + $package = $this->repo['packages'][$package]; + + $count = self::ITEM_LIMIT; + foreach ($package as $version) { + $item = []; + $item['uri'] = $this->getURI() . '/' . $version['apkName']; + $item['title'] = $version['versionName']; + $item['timestamp'] = date(DateTime::ISO8601, (int) ($version['added'] / 1000)); + $item['uid'] = $version['versionCode']; + $size = round($version['size'] / 1048576, 1); // Bytes -> MB + $sdk_link = 'https://developer.android.com/studio/releases/platforms'; + $item['content'] = <<<EOD <p>size: {$size}MB</p> <p>Minimum SDK: {$version['minSdkVersion']} (<a href="{$sdk_link}">SDK to Android Version List</a>)</p> <p>hash ({$version['hashType']}): {$version['hash']}</p> EOD; - $this->items[] = $item; - if (--$count <= 0) - break; - } - } - - private function link($url) { - if (empty($url)) - return null; - return '<a href="' . $url . '">' . $url . '</a>'; - } + $this->items[] = $item; + if (--$count <= 0) { + break; + } + } + } + + private function link($url) + { + if (empty($url)) { + return null; + } + return '<a href="' . $url . '">' . $url . '</a>'; + } } |