audiothek

alternative frontend for ardaudiothek.de  https://audiothek.ce9e.org/
git clone https://git.ce9e.org/audiothek.git

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 		id
   14    -1 		title
   15    -1 		path
   16    -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 				id
   22    -1 				title
   23    -1 				publishDate
   24    -1 				summary
   25    -1 				duration
   26    -1 				path
   27    -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    50 
   51    -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    -1 
   77    -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    -1 
   87    -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.HTTPNotFound
   91    -1 			response.raise_for_status()
   92    -1 			data = await response.json()
   93    -1 
   94    -1 	show = data['data']['result']
   95    -1 
   96    -1 	if show is None:
   97    -1 		raise web.HTTPNotFound
   98    -1 
   99    -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    -1 
  106    -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 one
  112    -1 		'duration': str(node['duration']),
  113    -1 	} for node in show['items']['nodes']]
  114    -1 
  115    -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    -1 
  127    -1 	body = render_feed(show_data, episode_data, links)
  128    -1 
  129    -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   140 
  141    -1 	global ORIGIN
  142    -1 	ORIGIN = args.origin
   -1   141     global ORIGIN
   -1   142     ORIGIN = args.origin
  143   143 
  144    -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)