Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
wenbinf committed Apr 29, 2021
1 parent 9534686 commit b4a5a02
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@ build-iPhoneSimulator/

# Used by RuboCop. Remote config files pulled in from inherit_from directive.
# .rubocop-https?--*
.idea/
venv
.bundle
41 changes: 37 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ See the [Listen Notes Podcast API docs](https://www.listennotes.com/api/docs/).

Install the package with:
```sh
gem install podcast-api
gem install podcast_api
```


Expand All @@ -29,14 +29,47 @@ gem install podcast-api
## Usage

The library needs to be configured with your account's API key which is
available in your [Listen API Dashboard](https://www.listennotes.com/api/dashboard/#apps). Set `apiKey` to its
available in your [Listen API Dashboard](https://www.listennotes.com/api/dashboard/#apps). Set `api_key` to its
value:

```ruby

# TODO
require "podcast_api"

api_key = ENV["LISTEN_API_KEY"]
client = PodcastApi::Client.new(api_key: api_key)

begin
response = client.search(q: 'startup', type: 'episode')
puts JSON.parse(response.body)
rescue PodcastApi::AuthenticationError
puts 'Wrong api key'
rescue PodcastApi::InvalidRequestError
puts 'Client side errors, e.g., wrong parameters'
rescue PodcastApi::NotFoundError
puts 'Not found'
rescue PodcastApi::RateLimitError
puts 'Reached quota limit'
rescue PodcastApi::APIConnectionError
puts 'Failed to connect to Listen API servers'
rescue PodcastApi::PodcastApiError
puts 'Server side errors'
else
puts "Free Quota per month: #{response.headers['X-ListenAPI-FreeQuota']}"
puts "Usage this month: #{response.headers['X-ListenAPI-Usage']}"
puts "Next billing date: #{response.headers['X-Listenapi-NextBillingDate']}"
end
```

If `apiKey` is null, then we'll connect to a [mock server](https://www.listennotes.com/api/tutorials/#faq0) that returns fake data for testing purposes.
If `api_key` is nil, then we'll connect to a [mock server](https://www.listennotes.com/api/tutorials/#faq0) that returns fake data for testing purposes.

You can see all available API endpoints and parameters on the API Docs page at [listennotes.com/api/docs/](https://www.listennotes.com/api/docs/).

### Handling exceptions

Unsuccessful requests raise exceptions. The class of the exception will reflect
the sort of error that occurred.

All exception classes can be found in [this file](https://github.com/ListenNotes/podcast-api-ruby/blob/main/lib/errors.rb).

And you can see some sample code [here](https://github.com/ListenNotes/podcast-api-ruby/blob/main/examples/sample.rb).
2 changes: 2 additions & 0 deletions examples/Gemfile
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
source 'https://rubygems.org'

gem "podcast_api", path: "../"
9 changes: 9 additions & 0 deletions examples/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ PATH
remote: ..
specs:
podcast_api (1.0.1)
httparty

GEM
remote: https://rubygems.org/
specs:
httparty (0.18.1)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2021.0225)
multi_xml (0.6.0)

PLATFORMS
ruby
Expand Down
76 changes: 76 additions & 0 deletions examples/sample.rb
Original file line number Diff line number Diff line change
@@ -1 +1,77 @@
require "podcast_api"

api_key = ENV["LISTEN_API_KEY"]
client = PodcastApi::Client.new(api_key: api_key)

begin
response = client.search(q: 'startup')
puts JSON.parse(response.body)
rescue PodcastApi::AuthenticationError
puts 'Wrong api key'
rescue PodcastApi::InvalidRequestError
puts 'Client side errors, e.g., wrong parameters'
rescue PodcastApi::NotFoundError
puts 'Not found'
rescue PodcastApi::RateLimitError
puts 'Reached quota limit'
rescue PodcastApi::APIConnectionError
puts 'Failed to connect to Listen API servers'
rescue PodcastApi::PodcastApiError
puts 'Server side errors'
else
puts "Free Quota per month: #{response.headers['X-ListenAPI-FreeQuota']}"
puts "Usage this month: #{response.headers['X-ListenAPI-Usage']}"
puts "Next billing date: #{response.headers['X-Listenapi-NextBillingDate']}"
end


# response = client.typeahead(q: 'startup', show_podcasts: 1)
# puts JSON.parse(response.body)

# response = client.fetch_best_podcasts()
# puts JSON.parse(response.body)

# response = client.fetch_podcast_by_id(id: '4d3fe717742d4963a85562e9f84d8c79')
# puts JSON.parse(response.body)

# response = client.fetch_episode_by_id(id: '6b6d65930c5a4f71b254465871fed370')
# puts JSON.parse(response.body)

# response = client.batch_fetch_podcasts(ids: '3302bc71139541baa46ecb27dbf6071a,68faf62be97149c280ebcc25178aa731,37589a3e121e40debe4cef3d9638932a,9cf19c590ff0484d97b18b329fed0c6a')
# puts JSON.parse(response.body)

# response = client.batch_fetch_episodes(ids: 'c577d55b2b2b483c969fae3ceb58e362,0f34a9099579490993eec9e8c8cebb82')
# puts JSON.parse(response.body)

# response = client.fetch_curated_podcasts_list_by_id(id: 'SDFKduyJ47r')
# puts JSON.parse(response.body)

# response = client.fetch_podcast_genres()
# puts JSON.parse(response.body)

# response = client.fetch_podcast_regions()
# puts JSON.parse(response.body)

# response = client.fetch_podcast_languages()
# puts JSON.parse(response.body)

# response = client.just_listen()
# puts JSON.parse(response.body)

# response = client.fetch_recommendations_for_podcast(id: '25212ac3c53240a880dd5032e547047b')
# puts JSON.parse(response.body)

# response = client.fetch_recommendations_for_episode(id: '914a9deafa5340eeaa2859c77f275799')
# puts JSON.parse(response.body)

# response = client.fetch_playlist_by_id(id: 'm1pe7z60bsw')
# puts JSON.parse(response.body)

# response = client.fetch_my_playlists()
# puts JSON.parse(response.body)

# response = client.submit_podcast(rss: 'https://feeds.megaphone.fm/committed')
# puts JSON.parse(response.body)

# response = client.delete_podcast(id: '4d3fe717742d4963a85562e9f84d8c79')
# puts JSON.parse(response.body)
26 changes: 26 additions & 0 deletions lib/errors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module PodcastApi
# PodcastApiError is the base error from which all other more specific PodcastApi
# errors derive.
class PodcastApiError < StandardError
end

class AuthenticationError < PodcastApiError
end

class APIConnectionError < PodcastApiError
end

class InvalidRequestError < PodcastApiError
end

class RateLimitError < PodcastApiError
end

class NotFoundError < PodcastApiError
end

class APIConnectionError < PodcastApiError
end
end
137 changes: 133 additions & 4 deletions lib/podcast_api.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,140 @@
# frozen_string_literal: true

require "net/http"
require 'httparty'

# Version
require "version"

puts PodcastApi::VERSION
require 'version'
require 'errors'

module PodcastApi

class Client
include HTTParty

@@BASE_URL_PROD = 'https://listen-api.listennotes.com/api/v2'
@@BASE_URL_TEST = 'https://listen-api-test.listennotes.com/api/v2'

def initialize(api_key: nil, user_agent: nil)
@api_key = api_key
@base_url = api_key ? @@BASE_URL_PROD : @@BASE_URL_TEST
@headers = {
'X-ListenAPI-Key' => @api_key,
'User-Agent' => user_agent ? user_agent : "podcasts-api-ruby #{VERSION}"
}
puts @headers
end

protected
def get_response(response:)
if response.code == 200
return response
elsif response.code == 400
raise InvalidRequestError.new 'something wrong on your end (client side errors), e.g., missing required parameters'
elsif response.code == 401
raise AuthenticationError.new 'wrong api key or your account is suspended'
elsif response.code == 404
raise NotFoundError.new 'endpoint not exist, or podcast / episode not exist'
elsif response.code == 429
raise RateLimitError.new 'you are using FREE plan and you exceed the quota limit'
else
raise PodcastApiError.new 'something wrong on our end (unexpected server errors)'
end
end

def send_http_request(http_method, *args)
begin
response = HTTParty.public_send(http_method, *args)
rescue SocketError
raise APIConnectionError.new 'Failed to connect to Listen API servers'
else
return get_response(response: response)
end
end

public
def search(**kwargs)
return send_http_request('get', "#{@base_url}/search", {query: kwargs, headers: @headers})
end

def typeahead(**kwargs)
return send_http_request('get', "#{@base_url}/typeahead", {query: kwargs, headers: @headers})
end

def fetch_best_podcasts(**kwargs)
return send_http_request('get', "#{@base_url}/best_podcasts", {query: kwargs, headers: @headers})
end

def fetch_podcast_by_id(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/podcasts/#{id}", {query: kwargs, headers: @headers})
end

def fetch_episode_by_id(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/episodes/#{id}", {query: kwargs, headers: @headers})
end

def batch_fetch_podcasts(**kwargs)
return send_http_request('post', "#{@base_url}/podcasts", {body: kwargs, headers: @headers})
end

def batch_fetch_episodes(**kwargs)
return send_http_request('post', "#{@base_url}/episodes", {body: kwargs, headers: @headers})
end

def fetch_curated_podcasts_list_by_id(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/curated_podcasts/#{id}", {query: kwargs, headers: @headers})
end

def fetch_curated_podcasts_lists(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/curated_podcasts", {query: kwargs, headers: @headers})
end

def fetch_podcast_genres(**kwargs)
return send_http_request('get', "#{@base_url}/genres", {query: kwargs, headers: @headers})
end

def fetch_podcast_regions(**kwargs)
return send_http_request('get', "#{@base_url}/regions", {query: kwargs, headers: @headers})
end

def fetch_podcast_languages(**kwargs)
return send_http_request('get', "#{@base_url}/languages", {query: kwargs, headers: @headers})
end

def just_listen(**kwargs)
return send_http_request('get', "#{@base_url}/just_listen", {query: kwargs, headers: @headers})
end

def fetch_recommendations_for_podcast(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/podcasts/#{id}/recommendations", {query: kwargs, headers: @headers})
end

def fetch_recommendations_for_episode(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/episodes/#{id}/recommendations", {query: kwargs, headers: @headers})
end

def fetch_playlist_by_id(**kwargs)
id = kwargs.delete(:id)
return send_http_request('get', "#{@base_url}/playlists/#{id}", {query: kwargs, headers: @headers})
end

def fetch_my_playlists(**kwargs)
return send_http_request('get', "#{@base_url}/playlists", {query: kwargs, headers: @headers})
end

def submit_podcast(**kwargs)
return send_http_request('post', "#{@base_url}/podcasts/submit", {body: kwargs, headers: @headers})
end

def delete_podcast(**kwargs)
id = kwargs.delete(:id)
return send_http_request('delete', "#{@base_url}/podcasts/#{id}", {query: kwargs, headers: @headers})
end
end

end
2 changes: 1 addition & 1 deletion podcast_api.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Gem::Specification.new do |s|
s.email = "[email protected]"
s.homepage = "https://www.listennotes.com/api/"
s.license = "MIT"

s.add_runtime_dependency "httparty"
s.metadata = {
"bug_tracker_uri" => "https://github.com/ListenNotes/podcast-api-ruby/issues",
"changelog_uri" =>
Expand Down

0 comments on commit b4a5a02

Please sign in to comment.