podcast_api 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2359319833e4c907123b311fab199141119a0f4f24cd7f1ff22bbd765a96ddd2
4
+ data.tar.gz: 1b1c6746481927ba1b7bf3d56c85c6fdd126f5af3eeb89586591f4eebf48b0dd
5
+ SHA512:
6
+ metadata.gz: fe91bc1773b38f0ede9be6ebda3dc8f6c05dd34cf4727d38772b996ef7096268c66cb6d066de20eeba76abd920e051684bf7afcd84152c73c3bfc4f0bab4638e
7
+ data.tar.gz: 62e082095fb3f0a2b6a73c63ccf8b1f5b7f1a228263abe2bcc6809a47c7cb2b0dc934b5f2c1267696cb5c78a3a4fdc8879fe0a245d155321789d3766ffe5ce94
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Listen Notes
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.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Podcast API Ruby Library
2
+
3
+ [![Build Status](https://travis-ci.com/ListenNotes/podcast-api-ruby.svg?branch=main)](https://travis-ci.com/ListenNotes/podcast-api-ruby)
4
+
5
+ The Podcast API Ruby library provides convenient access to the [Listen Notes Podcast API](https://www.listennotes.com/api/) from
6
+ applications written in Ruby.
7
+
8
+ Simple and no-nonsense podcast search & directory API. Search the meta data of all podcasts and episodes by people, places, or topics.
9
+
10
+ <a href="https://www.listennotes.com/api/"><img src="https://raw.githubusercontent.com/ListenNotes/ListenApiDemo/master/web/src/powered_by_listennotes.png" width="300" /></a>
11
+
12
+ ## Documentation
13
+
14
+ See the [Listen Notes Podcast API docs](https://www.listennotes.com/api/docs/).
15
+
16
+
17
+ ## Installation
18
+
19
+ Install the package with:
20
+ ```sh
21
+ gem install podcast_api
22
+ ```
23
+
24
+
25
+ ### Requirements
26
+
27
+ - Ruby 2.3+
28
+
29
+ ## Usage
30
+
31
+ 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 `api_key` to its
33
+ value:
34
+
35
+ ```ruby
36
+
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
62
+ ```
63
+
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.
65
+
66
+ 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).
data/examples/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "podcast_api", path: "../"
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ podcast_api (1.0.1)
5
+ httparty
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ 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)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ podcast_api!
23
+
24
+ BUNDLED WITH
25
+ 1.17.2
@@ -0,0 +1,77 @@
1
+ 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)
data/lib/errors.rb ADDED
@@ -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
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+
5
+ # Version
6
+ require 'version'
7
+ require 'errors'
8
+
9
+ 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
+
140
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PodcastApi
4
+ VERSION = "1.0.1"
5
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift(::File.join(::File.dirname(__FILE__), "lib"))
4
+
5
+ require "version"
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "podcast_api"
9
+ s.version = PodcastApi::VERSION
10
+ s.required_ruby_version = ">= 2.3.0"
11
+ s.summary = "Ruby bindings for the Listen Notes Podcast API"
12
+ s.description = "Listen Notes is the best podcast search engine and api. " \
13
+ "See https://www.listennotes.com/api/ for details."
14
+ s.author = "Listen Notes, Inc."
15
+ s.email = "hello@listennotes.com"
16
+ s.homepage = "https://www.listennotes.com/api/"
17
+ s.license = "MIT"
18
+ s.add_runtime_dependency "httparty"
19
+ s.metadata = {
20
+ "bug_tracker_uri" => "https://github.com/ListenNotes/podcast-api-ruby/issues",
21
+ "changelog_uri" =>
22
+ "https://github.com/ListenNotes/podcast-api-ruby/releases",
23
+ "documentation_uri" => "https://www.listennotes.com/api/docs/",
24
+ "github_repo" => "https://github.com/ListenNotes/podcast-api-ruby",
25
+ "homepage_uri" => "https://www.listennotes.com/api/",
26
+ "source_code_uri" => "https://github.com/ListenNotes/podcast-api-ruby",
27
+ }
28
+
29
+ ignored = Regexp.union(
30
+ /\A\.editorconfig/,
31
+ /\A\.git/,
32
+ /\A\.rubocop/,
33
+ /\A\.travis.yml/,
34
+ /\Atest/
35
+ )
36
+ s.files = `git ls-files`.split("\n").reject { |f| ignored.match(f) }
37
+ s.executables = `git ls-files -- bin/*`.split("\n")
38
+ .map { |f| ::File.basename(f) }
39
+ s.require_paths = ["lib"]
40
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: podcast_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Listen Notes, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Listen Notes is the best podcast search engine and api. See https://www.listennotes.com/api/
28
+ for details.
29
+ email: hello@listennotes.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.md
36
+ - examples/Gemfile
37
+ - examples/Gemfile.lock
38
+ - examples/sample.rb
39
+ - lib/errors.rb
40
+ - lib/podcast_api.rb
41
+ - lib/version.rb
42
+ - podcast_api.gemspec
43
+ homepage: https://www.listennotes.com/api/
44
+ licenses:
45
+ - MIT
46
+ metadata:
47
+ bug_tracker_uri: https://github.com/ListenNotes/podcast-api-ruby/issues
48
+ changelog_uri: https://github.com/ListenNotes/podcast-api-ruby/releases
49
+ documentation_uri: https://www.listennotes.com/api/docs/
50
+ github_repo: https://github.com/ListenNotes/podcast-api-ruby
51
+ homepage_uri: https://www.listennotes.com/api/
52
+ source_code_uri: https://github.com/ListenNotes/podcast-api-ruby
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.0
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubygems_version: 3.0.3
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Ruby bindings for the Listen Notes Podcast API
72
+ test_files: []