7
7
from typing import Any , Iterable , List , Mapping , MutableMapping , Optional , Tuple
8
8
import logging
9
9
import requests
10
+ import time
10
11
from airbyte_cdk .sources import AbstractSource
11
12
from airbyte_cdk .sources .streams import Stream
12
13
from airbyte_cdk .sources .streams .http import HttpStream , HttpSubStream
22
23
# Basic full refresh stream
23
24
class SimplecastFectherStream (HttpStream ):
24
25
url_base = "https://api.simplecast.com/"
26
+ primary_key = None
27
+
25
28
26
29
def next_page_token (self , response : requests .Response ) -> Optional [Mapping [str , Any ]]:
27
- return None
30
+ pages = response .json ().get ('pages' )
31
+ if pages and pages .get ('next' ):
32
+ time .sleep (2 )
33
+ return {
34
+ 'limit' : pages .get ('limit' ),
35
+ 'offset' : pages .get ('limit' )* pages .get ('current' )
36
+ }
37
+
38
+ def request_params (
39
+ self ,
40
+ stream_state : Optional [Mapping [str , Any ]],
41
+ stream_slice : Optional [Mapping [str , Any ]] = None ,
42
+ next_page_token : Optional [Mapping [str , Any ]] = None ,
43
+ ) -> MutableMapping [str , Any ]:
44
+ if next_page_token :
45
+ return next_page_token
46
+
28
47
29
48
class Podcast (SimplecastFectherStream ):
30
49
@@ -55,11 +74,12 @@ def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapp
55
74
}
56
75
yield podcast
57
76
58
- class Episode (HttpSubStream , Podcast ):
77
+ class Episode (HttpSubStream , SimplecastFectherStream ):
59
78
primary_key = "episode_id"
60
79
61
- def __init__ (self , ** kwargs ):
62
- super ().__init__ (Podcast (** kwargs ), ** kwargs )
80
+ @property
81
+ def use_cache (self ) -> bool :
82
+ return True
63
83
64
84
def path (
65
85
self ,
@@ -89,11 +109,11 @@ def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapp
89
109
}
90
110
yield episode
91
111
92
- class AnalyticSubStream (HttpSubStream , Podcast , ABC ):
112
+ class AnalyticSubStream (HttpSubStream , SimplecastFectherStream , ABC ):
93
113
primary_key = None
94
114
95
115
def __init__ (self , endpoint :str , keys_dict :dict , collection_name :str , ** kwargs ):
96
- super ().__init__ (Podcast ( ** kwargs ), ** kwargs )
116
+ super ().__init__ (** kwargs )
97
117
self .endpoint = endpoint
98
118
self .keys_dict = keys_dict
99
119
self .collection_name = collection_name
@@ -151,7 +171,7 @@ def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapp
151
171
}
152
172
yield analytic_episode
153
173
154
- class AnalyticDownload (AnalyticSubStream , Podcast ):
174
+ class AnalyticDownload (AnalyticSubStream ):
155
175
156
176
def __init__ (self , ** kwargs ):
157
177
super ().__init__ (endpoint = "downloads" , keys_dict = DOWNLOADS_KEY , collection_name = "by_interval" , ** kwargs )
@@ -171,22 +191,57 @@ class TechnologyListeningMethod(AnalyticSubStream):
171
191
def __init__ (self , ** kwargs ):
172
192
super ().__init__ (endpoint = "technology/listening_methods" , keys_dict = TECH_KEY , collection_name = "collection" , ** kwargs )
173
193
194
+ class AnalyticEpisodeV2 (HttpSubStream ,SimplecastFectherStream ):
195
+ def path (
196
+ self ,
197
+ stream_state : Mapping [str , Any ] = None ,
198
+ stream_slice : Mapping [str , Any ] = None ,
199
+ next_page_token : Mapping [str , Any ] = None
200
+ ) -> str :
201
+ episode_id = stream_slice .get ("parent" ).get ("id" )
202
+ return f"analytics?episode={ episode_id } "
203
+
204
+ def parse_response (self , response : requests .Response , ** kwargs ) -> Iterable [Mapping ]:
205
+ data = response .json ()
206
+ logger .debug ("Response: %s" , data )
207
+ yield data
208
+
209
+ class AnalyticPodcastV2 (HttpSubStream , SimplecastFectherStream ):
210
+ def path (
211
+ self ,
212
+ stream_state : Mapping [str , Any ] = None ,
213
+ stream_slice : Mapping [str , Any ] = None ,
214
+ next_page_token : Mapping [str , Any ] = None
215
+ ) -> str :
216
+ podcast_id = stream_slice .get ("parent" ).get ("id" )
217
+ return f"analytics?podcast={ podcast_id } "
218
+
219
+ def parse_response (self , response : requests .Response , ** kwargs ) -> Iterable [Mapping ]:
220
+ data = response .json ()
221
+ logger .debug ("Response: %s" , data )
222
+ yield data
223
+
224
+
174
225
175
226
# Source
176
227
class SourceSimplecastFecther (AbstractSource ):
177
228
def check_connection (self , logger , config ) -> Tuple [bool , any ]:
178
229
return True , None
179
230
180
231
def streams (self , config : Mapping [str , Any ]) -> List [Stream ]:
181
- auth = TokenAuthenticator (token = config ["api_key" ])
232
+ auth = TokenAuthenticator (token = config ["api_key" ])
233
+ podcasts = Podcast (authenticator = auth )
234
+ episodes = Episode (authenticator = auth , parent = podcasts )
182
235
return [
183
- Podcast (authenticator = auth ),
184
- Episode (authenticator = auth ),
185
- AnalyticLocation (authenticator = auth ),
186
- AnalyticTimeOfWeek (authenticator = auth ),
187
- AnalyticEpisode (authenticator = auth ),
188
- AnalyticDownload (authenticator = auth ),
189
- TechnologyApplication (authenticator = auth ),
190
- TechnologyDeviceClass (authenticator = auth ),
191
- TechnologyListeningMethod (authenticator = auth )
236
+ podcasts ,
237
+ episodes ,
238
+ AnalyticLocation (authenticator = auth , parent = podcasts ),
239
+ AnalyticTimeOfWeek (authenticator = auth , parent = podcasts ),
240
+ AnalyticEpisode (authenticator = auth , parent = podcasts ),
241
+ AnalyticDownload (authenticator = auth ,parent = podcasts ),
242
+ TechnologyApplication (authenticator = auth , parent = podcasts ),
243
+ TechnologyDeviceClass (authenticator = auth , parent = podcasts ),
244
+ TechnologyListeningMethod (authenticator = auth , parent = podcasts ),
245
+ AnalyticEpisodeV2 (authenticator = auth , parent = episodes ),
246
+ AnalyticPodcastV2 (authenticator = auth , parent = podcasts )
192
247
]
0 commit comments