├── .gitignore ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── LICENSE.txt ├── README.md ├── Rakefile ├── lib ├── simplecast.rb └── simplecast │ ├── client.rb │ ├── client │ ├── episode.rb │ ├── podcast.rb │ ├── resource.rb │ └── statistic.rb │ ├── configurable.rb │ ├── episode.rb │ ├── model.rb │ ├── podcast.rb │ ├── statistic.rb │ └── version.rb ├── simplecast.gemspec └── spec ├── simplecast ├── client │ ├── episode_spec.rb │ ├── podcast_spec.rb │ └── resource_spec.rb ├── client_spec.rb ├── episode_spec.rb └── model_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /test/tmp/ 9 | /test/version_tmp/ 10 | /tmp/ 11 | 12 | ## Specific to RubyMotion: 13 | .dat* 14 | .repl_history 15 | build/ 16 | 17 | ## Documentation cache and generated files: 18 | /.yardoc/ 19 | /_yardoc/ 20 | /doc/ 21 | /rdoc/ 22 | 23 | ## Environment normalisation: 24 | /.bundle/ 25 | /vendor/bundle 26 | /lib/bundler/man/ 27 | 28 | # for a library or gem, you might want to ignore these files since the code is 29 | # intended to run in multiple environments; otherwise, check them in: 30 | # Gemfile.lock 31 | # .ruby-version 32 | # .ruby-gemset 33 | 34 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 35 | .rvmrc 36 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in simplecast.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | simplecast (0.0.1) 5 | hurley (~> 0.1) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | diff-lcs (1.2.5) 11 | hurley (0.1) 12 | rake (10.4.2) 13 | rspec (3.2.0) 14 | rspec-core (~> 3.2.0) 15 | rspec-expectations (~> 3.2.0) 16 | rspec-mocks (~> 3.2.0) 17 | rspec-core (3.2.3) 18 | rspec-support (~> 3.2.0) 19 | rspec-expectations (3.2.1) 20 | diff-lcs (>= 1.2.0, < 2.0) 21 | rspec-support (~> 3.2.0) 22 | rspec-mocks (3.2.1) 23 | diff-lcs (>= 1.2.0, < 2.0) 24 | rspec-support (~> 3.2.0) 25 | rspec-support (3.2.2) 26 | 27 | PLATFORMS 28 | ruby 29 | 30 | DEPENDENCIES 31 | bundler (~> 1.7) 32 | rake (~> 10.0) 33 | rspec 34 | simplecast! 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jonathan Cutrell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Jonathan Cutrell 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simplecast 2 | 3 | ## Note: This gem is untested and currently unmaintained. 4 | With Simplecast being under new leadership, I've spoken with their team about upcoming API changes. Instead of focusing on developing this gem more completely under the current API, I've chosen to wait until the new changes are released. This gem (or a version of it, anyway) powers [Spec.fm](https://spec.fm), but I recommend testing thoroughly. Optionally, use Simplecast's already-supported RSS feed as a reliable (albeit limited) alternative. 5 | 6 | Simplecast is awesome. So is Ruby. Use them both. Profit. 7 | 8 | Note: Publishing is not currently supported by the Simplecast API, and thus is also not supported by this gem. It probably will be one day. Who knows? 9 | 10 | ## Installation 11 | 12 | Add this line to your application's Gemfile: 13 | 14 | ```ruby 15 | gem 'simplecast' 16 | ``` 17 | 18 | And then execute: 19 | 20 | $ bundle 21 | 22 | Or install it yourself as: 23 | 24 | $ gem install simplecast 25 | 26 | ## Usage 27 | 28 | Set up the gem in a config file (if you're using Rails, just add something like a simplecast.rb in initializers). 29 | 30 | Right now, there are only two config options: `api_key` and `podcast_id`. Your API key can be found in your [account settings](https://simplecast.com/user/edit). 31 | 32 | Your `podcast_id` is in the URL for your account, and is likely just a number. 33 | 34 | ```ruby 35 | Simplecast.configure do |c| 36 | c.api_key "Your_api_key_here" 37 | c.podcast_id "Your_podcast_id_here" 38 | end 39 | ``` 40 | 41 | Next, you can access Podcasts, Episodes, and Statistics like this: 42 | 43 | ```ruby 44 | # Episodes 45 | Simplecast::Client::Episode.all # gets all podcasts, as long as podcast_id was set in the config 46 | Simplecast::Client::Episode.all(podcast_id) # gets all podcasts, as long as podcast_id was set in the config 47 | Simplecast::Client::Episode.find(episode_id) 48 | Simplecast::Client::Episode.find(episode_id, podcast_id) 49 | 50 | # Podcast 51 | Simplecast::Client::Podcast.all 52 | Simplecast::Client::Podcast.find(podcast_id) 53 | 54 | # Statistics 55 | # the overall method takes timeframe parameters as defined at https://api.simplecast.com - /podcasts/:podcast_id/statistics/overall.json 56 | Simplecast::Client::Statistic.overall(podcast_id, options:{}) 57 | 58 | # returns listener stats. /podcasts/:podcast_id/statistics.json 59 | Simplecast::Client::Statistic.all(podcast_id) 60 | 61 | # returns stats for a given episode. Takes timeframe params. /podcasts/:podcast_id/statistics/episode.json 62 | Simplecast::Client::Statistic.for_episode(episode_id, podcast_id: nil, opts: {}) 63 | ``` 64 | 65 | ## Contributing 66 | 67 | 1. Fork it ( https://github.com/jcutrell/simplecast/fork ) 68 | 2. Create your feature branch (`git checkout -b my-new-feature`) 69 | 3. Commit your changes (`git commit -am 'Add some feature'`) 70 | 4. Push to the branch (`git push origin my-new-feature`) 71 | 5. Create a new Pull Request 72 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | 3 | -------------------------------------------------------------------------------- /lib/simplecast.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.dirname(__FILE__) 2 | require "simplecast/version" 3 | require "simplecast/configurable" 4 | 5 | require "simplecast/model" 6 | require "simplecast/podcast" 7 | require "simplecast/episode" 8 | require "simplecast/statistic" 9 | 10 | require "simplecast/client" 11 | require "simplecast/client/resource" 12 | require "simplecast/client/podcast" 13 | require "simplecast/client/episode" 14 | require "simplecast/client/statistic" 15 | 16 | module Simplecast 17 | class << self 18 | include Simplecast::Configurable 19 | def client 20 | @client = Simplecast::Client.new(options) unless defined?(@client) 21 | @client 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/simplecast/client.rb: -------------------------------------------------------------------------------- 1 | require 'hurley' 2 | require 'json' 3 | require 'simplecast/configurable' 4 | module Simplecast 5 | class Client 6 | include Simplecast::Configurable 7 | def initialize(options = {}) 8 | # Use options passed in, but fall back to module defaults 9 | Simplecast::Configurable.keys.each do |key| 10 | instance_variable_set(:"@#{key}", options[key] || Simplecast.instance_variable_get(:"@#{key}")) 11 | end 12 | @client = Hurley::Client.new('https://api.simplecast.com/v1/') 13 | @client.header["X-API-KEY"] = @api_key 14 | @client 15 | end 16 | def request(method, path, data, options = {}) 17 | if data.is_a?(Hash) 18 | options[:query] = data.delete(:query) || {} 19 | options[:headers] = data.delete(:headers) || {} 20 | if accept = data.delete(:accept) 21 | options[:headers][:accept] = accept 22 | end 23 | end 24 | @last_response = response = @client.send(method, URI::Parser.new.escape(path.to_s), data, options) 25 | response.data 26 | end 27 | def get(url) 28 | response = @client.get(url) 29 | JSON.parse(response.body) 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/simplecast/client/episode.rb: -------------------------------------------------------------------------------- 1 | module Simplecast 2 | class Client 3 | module Episode 4 | class << self 5 | include Simplecast::Client::Resource 6 | def find(id, podcast_id = nil) 7 | podcast_id ||= client.podcast_id 8 | api_obj = client.get("podcasts/#{podcast_id}/episodes/#{id}.json") 9 | model.new(api_obj) 10 | end 11 | def embed(id, podcast_id = nil) 12 | podcast_id ||= client.podcast_id 13 | api_obj = client.get("podcasts/#{podcast_id}/episodes/#{id}/embed.json") 14 | end 15 | def all(podcast_id = nil) 16 | podcast_id ||= client.podcast_id 17 | api_obj_array = client.get("podcasts/#{podcast_id}/episodes.json") 18 | api_obj_array.map {|api_obj| model.new(api_obj) } 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/simplecast/client/podcast.rb: -------------------------------------------------------------------------------- 1 | module Simplecast 2 | class Client 3 | module Podcast 4 | class << self 5 | include Simplecast::Client::Resource 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/simplecast/client/resource.rb: -------------------------------------------------------------------------------- 1 | module Simplecast 2 | class Client 3 | module Resource 4 | include Simplecast::Configurable 5 | def find(id) 6 | api_obj = client.get("#{resource_plural_name_lower}/#{id}.json") 7 | model.new(api_obj) 8 | end 9 | def all 10 | all = client.get("#{resource_plural_name_lower}.json") 11 | all.map {|item| model.new(item) } 12 | end 13 | def resource_plural_name_lower 14 | send(:name).split('::').last.downcase + "s" 15 | end 16 | def client 17 | @client ||= Simplecast.client 18 | end 19 | def model 20 | Simplecast.const_get(name.split("::").last) 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/simplecast/client/statistic.rb: -------------------------------------------------------------------------------- 1 | require 'hurley' 2 | module Simplecast 3 | class Client 4 | module Statistic 5 | class << self 6 | include Simplecast::Client::Resource 7 | def for_episode(episode_id, podcast_id: nil, opts: {}) 8 | opts.merge!({episode_id: episode_id}) 9 | podcast_id ||= client.podcast_id # TODO: || raise Simplecast::Error.new("Podcast ID must be supplied either in configuration or directly to the #for_episode method.") 10 | q = Hurley::Query::Flat.new(opts).to_query_string 11 | api_obj = client.get("podcasts/#{podcast_id}/statistics/episode.json?#{q}") 12 | model.new(api_obj) 13 | end 14 | def overall(podcast_id: nil, opts: { timeframe: "recent" }) 15 | podcast_id ||= client.podcast_id 16 | q = Hurley::Query::Flat.new(opts).to_query_string 17 | api_obj = client.get("podcasts/#{podcast_id}/statistics/overall.json?#{q}") 18 | model.new(api_obj) 19 | end 20 | def all(podcast_id: nil) 21 | podcast_id ||= client.podcast_id 22 | api_obj_array = client.get("podcasts/#{podcast_id}/statistics.json") 23 | api_obj_array.map {|api_obj| model.new(api_obj) } 24 | end 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/simplecast/configurable.rb: -------------------------------------------------------------------------------- 1 | module Simplecast 2 | module Configurable 3 | attr_accessor :api_key, :podcast_id 4 | class << self 5 | def keys 6 | @keys ||= [ 7 | :api_key, 8 | :podcast_id 9 | ] 10 | end 11 | end 12 | def configure 13 | yield self 14 | end 15 | def options 16 | Hash[Simplecast::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}] 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/simplecast/episode.rb: -------------------------------------------------------------------------------- 1 | require 'ostruct' 2 | module Simplecast 3 | class Episode < OpenStruct 4 | include Simplecast::Model 5 | def embed 6 | Simplecast::Client::Episode.embed(id) 7 | end 8 | def podcast 9 | Simplecast::Client::Podcast.find(podcast_id) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/simplecast/model.rb: -------------------------------------------------------------------------------- 1 | module Simplecast 2 | module Model 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /lib/simplecast/podcast.rb: -------------------------------------------------------------------------------- 1 | require 'ostruct' 2 | module Simplecast 3 | class Podcast < OpenStruct 4 | include Simplecast::Model 5 | def episodes 6 | Simplecast::Client::Episode.all(id) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/simplecast/statistic.rb: -------------------------------------------------------------------------------- 1 | require 'ostruct' 2 | module Simplecast 3 | class Statistic < OpenStruct 4 | include Simplecast::Model 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/simplecast/version.rb: -------------------------------------------------------------------------------- 1 | module Simplecast 2 | VERSION = "0.1.0" 3 | end 4 | -------------------------------------------------------------------------------- /simplecast.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'simplecast/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "simplecast" 8 | spec.version = Simplecast::VERSION 9 | spec.authors = ["Jonathan Cutrell"] 10 | spec.email = ["jonathan@whiteboard.is"] 11 | spec.summary = %q{Simple wrapper for Simplecast podcasting service.} 12 | #spec.description = %q{} 13 | spec.homepage = "https://github.com/jcutrell/Simplecast" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(spec)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_runtime_dependency "hurley", "~> 0.1" 22 | spec.add_development_dependency "bundler", "~> 1.7" 23 | spec.add_development_dependency "rake", "~> 10.0" 24 | spec.add_development_dependency "rspec" 25 | end 26 | -------------------------------------------------------------------------------- /spec/simplecast/client/episode_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Simplecast::Client::Episode do 4 | it "#responds_to :all" do 5 | expect(Simplecast::Client::Episode).to respond_to(:all) 6 | end 7 | it "#responds_to :find" do 8 | expect(Simplecast::Client::Episode).to respond_to(:find) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/simplecast/client/podcast_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Simplecast::Client::Podcast do 4 | it "#responds_to :all" do 5 | expect(Simplecast::Client::Podcast).to respond_to(:all) 6 | end 7 | it "#responds_to :find" do 8 | expect(Simplecast::Client::Episode).to respond_to(:find) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/simplecast/client/resource_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Simplecast::Client::Resource do 4 | before do 5 | module Simplecast 6 | class Client 7 | module Test 8 | class << self 9 | include Simplecast::Client::Resource 10 | end 11 | end 12 | end 13 | end 14 | end 15 | it "should return the proper resource name" do 16 | tc = Simplecast::Client::Test 17 | expect(tc.resource_plural_name_lower).to eq("tests") 18 | end 19 | it "should return an instance of Simplecast::Client" do 20 | expect(Simplecast::Client::Test.client).to be_an_instance_of(Simplecast::Client) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/simplecast/client_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Simplecast::Client do 4 | 5 | describe "module configuration" do 6 | 7 | before do 8 | Simplecast.configure do |c| 9 | Simplecast::Configurable.keys.each do |key| 10 | c.send("#{key}=", "Some #{key}") 11 | end 12 | end 13 | end 14 | 15 | it "inherits the module configuration" do 16 | client = Simplecast::Client.new 17 | Simplecast::Configurable.keys.each do |key| 18 | expect(client.instance_variable_get(:"@#{key}")).to eq("Some #{key}") 19 | end 20 | end 21 | 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /spec/simplecast/episode_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Simplecast::Episode" do 4 | it "Should respond to embed" do 5 | episode = Simplecast::Episode.new 6 | expect(episode).to respond_to(:embed) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/simplecast/model_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe "Simplecast::Model" do 3 | before do 4 | class Simplecast::TestModel < OpenStruct 5 | include Simplecast::Model 6 | end 7 | end 8 | it "Should allow any attributes to be passed to it" do 9 | model = Simplecast::TestModel.new({attr_one: "Yes", something_else: "Whatever"}) 10 | expect(model).to respond_to(:attr_one) 11 | expect(model).to respond_to(:something_else) 12 | expect(model).not_to respond_to(:foozle) 13 | expect(model.attr_one).to eq("Yes") 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecast' 2 | --------------------------------------------------------------------------------