Skip to content

Instantly share code, notes, and snippets.

@matt-snider
Last active April 6, 2022 21:54
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save matt-snider/fd453f2c31a9d0131c52 to your computer and use it in GitHub Desktop.
Save matt-snider/fd453f2c31a9d0131c52 to your computer and use it in GitHub Desktop.
Daily XKCD Dashing Widget

Preview

Description

A Dashing widget that shows the current xkcd comic.

The widget will display the current comic if it was published today, and otherwise it will find a random one. This ensures there is a new comic shown every day.

Dependencies

The only dependency is json.

Add it to Dashing's Gemfile:

gem 'json'

and run bundle install.

Usage

To use this widget, simply run:

dashing install fd453f2c31a9d0131c52

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

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-view="DailyXKCD" data-id="xkcd-of-the-day"></div>
</li>

The job to fetch a comic is run every day.

class Dashing.DailyXKCD extends Dashing.Widget
ready: ->
# This is fired when the widget is done being rendered
onData: (data) ->
# Handle incoming data
# You can access the html node of this widget with `@node`
# Example: $(@node).fadeOut().fadeIn() will make the node flash each time data comes in.
<h1 class="header" data-bind="'xkcd #' | append num | append ': ' | append title"></h1>
<img class="xkcd-image" data-bind-src="img"/>
<p class="date" data-bind="'Published: ' | append datestr"></p>
<p class="caption" data-bind="alt"></p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require 'net/http'
require 'json'
require 'date'
XKCD_URI = 'https://xkcd.com'
DATE_FORMAT_STR = '%B %-d, %Y'
$displayed_xkcd = nil
$prev_displayed_xkcd = nil
# Get's the nth xkcd entry, unless
# nil is passed, in which case current
def get_nth_xkcd(n)
uri = URI.join(XKCD_URI, n.to_s + '/', 'info.0.json')
response = Net::HTTP.get(uri)
JSON.parse(response)
end
# Get's the current, featured xkcd entry
def get_current_xkcd
get_nth_xkcd(nil)
end
# Get's a random xkcd
def get_random_xkcd
curr_id = get_current_xkcd['num']
random_id = nil
# 404 is reserved for Not found
while true do
random_id = rand(curr_id)
break if random_id != 404
end
get_nth_xkcd(random_id)
end
# Check if provided xkcd was published yesterday
def published_yesterday_and_unseen(xkcd_date, xkcd)
xkcd_date == Date.today.prev_day and ($prev_displayed_xkcd.nil? or not $prev_displayed_xkcd['num'] == xkcd['num'])
end
# Basic logic:
# - if an xkcd was published today, display it.
# - if an xkcd was published yesterday, and we didn't
# show it yesterday, display it.
# - otherwise, display a random xkcd.
SCHEDULER.every '1d', :first_in => 0 do |job|
$prev_displayed_xkcd = $displayed_xkcd
xkcd = get_current_xkcd
xkcd_date = Date.new(
xkcd['year'].to_i,
xkcd['month'].to_i,
xkcd['day'].to_i
)
if xkcd_date == Date.today or published_yesterday_and_unseen(xkcd_date, xkcd)
$displayed_xkcd = xkcd
else
$displayed_xkcd = get_random_xkcd
xkcd_date = Date.new(
$displayed_xkcd['year'].to_i,
$displayed_xkcd['month'].to_i,
$displayed_xkcd['day'].to_i
)
end
$displayed_xkcd['datestr'] = xkcd_date.strftime(DATE_FORMAT_STR)
send_event('xkcd-of-the-day', $displayed_xkcd)
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: white;
$header-color: rgba(0, 0, 0, 0.7);
$title-color: rgba(0, 0, 0, 0.7);
$caption-color: rgba(0, 0, 0, 0.7);
$published-color: rgba(0, 0, 0, 0.7);
$updated-at-color: rgba(0, 0, 0, 0.3);
// ----------------------------------------------------------------------------
// Widget-daily-xkcd styles
// ----------------------------------------------------------------------------
.widget-daily-xkcd {
background-color: $background-color;
vertical-align: top !important;
padding: 8px 12px !important;
.wrapper {
max-height: 100%;
}
.header {
color: $header-color;
font-size: large;
font-variant: small-caps;
}
.xkcd-image {
max-height: 200px;
}
.date {
color: $published-color;
margin-bottom: 0.5vh;
font-size: small;
text-align: left;
}
.caption {
color: $caption-color;
font-size: small;
text-align: justify;
margin-bottom: 0.5vh;
}
.updated-at {
color: $updated-at-color;
position: relative;
padding: 0;
margin: 0;
bottom:0;
}
}
@brockklein
Copy link

