aboutsummaryrefslogtreecommitdiff
path: root/bridges/PatreonBridge.php
diff options
context:
space:
mode:
authorGravatar Dag <me@dvikan.no> 2022-07-01 15:10:30 +0200
committerGravatar GitHub <noreply@github.com> 2022-07-01 15:10:30 +0200
commit4f75591060d95208a301bc6bf460d875631b29cc (patch)
tree4e37d86840e8d990a563ba75d3de6f84a53cc2de /bridges/PatreonBridge.php
parent66568e3a39c61546c09a47a5688914a0bdf3c60c (diff)
downloadrss-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.php415
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;
+ }
}