aboutsummaryrefslogtreecommitdiff
path: root/bridges/RedditBridge.php
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/RedditBridge.php')
-rw-r--r--bridges/RedditBridge.php573
1 files changed, 287 insertions, 286 deletions
diff --git a/bridges/RedditBridge.php b/bridges/RedditBridge.php
index 538d810b..1a643283 100644
--- a/bridges/RedditBridge.php
+++ b/bridges/RedditBridge.php
@@ -1,289 +1,290 @@
<?php
-class RedditBridge extends BridgeAbstract {
-
- const MAINTAINER = 'dawidsowa';
- const NAME = 'Reddit Bridge';
- const URI = 'https://www.reddit.com';
- const DESCRIPTION = 'Return hot submissions from Reddit';
-
- const PARAMETERS = array(
- 'global' => array(
- 'score' => array(
- 'name' => 'Minimal score',
- 'required' => false,
- 'type' => 'number',
- 'exampleValue' => 100,
- 'title' => 'Filter out posts with lower score'
- ),
- 'd' => array(
- 'name' => 'Sort By',
- 'type' => 'list',
- 'title' => 'Sort by new, hot, top or relevancy',
- 'values' => array(
- 'Hot' => 'hot',
- 'Relevance' => 'relevance',
- 'New' => 'new',
- 'Top' => 'top'
- ),
- 'defaultValue' => 'Hot'
- ),
- 'search' => array(
- 'name' => 'Keyword search',
- 'required' => false,
- 'exampleValue' => 'cats, dogs',
- 'title' => 'Keyword search, separated by commas'
- )
- ),
- 'single' => array(
- 'r' => array(
- 'name' => 'SubReddit',
- 'required' => true,
- 'exampleValue' => 'selfhosted',
- 'title' => 'SubReddit name'
- )
- ),
- 'multi' => array(
- 'rs' => array(
- 'name' => 'SubReddits',
- 'required' => true,
- 'exampleValue' => 'selfhosted, php',
- 'title' => 'SubReddit names, separated by commas'
- )
- ),
- 'user' => array(
- 'u' => array(
- 'name' => 'User',
- 'required' => true,
- 'exampleValue' => 'shwikibot',
- 'title' => 'User name'
- ),
- 'comments' => array(
- 'type' => 'checkbox',
- 'name' => 'Comments',
- 'title' => 'Whether to return comments',
- 'defaultValue' => false
- )
- )
- );
-
- public function detectParameters($url) {
- $parsed_url = parse_url($url);
-
- if ($parsed_url['host'] != 'www.reddit.com' && $parsed_url['host'] != 'old.reddit.com') return null;
-
- $path = explode('/', $parsed_url['path']);
-
- if ($path[1] == 'r') {
- return array(
- 'r' => $path[2]
- );
- } elseif ($path[1] == 'user') {
- return array(
- 'u' => $path[2]
- );
- } else {
- return null;
- }
- }
-
- public function getIcon() {
- return 'https://www.redditstatic.com/desktop2x/img/favicon/favicon-96x96.png';
- }
-
- public function getName() {
- if ($this->queriedContext == 'single') {
- return 'Reddit r/' . $this->getInput('r');
- } elseif ($this->queriedContext == 'user') {
- return 'Reddit u/' . $this->getInput('u');
- } else {
- return self::NAME;
- }
- }
-
- public function collectData() {
-
- $user = false;
- $comments = false;
- $section = $this->getInput('d');
-
- switch ($this->queriedContext) {
- case 'single':
- $subreddits[] = $this->getInput('r');
- break;
- case 'multi':
- $subreddits = explode(',', $this->getInput('rs'));
- break;
- case 'user':
- $subreddits[] = $this->getInput('u');
- $user = true;
- $comments = $this->getInput('comments');
- break;
- }
-
- if(!($this->getInput('search') === '')) {
- $keywords = $this->getInput('search');
- $keywords = str_replace(array(',', ' '), '%20', $keywords);
- $keywords = $keywords . '%20';
- } else {
- $keywords = '';
- }
-
- foreach ($subreddits as $subreddit) {
- $name = trim($subreddit);
- $values = getContents(self::URI
- . '/search.json?q='
- . $keywords
- . ($user ? 'author%3A' : 'subreddit%3A')
- . $name
- . '&sort='
- . $this->getInput('d')
- . '&include_over_18=on');
- $decodedValues = json_decode($values);
-
- foreach ($decodedValues->data->children as $post) {
- if ($post->kind == 't1' && !$comments) {
- continue;
- }
-
- $data = $post->data;
-
- if ($data->score < $this->getInput('score')) {
- continue;
- }
-
- $item = array();
- $item['author'] = $data->author;
- $item['uid'] = $data->id;
- $item['timestamp'] = $data->created_utc;
- $item['uri'] = $this->encodePermalink($data->permalink);
-
- $item['categories'] = array();
-
- if ($post->kind == 't1') {
- $item['title'] = 'Comment: ' . $data->link_title;
- } else {
- $item['title'] = $data->title;
-
- $item['categories'][] = $data->link_flair_text;
- $item['categories'][] = $data->pinned ? 'Pinned' : null;
- $item['categories'][] = $data->spoiler ? 'Spoiler' : null;
- }
-
- $item['categories'][] = $data->over_18 ? 'NSFW' : null;
- $item['categories'] = array_filter($item['categories']);
-
- if ($post->kind == 't1') {
- // Comment
-
- $item['content']
- = htmlspecialchars_decode($data->body_html);
-
- } elseif ($data->is_self) {
- // Text post
-
- $item['content']
- = htmlspecialchars_decode($data->selftext_html);
-
- } elseif (isset($data->post_hint) ? $data->post_hint == 'link' : false) {
- // Link with preview
-
- if (isset($data->media)) {
- // Reddit embeds content for some sites (e.g. Twitter)
- $embed = htmlspecialchars_decode(
- $data->media->oembed->html
- );
- } else {
- $embed = '';
- }
-
- $item['content'] = $this->template(
- $data->url,
- $data->thumbnail,
- $data->domain
- ) . $embed;
-
- } elseif (isset($data->post_hint) ? $data->post_hint == 'image' : false) {
- // Single image
-
- $item['content'] = $this->link(
- $this->encodePermalink($data->permalink),
- '<img src="' . $data->url . '" />'
- );
-
- } elseif (isset($data->is_gallery) ? $data->is_gallery : false) {
- // Multiple images
-
- $images = array();
- foreach ($data->gallery_data->items as $media) {
- $id = $media->media_id;
- $type = $data->media_metadata->$id->m == 'image/gif' ? 'gif' : 'u';
- $src = $data->media_metadata->$id->s->$type;
- $images[] = '<figure><img src="' . $src . '"/></figure><br>';
- }
-
- $item['content'] = implode('', $images);
-
- } elseif ($data->is_video) {
- // Video
-
- // Higher index -> Higher resolution
- end($data->preview->images[0]->resolutions);
- $index = key($data->preview->images[0]->resolutions);
-
- $item['content'] = $this->template(
- $data->url,
- $data->preview->images[0]->resolutions[$index]->url,
- 'Video'
- );
-
- } elseif (isset($data->media) ? $data->media->type == 'youtube.com' : false) {
- // Youtube link
-
- $item['content'] = $this->template(
- $data->url,
- $data->media->oembed->thumbnail_url,
- 'YouTube');
-
- } elseif (explode('.', $data->domain)[0] == 'self') {
- // Crossposted text post
- // TODO (optionally?) Fetch content of the original post.
-
- $item['content'] = $this->link(
- $this->encodePermalink($data->permalink),
- 'Crossposted from r/'
- . explode('.', $data->domain)[1]
- );
-
- } else {
- // Link WITHOUT preview
-
- $item['content'] = $this->link($data->url, $data->domain);
- }
-
- $this->items[] = $item;
- }
- }
- // Sort the order to put the latest posts first, even for mixed subreddits
- usort($this->items, function($a, $b) {
- return $a['timestamp'] < $b['timestamp'];
- });
- }
-
- private function encodePermalink($link) {
- return self::URI . implode(
- '/',
- array_map('urlencode', explode('/', $link))
- );
- }
-
- private function template($href, $src, $caption) {
- return '<a href="' . $href . '"><figure><figcaption>'
- . $caption . '</figcaption><img src="'
- . $src . '"/></figure></a>';
- }
-
- private function link($href, $text) {
- return '<a href="' . $href . '">' . $text . '</a>';
- }
+class RedditBridge extends BridgeAbstract
+{
+ const MAINTAINER = 'dawidsowa';
+ const NAME = 'Reddit Bridge';
+ const URI = 'https://www.reddit.com';
+ const DESCRIPTION = 'Return hot submissions from Reddit';
+
+ const PARAMETERS = [
+ 'global' => [
+ 'score' => [
+ 'name' => 'Minimal score',
+ 'required' => false,
+ 'type' => 'number',
+ 'exampleValue' => 100,
+ 'title' => 'Filter out posts with lower score'
+ ],
+ 'd' => [
+ 'name' => 'Sort By',
+ 'type' => 'list',
+ 'title' => 'Sort by new, hot, top or relevancy',
+ 'values' => [
+ 'Hot' => 'hot',
+ 'Relevance' => 'relevance',
+ 'New' => 'new',
+ 'Top' => 'top'
+ ],
+ 'defaultValue' => 'Hot'
+ ],
+ 'search' => [
+ 'name' => 'Keyword search',
+ 'required' => false,
+ 'exampleValue' => 'cats, dogs',
+ 'title' => 'Keyword search, separated by commas'
+ ]
+ ],
+ 'single' => [
+ 'r' => [
+ 'name' => 'SubReddit',
+ 'required' => true,
+ 'exampleValue' => 'selfhosted',
+ 'title' => 'SubReddit name'
+ ]
+ ],
+ 'multi' => [
+ 'rs' => [
+ 'name' => 'SubReddits',
+ 'required' => true,
+ 'exampleValue' => 'selfhosted, php',
+ 'title' => 'SubReddit names, separated by commas'
+ ]
+ ],
+ 'user' => [
+ 'u' => [
+ 'name' => 'User',
+ 'required' => true,
+ 'exampleValue' => 'shwikibot',
+ 'title' => 'User name'
+ ],
+ 'comments' => [
+ 'type' => 'checkbox',
+ 'name' => 'Comments',
+ 'title' => 'Whether to return comments',
+ 'defaultValue' => false
+ ]
+ ]
+ ];
+
+ public function detectParameters($url)
+ {
+ $parsed_url = parse_url($url);
+
+ if ($parsed_url['host'] != 'www.reddit.com' && $parsed_url['host'] != 'old.reddit.com') {
+ return null;
+ }
+
+ $path = explode('/', $parsed_url['path']);
+
+ if ($path[1] == 'r') {
+ return [
+ 'r' => $path[2]
+ ];
+ } elseif ($path[1] == 'user') {
+ return [
+ 'u' => $path[2]
+ ];
+ } else {
+ return null;
+ }
+ }
+
+ public function getIcon()
+ {
+ return 'https://www.redditstatic.com/desktop2x/img/favicon/favicon-96x96.png';
+ }
+
+ public function getName()
+ {
+ if ($this->queriedContext == 'single') {
+ return 'Reddit r/' . $this->getInput('r');
+ } elseif ($this->queriedContext == 'user') {
+ return 'Reddit u/' . $this->getInput('u');
+ } else {
+ return self::NAME;
+ }
+ }
+
+ public function collectData()
+ {
+ $user = false;
+ $comments = false;
+ $section = $this->getInput('d');
+
+ switch ($this->queriedContext) {
+ case 'single':
+ $subreddits[] = $this->getInput('r');
+ break;
+ case 'multi':
+ $subreddits = explode(',', $this->getInput('rs'));
+ break;
+ case 'user':
+ $subreddits[] = $this->getInput('u');
+ $user = true;
+ $comments = $this->getInput('comments');
+ break;
+ }
+
+ if (!($this->getInput('search') === '')) {
+ $keywords = $this->getInput('search');
+ $keywords = str_replace([',', ' '], '%20', $keywords);
+ $keywords = $keywords . '%20';
+ } else {
+ $keywords = '';
+ }
+
+ foreach ($subreddits as $subreddit) {
+ $name = trim($subreddit);
+ $values = getContents(self::URI
+ . '/search.json?q='
+ . $keywords
+ . ($user ? 'author%3A' : 'subreddit%3A')
+ . $name
+ . '&sort='
+ . $this->getInput('d')
+ . '&include_over_18=on');
+ $decodedValues = json_decode($values);
+
+ foreach ($decodedValues->data->children as $post) {
+ if ($post->kind == 't1' && !$comments) {
+ continue;
+ }
+
+ $data = $post->data;
+
+ if ($data->score < $this->getInput('score')) {
+ continue;
+ }
+
+ $item = [];
+ $item['author'] = $data->author;
+ $item['uid'] = $data->id;
+ $item['timestamp'] = $data->created_utc;
+ $item['uri'] = $this->encodePermalink($data->permalink);
+
+ $item['categories'] = [];
+
+ if ($post->kind == 't1') {
+ $item['title'] = 'Comment: ' . $data->link_title;
+ } else {
+ $item['title'] = $data->title;
+
+ $item['categories'][] = $data->link_flair_text;
+ $item['categories'][] = $data->pinned ? 'Pinned' : null;
+ $item['categories'][] = $data->spoiler ? 'Spoiler' : null;
+ }
+
+ $item['categories'][] = $data->over_18 ? 'NSFW' : null;
+ $item['categories'] = array_filter($item['categories']);
+
+ if ($post->kind == 't1') {
+ // Comment
+
+ $item['content']
+ = htmlspecialchars_decode($data->body_html);
+ } elseif ($data->is_self) {
+ // Text post
+
+ $item['content']
+ = htmlspecialchars_decode($data->selftext_html);
+ } elseif (isset($data->post_hint) ? $data->post_hint == 'link' : false) {
+ // Link with preview
+
+ if (isset($data->media)) {
+ // Reddit embeds content for some sites (e.g. Twitter)
+ $embed = htmlspecialchars_decode(
+ $data->media->oembed->html
+ );
+ } else {
+ $embed = '';
+ }
+
+ $item['content'] = $this->template(
+ $data->url,
+ $data->thumbnail,
+ $data->domain
+ ) . $embed;
+ } elseif (isset($data->post_hint) ? $data->post_hint == 'image' : false) {
+ // Single image
+
+ $item['content'] = $this->link(
+ $this->encodePermalink($data->permalink),
+ '<img src="' . $data->url . '" />'
+ );
+ } elseif (isset($data->is_gallery) ? $data->is_gallery : false) {
+ // Multiple images
+
+ $images = [];
+ foreach ($data->gallery_data->items as $media) {
+ $id = $media->media_id;
+ $type = $data->media_metadata->$id->m == 'image/gif' ? 'gif' : 'u';
+ $src = $data->media_metadata->$id->s->$type;
+ $images[] = '<figure><img src="' . $src . '"/></figure><br>';
+ }
+
+ $item['content'] = implode('', $images);
+ } elseif ($data->is_video) {
+ // Video
+
+ // Higher index -> Higher resolution
+ end($data->preview->images[0]->resolutions);
+ $index = key($data->preview->images[0]->resolutions);
+
+ $item['content'] = $this->template(
+ $data->url,
+ $data->preview->images[0]->resolutions[$index]->url,
+ 'Video'
+ );
+ } elseif (isset($data->media) ? $data->media->type == 'youtube.com' : false) {
+ // Youtube link
+
+ $item['content'] = $this->template(
+ $data->url,
+ $data->media->oembed->thumbnail_url,
+ 'YouTube'
+ );
+ } elseif (explode('.', $data->domain)[0] == 'self') {
+ // Crossposted text post
+ // TODO (optionally?) Fetch content of the original post.
+
+ $item['content'] = $this->link(
+ $this->encodePermalink($data->permalink),
+ 'Crossposted from r/'
+ . explode('.', $data->domain)[1]
+ );
+ } else {
+ // Link WITHOUT preview
+
+ $item['content'] = $this->link($data->url, $data->domain);
+ }
+
+ $this->items[] = $item;
+ }
+ }
+ // Sort the order to put the latest posts first, even for mixed subreddits
+ usort($this->items, function ($a, $b) {
+ return $a['timestamp'] < $b['timestamp'];
+ });
+ }
+
+ private function encodePermalink($link)
+ {
+ return self::URI . implode(
+ '/',
+ array_map('urlencode', explode('/', $link))
+ );
+ }
+
+ private function template($href, $src, $caption)
+ {
+ return '<a href="' . $href . '"><figure><figcaption>'
+ . $caption . '</figcaption><img src="'
+ . $src . '"/></figure></a>';
+ }
+
+ private function link($href, $text)
+ {
+ return '<a href="' . $href . '">' . $text . '</a>';
+ }
}