diff options
author | 2022-07-01 15:10:30 +0200 | |
---|---|---|
committer | 2022-07-01 15:10:30 +0200 | |
commit | 4f75591060d95208a301bc6bf460d875631b29cc (patch) | |
tree | 4e37d86840e8d990a563ba75d3de6f84a53cc2de /bridges/PatreonBridge.php | |
parent | 66568e3a39c61546c09a47a5688914a0bdf3c60c (diff) | |
download | rss-bridge-4f75591060d95208a301bc6bf460d875631b29cc.tar.gz rss-bridge-4f75591060d95208a301bc6bf460d875631b29cc.tar.zst rss-bridge-4f75591060d95208a301bc6bf460d875631b29cc.zip |
Reformat codebase v4 (#2872)
Reformat code base to PSR12
Co-authored-by: rssbridge <noreply@github.com>
Diffstat (limited to 'bridges/PatreonBridge.php')
-rw-r--r-- | bridges/PatreonBridge.php | 415 |
1 files changed, 215 insertions, 200 deletions
diff --git a/bridges/PatreonBridge.php b/bridges/PatreonBridge.php index 5f9a4565..a15d0378 100644 --- a/bridges/PatreonBridge.php +++ b/bridges/PatreonBridge.php @@ -1,202 +1,217 @@ <?php -class PatreonBridge extends BridgeAbstract { - const NAME = 'Patreon Bridge'; - const URI = 'https://www.patreon.com/'; - const CACHE_TIMEOUT = 300; // 5min - const DESCRIPTION = 'Returns posts by creators on Patreon'; - const MAINTAINER = 'Roliga'; - const PARAMETERS = array( array( - 'creator' => array( - 'name' => 'Creator', - 'type' => 'text', - 'required' => true, - 'exampleValue' => 'sanityinc', - 'title' => 'Creator name as seen in their page URL' - ) - )); - - public function collectData(){ - $html = getSimpleHTMLDOMCached($this->getURI(), 86400); - $regex = '#/api/campaigns/([0-9]+)#'; - if(preg_match($regex, $html->save(), $matches) > 0) { - $campaign_id = $matches[1]; - } else { - returnServerError('Could not find campaign ID'); - } - - $query = array( - 'include' => implode(',', array( - 'user', - 'attachments', - 'user_defined_tags', - //'campaign', - //'poll.choices', - //'poll.current_user_responses.user', - //'poll.current_user_responses.choice', - //'poll.current_user_responses.poll', - //'access_rules.tier.null', - //'images.null', - //'audio.null' - )), - 'fields' => array( - 'post' => implode(',', array( - //'change_visibility_at', - //'comment_count', - 'content', - //'current_user_can_delete', - //'current_user_can_view', - //'current_user_has_liked', - //'embed', - 'image', - //'is_paid', - //'like_count', - //'min_cents_pledged_to_view', - //'patreon_url', - //'patron_count', - //'pledge_url', - //'post_file', - //'post_metadata', - //'post_type', - 'published_at', - 'teaser_text', - //'thumbnail_url', - 'title', - //'upgrade_url', - 'url', - //'was_posted_by_campaign_owner' - )), - 'user' => implode(',', array( - //'image_url', - 'full_name', - //'url' - )) - ), - 'filter' => array( - 'contains_exclusive_posts' => true, - 'is_draft' => false, - 'campaign_id' => $campaign_id - ), - 'sort' => '-published_at' - ); - $posts = $this->apiGet('posts', $query); - - foreach($posts->data as $post) { - $item = array( - 'uri' => $post->attributes->url, - 'title' => $post->attributes->title, - 'timestamp' => $post->attributes->published_at, - 'content' => '', - 'uid' => 'patreon.com/' . $post->id - ); - - $user = $this->findInclude($posts, - 'user', - $post->relationships->user->data->id); - $item['author'] = $user->full_name; - - if(isset($post->attributes->image)) - $item['content'] .= '<p><a href="' - . $post->attributes->url - . '"><img src="' - . $post->attributes->image->thumb_url - . '" /></a></p>'; - - if(isset($post->attributes->content)) { - $item['content'] .= $post->attributes->content; - } elseif (isset($post->attributes->teaser_text)) { - $item['content'] .= '<p>' - . $post->attributes->teaser_text - . '</p>'; - } - - if(isset($post->relationships->user_defined_tags)) { - $item['categories'] = array(); - foreach($post->relationships->user_defined_tags->data as $tag) { - $attrs = $this->findInclude($posts, 'post_tag', $tag->id); - $item['categories'][] = $attrs->value; - } - } - - if(isset($post->relationships->attachments)) { - $item['enclosures'] = array(); - foreach($post->relationships->attachments->data as $attachment) { - $attrs = $this->findInclude($posts, 'attachment', $attachment->id); - $item['enclosures'][] = $attrs->url; - } - } - - $this->items[] = $item; - } - } - - /* - * Searches the "included" array in an API response and returns attributes - * for the first match. - */ - private function findInclude($data, $type, $id) { - foreach($data->included as $include) - if($include->type === $type && $include->id === $id) - return $include->attributes; - } - - private function apiGet($endpoint, $query_data = array()) { - $query_data['json-api-version'] = 1.0; - $query_data['json-api-use-default-includes'] = 0; - - $url = 'https://www.patreon.com/api/' - . $endpoint - . '?' - . http_build_query($query_data); - - /* - * Accept-Language header and the CURL cipher list are for bypassing the - * Cloudflare anti-bot protection on the Patreon API. If this ever breaks, - * here are some other project that also deal with this: - * https://github.com/mikf/gallery-dl/issues/342 - * https://github.com/daemionfox/patreon-feed/issues/7 - * https://www.patreondevelopers.com/t/api-returning-cloudflare-challenge/2025 - * https://github.com/splitbrain/patreon-rss/issues/4 - */ - $header = array( - 'Accept-Language: en-US', - 'Content-Type: application/json' - ); - $opts = array( - CURLOPT_SSL_CIPHER_LIST => implode(':', array( - 'DEFAULT', - '!DHE-RSA-CHACHA20-POLY1305' - )) - ); - - $data = json_decode(getContents($url, $header, $opts)); - - return $data; - } - - public function getName(){ - if(!is_null($this->getInput('creator'))) - return $this->getInput('creator') . ' posts'; - - return parent::getName(); - } - - public function getURI(){ - if(!is_null($this->getInput('creator'))) - return self::URI . $this->getInput('creator'); - - return parent::getURI(); - } - - public function detectParameters($url){ - $params = array(); - - // Matches e.g. https://www.patreon.com/SomeCreator - $regex = '/^(https?:\/\/)?(www\.)?patreon\.com\/([^\/&?\n]+)/'; - if(preg_match($regex, $url, $matches) > 0) { - $params['creator'] = urldecode($matches[3]); - return $params; - } - - return null; - } + +class PatreonBridge extends BridgeAbstract +{ + const NAME = 'Patreon Bridge'; + const URI = 'https://www.patreon.com/'; + const CACHE_TIMEOUT = 300; // 5min + const DESCRIPTION = 'Returns posts by creators on Patreon'; + const MAINTAINER = 'Roliga'; + const PARAMETERS = [ [ + 'creator' => [ + 'name' => 'Creator', + 'type' => 'text', + 'required' => true, + 'exampleValue' => 'sanityinc', + 'title' => 'Creator name as seen in their page URL' + ] + ]]; + + public function collectData() + { + $html = getSimpleHTMLDOMCached($this->getURI(), 86400); + $regex = '#/api/campaigns/([0-9]+)#'; + if (preg_match($regex, $html->save(), $matches) > 0) { + $campaign_id = $matches[1]; + } else { + returnServerError('Could not find campaign ID'); + } + + $query = [ + 'include' => implode(',', [ + 'user', + 'attachments', + 'user_defined_tags', + //'campaign', + //'poll.choices', + //'poll.current_user_responses.user', + //'poll.current_user_responses.choice', + //'poll.current_user_responses.poll', + //'access_rules.tier.null', + //'images.null', + //'audio.null' + ]), + 'fields' => [ + 'post' => implode(',', [ + //'change_visibility_at', + //'comment_count', + 'content', + //'current_user_can_delete', + //'current_user_can_view', + //'current_user_has_liked', + //'embed', + 'image', + //'is_paid', + //'like_count', + //'min_cents_pledged_to_view', + //'patreon_url', + //'patron_count', + //'pledge_url', + //'post_file', + //'post_metadata', + //'post_type', + 'published_at', + 'teaser_text', + //'thumbnail_url', + 'title', + //'upgrade_url', + 'url', + //'was_posted_by_campaign_owner' + ]), + 'user' => implode(',', [ + //'image_url', + 'full_name', + //'url' + ]) + ], + 'filter' => [ + 'contains_exclusive_posts' => true, + 'is_draft' => false, + 'campaign_id' => $campaign_id + ], + 'sort' => '-published_at' + ]; + $posts = $this->apiGet('posts', $query); + + foreach ($posts->data as $post) { + $item = [ + 'uri' => $post->attributes->url, + 'title' => $post->attributes->title, + 'timestamp' => $post->attributes->published_at, + 'content' => '', + 'uid' => 'patreon.com/' . $post->id + ]; + + $user = $this->findInclude( + $posts, + 'user', + $post->relationships->user->data->id + ); + $item['author'] = $user->full_name; + + if (isset($post->attributes->image)) { + $item['content'] .= '<p><a href="' + . $post->attributes->url + . '"><img src="' + . $post->attributes->image->thumb_url + . '" /></a></p>'; + } + + if (isset($post->attributes->content)) { + $item['content'] .= $post->attributes->content; + } elseif (isset($post->attributes->teaser_text)) { + $item['content'] .= '<p>' + . $post->attributes->teaser_text + . '</p>'; + } + + if (isset($post->relationships->user_defined_tags)) { + $item['categories'] = []; + foreach ($post->relationships->user_defined_tags->data as $tag) { + $attrs = $this->findInclude($posts, 'post_tag', $tag->id); + $item['categories'][] = $attrs->value; + } + } + + if (isset($post->relationships->attachments)) { + $item['enclosures'] = []; + foreach ($post->relationships->attachments->data as $attachment) { + $attrs = $this->findInclude($posts, 'attachment', $attachment->id); + $item['enclosures'][] = $attrs->url; + } + } + + $this->items[] = $item; + } + } + + /* + * Searches the "included" array in an API response and returns attributes + * for the first match. + */ + private function findInclude($data, $type, $id) + { + foreach ($data->included as $include) { + if ($include->type === $type && $include->id === $id) { + return $include->attributes; + } + } + } + + private function apiGet($endpoint, $query_data = []) + { + $query_data['json-api-version'] = 1.0; + $query_data['json-api-use-default-includes'] = 0; + + $url = 'https://www.patreon.com/api/' + . $endpoint + . '?' + . http_build_query($query_data); + + /* + * Accept-Language header and the CURL cipher list are for bypassing the + * Cloudflare anti-bot protection on the Patreon API. If this ever breaks, + * here are some other project that also deal with this: + * https://github.com/mikf/gallery-dl/issues/342 + * https://github.com/daemionfox/patreon-feed/issues/7 + * https://www.patreondevelopers.com/t/api-returning-cloudflare-challenge/2025 + * https://github.com/splitbrain/patreon-rss/issues/4 + */ + $header = [ + 'Accept-Language: en-US', + 'Content-Type: application/json' + ]; + $opts = [ + CURLOPT_SSL_CIPHER_LIST => implode(':', [ + 'DEFAULT', + '!DHE-RSA-CHACHA20-POLY1305' + ]) + ]; + + $data = json_decode(getContents($url, $header, $opts)); + + return $data; + } + + public function getName() + { + if (!is_null($this->getInput('creator'))) { + return $this->getInput('creator') . ' posts'; + } + + return parent::getName(); + } + + public function getURI() + { + if (!is_null($this->getInput('creator'))) { + return self::URI . $this->getInput('creator'); + } + + return parent::getURI(); + } + + public function detectParameters($url) + { + $params = []; + + // Matches e.g. https://www.patreon.com/SomeCreator + $regex = '/^(https?:\/\/)?(www\.)?patreon\.com\/([^\/&?\n]+)/'; + if (preg_match($regex, $url, $matches) > 0) { + $params['creator'] = urldecode($matches[3]); + return $params; + } + + return null; + } } |