From fdb1a77ac08ef09eceb5300fc9c883f473cefbba Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Thu, 31 Mar 2022 13:58:26 -0400 Subject: [PATCH 1/5] [MangaDexBridge] Add new bridge --- bridges/MangaDexBridge.php | 156 +++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 bridges/MangaDexBridge.php diff --git a/bridges/MangaDexBridge.php b/bridges/MangaDexBridge.php new file mode 100644 index 00000000000..2a01e73b8ef --- /dev/null +++ b/bridges/MangaDexBridge.php @@ -0,0 +1,156 @@ + array( + 'limit' => array( + 'name' => 'Item Limit', + 'type' => 'number', + 'defaultValue' => 10, + 'required' => true + ), + 'lang' => array( + 'name' => 'Chapter Languages', + 'title' => 'two-letter language codes, separated by just ","', + 'defaultValue' => 'en', + 'required' => false + ), + ), + 'Title Chapters' => array( + 'url' => array( + 'name' => 'URL to title page', + 'exampleValue' => 'https://mangadex.org/title/f9c33607-9180-4ba6-b85c-e4b5faee7192/official-test-manga', + 'required' => true + ) + ) + ); + + const TITLE_REGEX = '#title/(?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})#'; + + protected $feedName = ''; + + protected function buildArrayQuery($name, $array) { + $query = ''; + foreach($array as $item) { + $query .= '&' . $name . '=' . $item; + } + return $query; + } + + protected function getAPI() { + $params = array( + 'limit' => $this->getInput('limit') + ); + + $array_params = array(); + if (!empty($this->getInput('lang'))) { + $array_params['translatedLanguage[]'] = explode(',', $this->getInput('lang')); + } + + switch($this->queriedContext) { + case 'Title Chapters': + preg_match(self::TITLE_REGEX, $this->getInput('url'), $matches) + or returnClientError('Invalid URL Parameter'); + $params['order[updatedAt]'] = 'desc'; + $array_params['includes[]'] = array('manga', 'scanlation_group', 'user'); + $uri = self::API_ROOT . 'manga/' . $matches['uuid'] . '/feed'; + break; + default: + returnServerError('Unimplemented Context (getAPI)'); + } + + $uri .= '?' . http_build_query($params); + + // Arrays are passed as repeated keys to MangaDex + // This cannot be handled by http_build_query + foreach($array_params as $name => $array_param) { + $uri .= $this->buildArrayQuery($name, $array_param); + } + + return $uri; + + } + + public function getName() { + switch($this->queriedContext) { + case 'Title Chapters': + return $this->feedName . ' Chapters'; + default: + return parent::getName(); + } + } + + public function collectData() { + $api_uri = $this->getApi(); + $header = array( + 'Content-Type: application/json' + ); + $content = json_decode(getContents($api_uri, $header), true); + if ($content['result'] == 'ok') { + $content = $content['data']; + } else { + returnServerError('Could not retrieve API results'); + } + + switch($this->queriedContext) { + case 'Title Chapters': + $this->getChapters($content); + break; + default: + returnServerError('Unimplemented Context (collectData)'); + } + } + + protected function getChapters($content) { + foreach($content as $chapter) { + $item = array(); + $item['uid'] = $chapter['id']; + $item['uri'] = self::URI . 'chapter/' . $chapter['id']; + + // Preceding space accounts for Manga title added later + $item['title'] = ' Chapter ' . $chapter['attributes']['chapter']; + if (!empty($chapter['attributes']['title'])) { + $item['title'] .= ' - ' . $chapter['attributes']['title']; + } + $item['title'] .= ' [' . $chapter['attributes']['translatedLanguage'] . ']'; + + $item['timestamp'] = $chapter['attributes']['updatedAt']; + + $groups = array(); + $users = array(); + foreach($chapter['relationships'] as $rel) { + switch($rel['type']) { + case 'scanlation_group': + $groups[] = $rel['attributes']['name']; + break; + case 'manga': + if (empty($this->feedName)) { + $this->feedName = reset($rel['attributes']['title']); + } + $item['title'] = reset($rel['attributes']['title']) . $item['title']; + break; + case 'user': + if (isset($item['author'])) { + $users[] = $rel['attributes']['username']; + } else { + $item['author'] = $rel['attributes']['username']; + } + break; + } + } + $item['content'] = 'Groups: ' . + (empty($groups) ? 'No Group' : implode(', ', $groups)); + if (!empty($users)) { + $item['content'] .= '
Other Users: ' . implode(', ', $users); + } + + $this->items[] = $item; + } + } +} From a0dbe545d6bd53e781457db18847544e1ae23eaf Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Thu, 31 Mar 2022 14:55:56 -0400 Subject: [PATCH 2/5] [MangaDexBridge] Fix review comments --- bridges/MangaDexBridge.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridges/MangaDexBridge.php b/bridges/MangaDexBridge.php index 2a01e73b8ef..811342e0015 100644 --- a/bridges/MangaDexBridge.php +++ b/bridges/MangaDexBridge.php @@ -5,7 +5,6 @@ class MangaDexBridge extends BridgeAbstract { const URI = 'https://mangadex.org/'; const API_ROOT = 'https://api.mangadex.org/'; const DESCRIPTION = 'Returns MangaDex items using the API'; - const CACHE_TIMEOUT = 0; const PARAMETERS = array( 'global' => array( @@ -17,8 +16,9 @@ class MangaDexBridge extends BridgeAbstract { ), 'lang' => array( 'name' => 'Chapter Languages', - 'title' => 'two-letter language codes, separated by just ","', + 'title' => 'comma-separated, two-letter language codes (example "en,jp")', 'defaultValue' => 'en', + 'exampleValue' => 'en,jp', 'required' => false ), ), From c56e4158b900c14a3f03365f5a5275c10a52fd31 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Thu, 31 Mar 2022 15:47:27 -0400 Subject: [PATCH 3/5] [MangaDexBridge] Fix bug with unavailable chapters --- bridges/MangaDexBridge.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bridges/MangaDexBridge.php b/bridges/MangaDexBridge.php index 811342e0015..8ffdb675b81 100644 --- a/bridges/MangaDexBridge.php +++ b/bridges/MangaDexBridge.php @@ -27,6 +27,11 @@ class MangaDexBridge extends BridgeAbstract { 'name' => 'URL to title page', 'exampleValue' => 'https://mangadex.org/title/f9c33607-9180-4ba6-b85c-e4b5faee7192/official-test-manga', 'required' => true + ), + 'external' => array( + 'name' => 'Allow external feed items', + 'type' => 'checkbox', + 'title' => 'Some chapters are inaccessible or only available on an external site. Include these?' ) ) ); @@ -58,6 +63,9 @@ protected function getAPI() { preg_match(self::TITLE_REGEX, $this->getInput('url'), $matches) or returnClientError('Invalid URL Parameter'); $params['order[updatedAt]'] = 'desc'; + if (!$this->getInput('external')) { + $params['includeFutureUpdates'] = '0'; + } $array_params['includes[]'] = array('manga', 'scanlation_group', 'user'); $uri = self::API_ROOT . 'manga/' . $matches['uuid'] . '/feed'; break; From c8af80454710ba12be5a759cce70f6d7566ace23 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Thu, 31 Mar 2022 16:02:38 -0400 Subject: [PATCH 4/5] Add getURI to lead to title page --- bridges/MangaDexBridge.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bridges/MangaDexBridge.php b/bridges/MangaDexBridge.php index 8ffdb675b81..d0cfdce6718 100644 --- a/bridges/MangaDexBridge.php +++ b/bridges/MangaDexBridge.php @@ -39,6 +39,7 @@ class MangaDexBridge extends BridgeAbstract { const TITLE_REGEX = '#title/(?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})#'; protected $feedName = ''; + protected $feedURI = ''; protected function buildArrayQuery($name, $array) { $query = ''; @@ -62,6 +63,7 @@ protected function getAPI() { case 'Title Chapters': preg_match(self::TITLE_REGEX, $this->getInput('url'), $matches) or returnClientError('Invalid URL Parameter'); + $this->feedURI = self::URI . 'title/' . $matches['uuid']; $params['order[updatedAt]'] = 'desc'; if (!$this->getInput('external')) { $params['includeFutureUpdates'] = '0'; @@ -94,6 +96,15 @@ public function getName() { } } + public function getURI() { + switch($this->queriedContext) { + case 'Title Chapters': + return $this->feedURI; + default: + return parent::getURI(); + } + } + public function collectData() { $api_uri = $this->getApi(); $header = array( From 8a25823f693bba1c0d2120a829b5fd774a5b3738 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Fri, 1 Apr 2022 12:53:20 -0400 Subject: [PATCH 5/5] Remove defaultValue --- bridges/MangaDexBridge.php | 1 - 1 file changed, 1 deletion(-) diff --git a/bridges/MangaDexBridge.php b/bridges/MangaDexBridge.php index d0cfdce6718..0966849572f 100644 --- a/bridges/MangaDexBridge.php +++ b/bridges/MangaDexBridge.php @@ -17,7 +17,6 @@ class MangaDexBridge extends BridgeAbstract { 'lang' => array( 'name' => 'Chapter Languages', 'title' => 'comma-separated, two-letter language codes (example "en,jp")', - 'defaultValue' => 'en', 'exampleValue' => 'en,jp', 'required' => false ),