kevinquillen
6/2/2013 - 9:25 PM

Reddit Widget for Dashing

Reddit Widget for Dashing

// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color:  #12b0c5;
$title-color:       rgba(255, 255, 255, 0.7);
$moreinfo-color:    rgba(255, 255, 255, 0.7);

// ----------------------------------------------------------------------------
// Widget-list styles
// ----------------------------------------------------------------------------
.widget-reddit {
  background-color: $background-color;
  vertical-align: top !important;

  .title {
    color: $title-color;
  }

  th, td {
    text-align: left;
  }

  td.post-title {
    max-width: 350px;
  }

  .updated-at {
    color: rgba(0, 0, 0, 0.3);
  }

  .more-info {
    color: $moreinfo-color;
  }
}
require 'net/http'
require 'json'

class Reddit
  def initialize()
    # add your desired subreddits here
    @subreddits = {
      '/r/programming' => 'http://www.reddit.com/r/programming.json',
      '/r/webdev' => 'http://www.reddit.com/r/webdev.json',
      '/r/drupal' => 'http://www.reddit.com/r/drupal.json',
      '/r/ruby' => 'http://www.reddit.com/r/ruby.json',
    }

    # the limit per subreddit to grab
    @maxcount = 5
  end

  def getTopPostsPerSubreddit()
    posts = [];

    @subreddits.each do |subreddit, url|
      response = JSON.parse(Net::HTTP.get(URI(url)))

      if !response
        puts "reddit communication error for #{@subreddit} (shrug)"
      else
        items = []

        for i in 0..@maxcount
          title = response['data']['children'][i]['data']['title']
          trimmed_title = title[0..85].gsub(/\s\w+$/, '...')

          items.push({
            title: trimmed_title,
            score: response['data']['children'][i]['data']['score'],
            comments: response['data']['children'][i]['data']['num_comments']
          })
        end

        posts.push({ label: 'Current top posts in "' + subreddit + '"', items: items })
      end
    end

    posts
  end
end

@Reddit = Reddit.new();

SCHEDULER.every '2m', :first_in => 0 do |job|
  posts = @Reddit.getTopPostsPerSubreddit
  send_event('reddit', { :posts => posts })
end
<h3>reddit</h3>

<table class="reddit-posts">
  <thead>
    <tr>
      <th class="subreddit-title" data-bind="posts.label" colspan="3">Loading...</th>
    </tr>

    <tr>
      <th class="post-title">Title</th>
      <th class="post-upvotes">Upvotes</th>
      <th class="post-comments">Comments</th>
    </tr>
  </thead>

  <tbody class="subreddit-data">
    <tr data-foreach-item="posts.items">
      <td class="post-title" data-bind="item.title"></td>
      <td class="post-score" data-bind="item.score"></td>
      <td class="post-comments" data-bind="item.comments"></td>
    </tr>
  </tbody>

  <tfoot></tfoot>
</table>
class Dashing.Reddit extends Dashing.Widget
  ready: ->
    @currentIndex = 0
    @titleElem = $(@node).find('.subreddit-title')
    @dataElem = $(@node).find('.subreddit-data')
    @top_posts = @get('posts')
    @nextSubreddit()
    @startCarousel()

  onData: (data) ->
    @currentIndex = 0

  startCarousel: ->
    setInterval(@nextSubreddit, 8000)

  nextSubreddit: =>
    if @top_posts
      @dataElem.fadeOut =>
        @set 'posts', @top_posts[@currentIndex]
        @titleElem.fadeIn()
        @dataElem.fadeIn()
        @currentIndex = (@currentIndex + 1) % @top_posts.length

Preview

Description

Took a little inspiration from the News widget to construct this Reddit widget. Simply add the subreddit .json feed URLs that you want to the top of the reddit.rb job script, and the widget will cycle through each one, showing top posts, their score, and comment count. You can also set the maxcount higher or lower, the default is 5 posts.

##Usage

To use this widget, copy reddit.html, reddit.coffee, and reddit.scss into the /widgets/reddit directory. Put the reddit.rb file in your /jobs folder.

To include the widget in a dashboard, add the following snippet to the dashboard layout file:

<li data-row="1" data-col="1" data-sizex="4" data-sizey="1">
  <div data-id="reddit" data-view="Reddit"></div>
</li>