Skip to content

Commit b4a5a02

Browse files
committed
Initial commit
1 parent 9534686 commit b4a5a02

File tree

8 files changed

+287
-9
lines changed

8 files changed

+287
-9
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,6 @@ build-iPhoneSimulator/
5454

5555
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
5656
# .rubocop-https?--*
57+
.idea/
58+
venv
59+
.bundle

README.md

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ See the [Listen Notes Podcast API docs](https://www.listennotes.com/api/docs/).
1818

1919
Install the package with:
2020
```sh
21-
gem install podcast-api
21+
gem install podcast_api
2222
```
2323

2424

@@ -29,14 +29,47 @@ gem install podcast-api
2929
## Usage
3030

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

3535
```ruby
3636

37-
# TODO
37+
require "podcast_api"
38+
39+
api_key = ENV["LISTEN_API_KEY"]
40+
client = PodcastApi::Client.new(api_key: api_key)
41+
42+
begin
43+
response = client.search(q: 'startup', type: 'episode')
44+
puts JSON.parse(response.body)
45+
rescue PodcastApi::AuthenticationError
46+
puts 'Wrong api key'
47+
rescue PodcastApi::InvalidRequestError
48+
puts 'Client side errors, e.g., wrong parameters'
49+
rescue PodcastApi::NotFoundError
50+
puts 'Not found'
51+
rescue PodcastApi::RateLimitError
52+
puts 'Reached quota limit'
53+
rescue PodcastApi::APIConnectionError
54+
puts 'Failed to connect to Listen API servers'
55+
rescue PodcastApi::PodcastApiError
56+
puts 'Server side errors'
57+
else
58+
puts "Free Quota per month: #{response.headers['X-ListenAPI-FreeQuota']}"
59+
puts "Usage this month: #{response.headers['X-ListenAPI-Usage']}"
60+
puts "Next billing date: #{response.headers['X-Listenapi-NextBillingDate']}"
61+
end
3862
```
3963

40-
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.
64+
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.
4165

4266
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/).
67+
68+
### Handling exceptions
69+
70+
Unsuccessful requests raise exceptions. The class of the exception will reflect
71+
the sort of error that occurred.
72+
73+
All exception classes can be found in [this file](https://github.com/ListenNotes/podcast-api-ruby/blob/main/lib/errors.rb).
74+
75+
And you can see some sample code [here](https://github.com/ListenNotes/podcast-api-ruby/blob/main/examples/sample.rb).

examples/Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
source 'https://rubygems.org'
2+
13
gem "podcast_api", path: "../"

examples/Gemfile.lock

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@ PATH
22
remote: ..
33
specs:
44
podcast_api (1.0.1)
5+
httparty
56

67
GEM
8+
remote: https://rubygems.org/
79
specs:
10+
httparty (0.18.1)
11+
mime-types (~> 3.0)
12+
multi_xml (>= 0.5.2)
13+
mime-types (3.3.1)
14+
mime-types-data (~> 3.2015)
15+
mime-types-data (3.2021.0225)
16+
multi_xml (0.6.0)
817

918
PLATFORMS
1019
ruby

examples/sample.rb

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,77 @@
11
require "podcast_api"
2+
3+
api_key = ENV["LISTEN_API_KEY"]
4+
client = PodcastApi::Client.new(api_key: api_key)
5+
6+
begin
7+
response = client.search(q: 'startup')
8+
puts JSON.parse(response.body)
9+
rescue PodcastApi::AuthenticationError
10+
puts 'Wrong api key'
11+
rescue PodcastApi::InvalidRequestError
12+
puts 'Client side errors, e.g., wrong parameters'
13+
rescue PodcastApi::NotFoundError
14+
puts 'Not found'
15+
rescue PodcastApi::RateLimitError
16+
puts 'Reached quota limit'
17+
rescue PodcastApi::APIConnectionError
18+
puts 'Failed to connect to Listen API servers'
19+
rescue PodcastApi::PodcastApiError
20+
puts 'Server side errors'
21+
else
22+
puts "Free Quota per month: #{response.headers['X-ListenAPI-FreeQuota']}"
23+
puts "Usage this month: #{response.headers['X-ListenAPI-Usage']}"
24+
puts "Next billing date: #{response.headers['X-Listenapi-NextBillingDate']}"
25+
end
26+
27+
28+
# response = client.typeahead(q: 'startup', show_podcasts: 1)
29+
# puts JSON.parse(response.body)
30+
31+
# response = client.fetch_best_podcasts()
32+
# puts JSON.parse(response.body)
33+
34+
# response = client.fetch_podcast_by_id(id: '4d3fe717742d4963a85562e9f84d8c79')
35+
# puts JSON.parse(response.body)
36+
37+
# response = client.fetch_episode_by_id(id: '6b6d65930c5a4f71b254465871fed370')
38+
# puts JSON.parse(response.body)
39+
40+
# response = client.batch_fetch_podcasts(ids: '3302bc71139541baa46ecb27dbf6071a,68faf62be97149c280ebcc25178aa731,37589a3e121e40debe4cef3d9638932a,9cf19c590ff0484d97b18b329fed0c6a')
41+
# puts JSON.parse(response.body)
42+
43+
# response = client.batch_fetch_episodes(ids: 'c577d55b2b2b483c969fae3ceb58e362,0f34a9099579490993eec9e8c8cebb82')
44+
# puts JSON.parse(response.body)
45+
46+
# response = client.fetch_curated_podcasts_list_by_id(id: 'SDFKduyJ47r')
47+
# puts JSON.parse(response.body)
48+
49+
# response = client.fetch_podcast_genres()
50+
# puts JSON.parse(response.body)
51+
52+
# response = client.fetch_podcast_regions()
53+
# puts JSON.parse(response.body)
54+
55+
# response = client.fetch_podcast_languages()
56+
# puts JSON.parse(response.body)
57+
58+
# response = client.just_listen()
59+
# puts JSON.parse(response.body)
60+
61+
# response = client.fetch_recommendations_for_podcast(id: '25212ac3c53240a880dd5032e547047b')
62+
# puts JSON.parse(response.body)
63+
64+
# response = client.fetch_recommendations_for_episode(id: '914a9deafa5340eeaa2859c77f275799')
65+
# puts JSON.parse(response.body)
66+
67+
# response = client.fetch_playlist_by_id(id: 'm1pe7z60bsw')
68+
# puts JSON.parse(response.body)
69+
70+
# response = client.fetch_my_playlists()
71+
# puts JSON.parse(response.body)
72+
73+
# response = client.submit_podcast(rss: 'https://feeds.megaphone.fm/committed')
74+
# puts JSON.parse(response.body)
75+
76+
# response = client.delete_podcast(id: '4d3fe717742d4963a85562e9f84d8c79')
77+
# puts JSON.parse(response.body)

lib/errors.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
module PodcastApi
4+
# PodcastApiError is the base error from which all other more specific PodcastApi
5+
# errors derive.
6+
class PodcastApiError < StandardError
7+
end
8+
9+
class AuthenticationError < PodcastApiError
10+
end
11+
12+
class APIConnectionError < PodcastApiError
13+
end
14+
15+
class InvalidRequestError < PodcastApiError
16+
end
17+
18+
class RateLimitError < PodcastApiError
19+
end
20+
21+
class NotFoundError < PodcastApiError
22+
end
23+
24+
class APIConnectionError < PodcastApiError
25+
end
26+
end

lib/podcast_api.rb

Lines changed: 133 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,140 @@
11
# frozen_string_literal: true
22

3-
require "net/http"
3+
require 'httparty'
44

55
# Version
6-
require "version"
7-
8-
puts PodcastApi::VERSION
6+
require 'version'
7+
require 'errors'
98

109
module PodcastApi
10+
11+
class Client
12+
include HTTParty
13+
14+
@@BASE_URL_PROD = 'https://listen-api.listennotes.com/api/v2'
15+
@@BASE_URL_TEST = 'https://listen-api-test.listennotes.com/api/v2'
16+
17+
def initialize(api_key: nil, user_agent: nil)
18+
@api_key = api_key
19+
@base_url = api_key ? @@BASE_URL_PROD : @@BASE_URL_TEST
20+
@headers = {
21+
'X-ListenAPI-Key' => @api_key,
22+
'User-Agent' => user_agent ? user_agent : "podcasts-api-ruby #{VERSION}"
23+
}
24+
puts @headers
25+
end
26+
27+
protected
28+
def get_response(response:)
29+
if response.code == 200
30+
return response
31+
elsif response.code == 400
32+
raise InvalidRequestError.new 'something wrong on your end (client side errors), e.g., missing required parameters'
33+
elsif response.code == 401
34+
raise AuthenticationError.new 'wrong api key or your account is suspended'
35+
elsif response.code == 404
36+
raise NotFoundError.new 'endpoint not exist, or podcast / episode not exist'
37+
elsif response.code == 429
38+
raise RateLimitError.new 'you are using FREE plan and you exceed the quota limit'
39+
else
40+
raise PodcastApiError.new 'something wrong on our end (unexpected server errors)'
41+
end
42+
end
43+
44+
def send_http_request(http_method, *args)
45+
begin
46+
response = HTTParty.public_send(http_method, *args)
47+
rescue SocketError
48+
raise APIConnectionError.new 'Failed to connect to Listen API servers'
49+
else
50+
return get_response(response: response)
51+
end
52+
end
53+
54+
public
55+
def search(**kwargs)
56+
return send_http_request('get', "#{@base_url}/search", {query: kwargs, headers: @headers})
57+
end
58+
59+
def typeahead(**kwargs)
60+
return send_http_request('get', "#{@base_url}/typeahead", {query: kwargs, headers: @headers})
61+
end
62+
63+
def fetch_best_podcasts(**kwargs)
64+
return send_http_request('get', "#{@base_url}/best_podcasts", {query: kwargs, headers: @headers})
65+
end
66+
67+
def fetch_podcast_by_id(**kwargs)
68+
id = kwargs.delete(:id)
69+
return send_http_request('get', "#{@base_url}/podcasts/#{id}", {query: kwargs, headers: @headers})
70+
end
71+
72+
def fetch_episode_by_id(**kwargs)
73+
id = kwargs.delete(:id)
74+
return send_http_request('get', "#{@base_url}/episodes/#{id}", {query: kwargs, headers: @headers})
75+
end
76+
77+
def batch_fetch_podcasts(**kwargs)
78+
return send_http_request('post', "#{@base_url}/podcasts", {body: kwargs, headers: @headers})
79+
end
80+
81+
def batch_fetch_episodes(**kwargs)
82+
return send_http_request('post', "#{@base_url}/episodes", {body: kwargs, headers: @headers})
83+
end
84+
85+
def fetch_curated_podcasts_list_by_id(**kwargs)
86+
id = kwargs.delete(:id)
87+
return send_http_request('get', "#{@base_url}/curated_podcasts/#{id}", {query: kwargs, headers: @headers})
88+
end
89+
90+
def fetch_curated_podcasts_lists(**kwargs)
91+
id = kwargs.delete(:id)
92+
return send_http_request('get', "#{@base_url}/curated_podcasts", {query: kwargs, headers: @headers})
93+
end
94+
95+
def fetch_podcast_genres(**kwargs)
96+
return send_http_request('get', "#{@base_url}/genres", {query: kwargs, headers: @headers})
97+
end
98+
99+
def fetch_podcast_regions(**kwargs)
100+
return send_http_request('get', "#{@base_url}/regions", {query: kwargs, headers: @headers})
101+
end
102+
103+
def fetch_podcast_languages(**kwargs)
104+
return send_http_request('get', "#{@base_url}/languages", {query: kwargs, headers: @headers})
105+
end
106+
107+
def just_listen(**kwargs)
108+
return send_http_request('get', "#{@base_url}/just_listen", {query: kwargs, headers: @headers})
109+
end
110+
111+
def fetch_recommendations_for_podcast(**kwargs)
112+
id = kwargs.delete(:id)
113+
return send_http_request('get', "#{@base_url}/podcasts/#{id}/recommendations", {query: kwargs, headers: @headers})
114+
end
115+
116+
def fetch_recommendations_for_episode(**kwargs)
117+
id = kwargs.delete(:id)
118+
return send_http_request('get', "#{@base_url}/episodes/#{id}/recommendations", {query: kwargs, headers: @headers})
119+
end
120+
121+
def fetch_playlist_by_id(**kwargs)
122+
id = kwargs.delete(:id)
123+
return send_http_request('get', "#{@base_url}/playlists/#{id}", {query: kwargs, headers: @headers})
124+
end
125+
126+
def fetch_my_playlists(**kwargs)
127+
return send_http_request('get', "#{@base_url}/playlists", {query: kwargs, headers: @headers})
128+
end
129+
130+
def submit_podcast(**kwargs)
131+
return send_http_request('post', "#{@base_url}/podcasts/submit", {body: kwargs, headers: @headers})
132+
end
133+
134+
def delete_podcast(**kwargs)
135+
id = kwargs.delete(:id)
136+
return send_http_request('delete', "#{@base_url}/podcasts/#{id}", {query: kwargs, headers: @headers})
137+
end
138+
end
139+
11140
end

podcast_api.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
1515
s.email = "[email protected]"
1616
s.homepage = "https://www.listennotes.com/api/"
1717
s.license = "MIT"
18-
18+
s.add_runtime_dependency "httparty"
1919
s.metadata = {
2020
"bug_tracker_uri" => "https://github.com/ListenNotes/podcast-api-ruby/issues",
2121
"changelog_uri" =>

0 commit comments

Comments
 (0)