- commit
- e9d75869afd2162c2cbfed6b2d45ea6d53182a8f
- parent
- be744a9c23511d92ca273c8987b9b58cef2a34cd
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2024-02-13 18:13
tabs to spaces
Diffstat
| M | audiothek.py | 224 | ++++++++++++++++++++++++++++++------------------------------ |
1 files changed, 112 insertions, 112 deletions
diff --git a/audiothek.py b/audiothek.py
@@ -9,138 +9,138 @@ COUNT = 20 9 9 10 10 QUERY = """ 11 11 query ProgramSetEpisodesQuery($id:ID!, $offset:Int!, $count:Int!) {12 -1 result:programSet(id:$id) {13 -1 id14 -1 title15 -1 path16 -1 image{ url1X1 }17 -1 publicationService{ title }18 -1 items(offset:$offset first:$count orderBy:PUBLISH_DATE_DESC filter:{isPublished:{equalTo:true}}) {19 -1 pageInfo{hasNextPage endCursor}20 -1 nodes{21 -1 id22 -1 title23 -1 publishDate24 -1 summary25 -1 duration26 -1 path27 -1 image{ url1X1 }28 -1 audios{ url }29 -1 }30 -1 }31 -1 }-1 12 result:programSet(id:$id) { -1 13 id -1 14 title -1 15 path -1 16 image{ url1X1 } -1 17 publicationService{ title } -1 18 items(offset:$offset first:$count orderBy:PUBLISH_DATE_DESC filter:{isPublished:{equalTo:true}}) { -1 19 pageInfo{hasNextPage endCursor} -1 20 nodes{ -1 21 id -1 22 title -1 23 publishDate -1 24 summary -1 25 duration -1 26 path -1 27 image{ url1X1 } -1 28 audios{ url } -1 29 } -1 30 } -1 31 } 32 32 }33 -1 """.replace('\t', '').replace('\n', ' ').strip()-1 33 """.replace(' ', '').replace('\n', ' ').strip() 34 34 35 35 FEED = """<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">36 -1 <channel>37 -1 <title>{title}</title>38 -1 <link>{url}</link>39 -1 <image>40 -1 <url>{img_url}</url>41 -1 <width>{img_size}</width>42 -1 <height>{img_size}</height>43 -1 </image>-1 36 <channel> -1 37 <title>{title}</title> -1 38 <link>{url}</link> -1 39 <image> -1 40 <url>{img_url}</url> -1 41 <width>{img_size}</width> -1 42 <height>{img_size}</height> -1 43 </image> 44 44 45 45 {entries}46 -1 </channel>-1 46 </channel> 47 47 </rss>""" 48 48 49 49 LINK = '<atom:link href="{href}" rel="{rel}" type="application/rss+xml"/>' 50 5051 -1 ENTRY = """ <item>52 -1 <title>{title}</title>53 -1 <link>{url}</link>54 -1 <guid>{url}</guid>55 -1 <enclosure url="{downloadUrl}" type="audio/mpeg"/>56 -1 <pubDate>{updated}</pubDate>57 -1 <description>{summary}</description>58 -1 <itunes:duration>{duration}</itunes:duration>59 -1 </item>"""-1 51 ENTRY = """ <item> -1 52 <title>{title}</title> -1 53 <link>{url}</link> -1 54 <guid>{url}</guid> -1 55 <enclosure url="{downloadUrl}" type="audio/mpeg"/> -1 56 <pubDate>{updated}</pubDate> -1 57 <description>{summary}</description> -1 58 <itunes:duration>{duration}</itunes:duration> -1 59 </item>""" 60 60 61 61 62 62 def escape_data(data):63 -1 return {64 -1 key: escape(value) for key, value in data.items()65 -1 }-1 63 return { -1 64 key: escape(value) for key, value in data.items() -1 65 } 66 66 67 67 68 68 def render_feed(show, episodes, links):69 -1 entries = [ENTRY.format(**escape_data(ep)) for ep in reversed(episodes)]70 -1 entries += [LINK.format(**escape_data(link)) for link in links]71 -1 return FEED.format(entries='\n'.join(entries), **escape_data(show))-1 69 entries = [ENTRY.format(**escape_data(ep)) for ep in reversed(episodes)] -1 70 entries += [LINK.format(**escape_data(link)) for link in links] -1 71 return FEED.format(entries='\n'.join(entries), **escape_data(show)) 72 72 73 73 74 74 async def feed(request):75 -1 offset = int(request.query.get('offset', '0'), 10)76 -177 -1 url = 'https://api.ardaudiothek.de/graphql'78 -1 params = {79 -1 'query': QUERY,80 -1 'variables': json.dumps({81 -1 'id': request.match_info['id'],82 -1 'offset': offset,83 -1 'count': COUNT,84 -1 }),85 -1 }86 -187 -1 async with aiohttp.ClientSession() as session:88 -1 async with session.get(url, params=params) as response:89 -1 if response.status == 404:90 -1 raise web.HTTPNotFound91 -1 response.raise_for_status()92 -1 data = await response.json()93 -194 -1 show = data['data']['result']95 -196 -1 if show is None:97 -1 raise web.HTTPNotFound98 -199 -1 show_data = {100 -1 'title': show['title'],101 -1 'url': 'https://www.ardaudiothek.de' + show['path'],102 -1 'img_url': show['image']['url1X1'].replace('{width}', '64'),103 -1 'img_size': '64',104 -1 }105 -1106 -1 episode_data = [{107 -1 'title': node['title'],108 -1 'url': 'https://www.ardaudiothek.de' + node['path'],109 -1 'summary': node['summary'],110 -1 'updated': node['publishDate'],111 -1 'downloadUrl': node['audios'][0]['url'], # FIXME: more than one112 -1 'duration': str(node['duration']),113 -1 } for node in show['items']['nodes']]114 -1115 -1 links = []116 -1 if ORIGIN:117 -1 links.append({118 -1 'href': f'{ORIGIN}{request.url.path_qs}',119 -1 'rel': 'self',120 -1 })121 -1 if show['items']['pageInfo']['hasNextPage']:122 -1 links.append({123 -1 'href': f'{ORIGIN}{request.url.path}?offset={offset + COUNT}',124 -1 'rel': 'next',125 -1 })126 -1127 -1 body = render_feed(show_data, episode_data, links)128 -1129 -1 return web.Response(130 -1 body=body.encode('utf8'),131 -1 content_type='text/xml',132 -1 )-1 75 offset = int(request.query.get('offset', '0'), 10) -1 76 -1 77 url = 'https://api.ardaudiothek.de/graphql' -1 78 params = { -1 79 'query': QUERY, -1 80 'variables': json.dumps({ -1 81 'id': request.match_info['id'], -1 82 'offset': offset, -1 83 'count': COUNT, -1 84 }), -1 85 } -1 86 -1 87 async with aiohttp.ClientSession() as session: -1 88 async with session.get(url, params=params) as response: -1 89 if response.status == 404: -1 90 raise web.HTTPNotFound -1 91 response.raise_for_status() -1 92 data = await response.json() -1 93 -1 94 show = data['data']['result'] -1 95 -1 96 if show is None: -1 97 raise web.HTTPNotFound -1 98 -1 99 show_data = { -1 100 'title': show['title'], -1 101 'url': 'https://www.ardaudiothek.de' + show['path'], -1 102 'img_url': show['image']['url1X1'].replace('{width}', '64'), -1 103 'img_size': '64', -1 104 } -1 105 -1 106 episode_data = [{ -1 107 'title': node['title'], -1 108 'url': 'https://www.ardaudiothek.de' + node['path'], -1 109 'summary': node['summary'], -1 110 'updated': node['publishDate'], -1 111 'downloadUrl': node['audios'][0]['url'], # FIXME: more than one -1 112 'duration': str(node['duration']), -1 113 } for node in show['items']['nodes']] -1 114 -1 115 links = [] -1 116 if ORIGIN: -1 117 links.append({ -1 118 'href': f'{ORIGIN}{request.url.path_qs}', -1 119 'rel': 'self', -1 120 }) -1 121 if show['items']['pageInfo']['hasNextPage']: -1 122 links.append({ -1 123 'href': f'{ORIGIN}{request.url.path}?offset={offset + COUNT}', -1 124 'rel': 'next', -1 125 }) -1 126 -1 127 body = render_feed(show_data, episode_data, links) -1 128 -1 129 return web.Response( -1 130 body=body.encode('utf8'), -1 131 content_type='text/xml', -1 132 ) 133 133 134 134 135 135 if __name__ == '__main__':136 -1 parser = argparse.ArgumentParser()137 -1 parser.add_argument('--port', type=int)138 -1 parser.add_argument('--origin')139 -1 args = parser.parse_args()-1 136 parser = argparse.ArgumentParser() -1 137 parser.add_argument('--port', type=int) -1 138 parser.add_argument('--origin') -1 139 args = parser.parse_args() 140 140141 -1 global ORIGIN142 -1 ORIGIN = args.origin-1 141 global ORIGIN -1 142 ORIGIN = args.origin 143 143144 -1 app = web.Application()145 -1 app.router.add_get('/{id:[0-9]+}.rss', feed)146 -1 web.run_app(app, host='localhost', port=args.port)-1 144 app = web.Application() -1 145 app.router.add_get('/{id:[0-9]+}.rss', feed) -1 146 web.run_app(app, host='localhost', port=args.port)