This repository has been archived by the owner on Feb 13, 2018. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d6512c8
Showing
8 changed files
with
419 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,5 @@ | |||
bin/ | |||
log | |||
.bundle | |||
vendor/gems | |||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,8 @@ | |||
source :rubygems | |||
|
|||
gem 'sinatra' | |||
|
|||
group :development do | |||
gem 'heroku' | |||
gem 'foreman' | |||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,39 @@ | |||
GEM | |||
remote: http://rubygems.org/ | |||
specs: | |||
addressable (2.2.8) | |||
excon (0.14.2) | |||
foreman (0.47.0) | |||
thor (>= 0.13.6) | |||
heroku (2.28.7) | |||
heroku-api (~> 0.2.6) | |||
launchy (>= 0.3.2) | |||
netrc (~> 0.7.5) | |||
rest-client (~> 1.6.1) | |||
rubyzip | |||
heroku-api (0.2.6) | |||
excon (~> 0.14.0) | |||
launchy (2.1.0) | |||
addressable (~> 2.2.6) | |||
mime-types (1.19) | |||
netrc (0.7.5) | |||
rack (1.4.1) | |||
rack-protection (1.2.0) | |||
rack | |||
rest-client (1.6.7) | |||
mime-types (>= 1.16) | |||
rubyzip (0.9.9) | |||
sinatra (1.3.2) | |||
rack (~> 1.3, >= 1.3.6) | |||
rack-protection (~> 1.2) | |||
tilt (~> 1.3, >= 1.3.3) | |||
thor (0.15.3) | |||
tilt (1.3.3) | |||
|
|||
PLATFORMS | |||
ruby | |||
|
|||
DEPENDENCIES | |||
foreman | |||
heroku | |||
sinatra |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
web: bundle exec ruby lib/nowplaying.rb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,23 @@ | |||
## Running on Heroku | |||
|
|||
Clone this repo. | |||
|
|||
In the clone: | |||
|
|||
heroku create --stack cedar jnewland-rdio-nowplaying | |||
|
|||
Set the following config at heroku: | |||
|
|||
heroku config:add RDIO_CONSUMER_KEY=foo | |||
heroku config:add RDIO_CONSUMER_SECRET=foo@foo.com | |||
heroku config:add POLL_INTERVAL=10 | |||
|
|||
Ship it: | |||
|
|||
git push heroku master | |||
|
|||
Fire up a web process: | |||
|
|||
heroku scale web=1 | |||
|
|||
Hit up [papertrail](https://papertrailapp.com/events) and check on the logs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,101 @@ | |||
#!/usr/bin/env ruby | |||
|
|||
# (c) 2011 Rdio Inc | |||
# Permission is hereby granted, free of charge, to any person obtaining a copy | |||
# of this software and associated documentation files (the "Software"), to deal | |||
# in the Software without restriction, including without limitation the rights | |||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
# copies of the Software, and to permit persons to whom the Software is | |||
# furnished to do so, subject to the following conditions: | |||
# | |||
# The above copyright notice and this permission notice shall be included in | |||
# all copies or substantial portions of the Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
# THE SOFTWARE. | |||
|
|||
require 'sinatra' | |||
require 'uri' | |||
$LOAD_PATH << './lib' | |||
require 'rdio' | |||
|
|||
RDIO_CONSUMER_KEY = ENV['RDIO_CONSUMER_KEY'] | |||
RDIO_CONSUMER_SECRET = ENV['RDIO_CONSUMER_SECRET'] | |||
|
|||
enable :sessions | |||
|
|||
get '/' do | |||
access_token = session[:at] | |||
access_token_secret = session[:ats] | |||
if access_token and access_token_secret | |||
rdio = Rdio.new([RDIO_CONSUMER_KEY, RDIO_CONSUMER_SECRET], | |||
[access_token, access_token_secret]) | |||
|
|||
user_key = rdio.call('currentUser')['result']['key'] | |||
play_data = rdio.call('get', { :keys => user_key, :extras => 'lastSongPlayed,lastSongPlayTime'})['result'][user_key] | |||
|
|||
play_time = play_data['lastSongPlayTime'] | |||
song_key = play_data['lastSongPlayed']['key'] | |||
|
|||
song = rdio.call('get', { :keys => song_key, :extras => 'bigIcon'})['result'][song_key] | |||
|
|||
response = " | |||
<html><head><title>Now Playing</title></head><body> | |||
<img src='%s' /> | |||
<h1>%s</h1> | |||
<h2>%s</h2> | |||
<h3>%s</h3> | |||
" % [song['bigIcon'], song['name'], song['album'], song['artist']] | |||
response += '</body></html>' | |||
return response | |||
else | |||
redirect to('/login') | |||
end | |||
end | |||
|
|||
get '/login' do | |||
session.clear | |||
# begin the authentication process | |||
rdio = Rdio.new([RDIO_CONSUMER_KEY, RDIO_CONSUMER_SECRET]) | |||
callback_url = (URI.join request.url, '/callback').to_s | |||
url = rdio.begin_authentication(callback_url) | |||
# save our request token in the session | |||
session[:rt] = rdio.token[0] | |||
session[:rts] = rdio.token[1] | |||
# go to Rdio to authenticate the app | |||
redirect url | |||
end | |||
|
|||
get '/callback' do | |||
# get the state from cookies and the query string | |||
request_token = session[:rt] | |||
request_token_secret = session[:rts] | |||
verifier = params[:oauth_verifier] | |||
# make sure we have everything we need | |||
if request_token and request_token_secret and verifier | |||
# exchange the verifier and request token for an access token | |||
rdio = Rdio.new([RDIO_CONSUMER_KEY, RDIO_CONSUMER_SECRET], | |||
[request_token, request_token_secret]) | |||
rdio.complete_authentication(verifier) | |||
# save the access token in cookies (and discard the request token) | |||
session[:at] = rdio.token[0] | |||
session[:ats] = rdio.token[1] | |||
session.delete(:rt) | |||
session.delete(:rts) | |||
# go to the home page | |||
redirect to('/') | |||
else | |||
# we're missing something important | |||
redirect to('/logout') | |||
end | |||
end | |||
|
|||
get '/logout' do | |||
session.clear | |||
redirect to('/') | |||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,160 @@ | |||
# om is oauth-mini - a simple implementation of a useful subset of OAuth. | |||
# It's designed to be useful and reusable but not general purpose. | |||
# | |||
# (c) 2011 Rdio Inc | |||
# Permission is hereby granted, free of charge, to any person obtaining a copy | |||
# of this software and associated documentation files (the "Software"), to deal | |||
# in the Software without restriction, including without limitation the rights | |||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
# copies of the Software, and to permit persons to whom the Software is | |||
# furnished to do so, subject to the following conditions: | |||
# | |||
# The above copyright notice and this permission notice shall be included in | |||
# all copies or substantial portions of the Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
# THE SOFTWARE. | |||
|
|||
# A simple OAuth client implementation. Do less better. | |||
# Here are the restrictions: | |||
# - only HMAC-SHA1 is supported | |||
# - only WWW-Authentiate form signatures are generated | |||
# | |||
# To sign a request: | |||
# auth = om([consumer_key,consumer_secret], url, params) | |||
# send Authorization: <auth> | |||
# when POSTing <params> to <url> | |||
# Optional additional arguments are: | |||
# token = [oauth_token, oauth_token_secret] | |||
# method = "POST" | |||
# realm = "Realm-for-authorization-header" | |||
|
|||
require 'uri' | |||
require 'cgi' | |||
require 'digest' | |||
require 'digest/sha1' | |||
|
|||
if not "".respond_to?(:encoding) | |||
# ruby 1.8 doesn't know about unicode :( | |||
require 'iconv' | |||
# we will just check that bytes are valid UTF-8 | |||
$__om_utf8_checker = Iconv.new("UTF-8", "UTF-8") | |||
end | |||
|
|||
def om(consumer, url, post_params, token=nil, method='POST', realm=nil, timestamp=nil, nonce=nil) | |||
# A one-shot simple OAuth signature generator | |||
|
|||
# the method must be upper-case | |||
method = method.upcase | |||
|
|||
# we want params as an Array of name / value pairs | |||
if post_params.is_a?(Array) | |||
params = post_params | |||
else | |||
params = post_params.collect { |x| x } | |||
end | |||
|
|||
# we want those pairs to be strings | |||
params = params.collect { |k,v| [k.to_s, v.to_s]} | |||
|
|||
# normalize the URL | |||
url = URI.parse(url) | |||
# scheme is lower-case | |||
url.scheme = url.scheme.downcase | |||
# remove username & password | |||
url.user = url.password = nil | |||
# host is lowercase | |||
url.host = url.host.downcase | |||
|
|||
# add URL params to the params | |||
if url.query | |||
CGI.parse(url.query).each { |k,vs| vs.each { |v| params.push([k,v]) } } | |||
end | |||
|
|||
# remove the params and fragment | |||
url.query = nil | |||
url.fragment = nil | |||
|
|||
# add OAuth params | |||
params = params + [ | |||
['oauth_version', '1.0'], | |||
['oauth_timestamp', timestamp || Time.now.to_i.to_s], | |||
['oauth_nonce', nonce || rand(1000000).to_s], | |||
['oauth_signature_method', 'HMAC-SHA1'], | |||
['oauth_consumer_key', consumer[0]], | |||
] | |||
|
|||
# the consumer secret is the first half of the HMAC-SHA1 key | |||
hmac_key = consumer[1] + '&' | |||
|
|||
if token != nil | |||
# include a token in params | |||
params.push ['oauth_token', token[0]] | |||
# and the token secret in the HMAC-SHA1 key | |||
hmac_key += token[1] | |||
end | |||
|
|||
def percent_encode(s) | |||
if s.respond_to?(:encoding) | |||
# Ruby 1.9 knows about encodings, convert the string to UTF-8 | |||
s = s.encode(Encoding::UTF_8) | |||
else | |||
# Ruby 1.8 does not, just check that it's valid UTF-8 | |||
begin | |||
$__om_utf8_checker.iconv(s) | |||
rescue Iconv::IllegalSequence => exception | |||
throw ArgumentError.new("Non-UTF-8 string: "+s.inspect) | |||
end | |||
end | |||
chars = s.bytes.map do |b| | |||
c = b.chr | |||
if ((c >= '0' and c <= '9') or | |||
(c >= 'A' and c <= 'Z') or | |||
(c >= 'a' and c <= 'z') or | |||
c == '-' or c == '.' or c == '_' or c == '~') | |||
c | |||
else | |||
'%%%02X' % b | |||
end | |||
end | |||
chars.join | |||
end | |||
|
|||
# Sort lexicographically, first after key, then after value. | |||
params.sort! | |||
# escape the key/value pairs and combine them into a string | |||
normalized_params = (params.collect {|p| percent_encode(p[0])+'='+percent_encode(p[1])}).join '&' | |||
|
|||
# build the signature base string | |||
signature_base_string = (percent_encode(method) + | |||
'&' + percent_encode(url.to_s) + | |||
'&' + percent_encode(normalized_params)) | |||
|
|||
# HMAC-SHA1 | |||
hmac = Digest::HMAC.new(hmac_key, Digest::SHA1) | |||
hmac.update(signature_base_string) | |||
|
|||
# Calculate the digest base 64. Drop the trailing \n | |||
oauth_signature = [hmac.digest].pack('m0').strip | |||
|
|||
# Build the Authorization header | |||
if realm | |||
authorization_params = [['realm', realm]] | |||
else | |||
authorization_params = [] | |||
end | |||
authorization_params.push(['oauth_signature', oauth_signature]) | |||
|
|||
# we only want certain params in the auth header | |||
oauth_params = ['oauth_version', 'oauth_timestamp', 'oauth_nonce', | |||
'oauth_signature_method', 'oauth_signature', | |||
'oauth_consumer_key', 'oauth_token'] | |||
authorization_params.concat(params.select { |param| nil != oauth_params.index(param[0]) }) | |||
|
|||
return 'OAuth ' + (authorization_params.collect {|param| '%s="%s"' % param}).join(', ') | |||
end |
Oops, something went wrong.