Matt, this is awesome.

I'd love to use it, but so far I haven't been able to successfully use the dashing install command (getting weird SSL errors).

I tried just manually placing the .coffee, .scss, and .html for the widget into a dailyxkcd folder in the widgets folder, putting the daily_xkcd.png image in /assets/images, and putting daily_xkcd.rb into the jobs folder.

Everything builds but I get a blank white column with no comic.

I'm a bit of an amateur. Can you think of anything else I need to do in order to install your widget manually?

Thanks!

@lcheong
Copy link

lcheong commented Dec 5, 2015

Hey @brockklein ... I pretty much did the same thing, but did not copy the png file anywhere (I think it's just an example file). It runs fine for me. I didn't edit anything at all after copying the files to the locations you specified. Perhaps the only difference is that my widgets/ folder is called "daily_xkcd" rather than "dailyxkcd" like you mention.

@aakashjog
Copy link

Is there any way to make sure that the widget does not exceed its size if the image is larger than the available space?

@crapmaster
Copy link

Seems like XKCD no longer accepts http calls. Need to be https.

I changed the following entry in daily_xkcd.rb and got the widget to work.
XKCD_URI = 'http://xkcd.com'
to
XKCD_URI = 'https://xkcd.com'

@manifolded
Copy link

Hey @crapmaster. You rule!

Your comment, once I read it, saved me a great deal of frustration.

@gordonjl
Copy link

Thanks, again, @crapmaster! Now I just need to figure out how to handle xkcd's many varying size dimensions!

@Mic92
Copy link

Mic92 commented Sep 23, 2018

I added:

<img class="xkcd-image" style="max-height: 200px;" data-bind-src="img"/>

to resize the image to fit into the tile.
Also I fixed the xkcd update:

-def published_yesterday_and_unseen(xkcd_date)
+def published_yesterday_and_unseen(xkcd_date, xkcd)
        xkcd_date == Date.today.prev_day and ($prev_displayed_xkcd.nil? or not $prev_displayed_xkcd['num'] == xkcd['num'])
 end
@@ -53,7 +53,7 @@ SCHEDULER.every '1d', :first_in => 0 do |job|
                xkcd['month'].to_i,
                xkcd['day'].to_i
        )
-       if xkcd_date == Date.today or published_yesterday_and_unseen(xkcd_date)
+       if xkcd_date == Date.today or published_yesterday_and_unseen(xkcd_date, xkcd)

because there was a missing variable

@matt-snider
Copy link
Author

Oh wow, sorry everyone... Comments on gists don't seem to result in notifications and I haven't looked at this in years! Glad this could be of use to a few people!

@emil-nasso
Copy link

Oh wow, sorry everyone... Comments on gists don't seem to result in notifications and I haven't looked at this in years! Glad this could be of use to a few people!

Hi! The widget works great. :) Do you think that you could change http to https in the URL as has been suggested? :)

I have not looked into Mic92's changes but that might be something to consider too, maybe. :)

@matt-snider
Copy link
Author

I updated the gist to use https and incorporate @Mic92 's suggestions, but I don't use Dashing anymore so I'm not sure if it works. @emil-nasso could you try it and let me know if it works?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment