#!/usr/bin/env python3 from datetime import datetime from sys import argv from urllib.parse import urljoin from lxml.builder import E from lxml.etree import CDATA, indent, tostring from helpers import ( DATE_FORMATTERS, guess_language, read_concerts, tmplocale, touchup_plaintext, ) TIMEZONE = datetime.now().astimezone().tzinfo NOW = datetime.now(tz=TIMEZONE) DATE_FORMAT = '%-d %b %Y %H:%M %z' # TODO: add item pubDate LOCALIZED_TEXT = { 'en': { 'title': 'Bellefeuille Quartet', 'indexpath': 'en/', 'description': 'News from the Bellefeuille quartet', }, 'fr': { 'title': 'Quatuor Bellefeuille', 'indexpath': '/', 'description': 'Des nouvelles du quatuor Bellefeuille', }, } LOCALIZED_FORMATS = { 'en': { 'title': lambda c: f'{c.time.strftime("%B %-d %Y")} in {c.place}', }, 'fr': { 'title': lambda c: f'{c.time.strftime("%-d %B %Y")} à {c.place}', }, } def join(sequence, joiner_factory): # There's got to be a standard itertools/functools thingy to do that… result = [] for i, item in enumerate(sequence, start=1): result.append(item) if i == len(sequence): return result result.append(joiner_factory()) def cdata_concert(concert, lang): formatters = DATE_FORMATTERS[lang] blocks = [] if concert.warning is not None: blocks.append(E.p(concert.warning)) blocks.extend(( E.p(formatters['date'](concert.time)), E.p(formatters['time'](concert.time)), E.p(*join(concert.address.splitlines(), E.br)), E.ol( *(E.li(touchup_plaintext(p)) for p in concert.pieces.splitlines()) ), *(E.p(line) for line in concert.instructions.splitlines()), )) return CDATA('\n'.join( tostring(b, encoding='utf-8').decode() for b in blocks )) def generate_concert(concert, concerts_url, lang): formatters = LOCALIZED_FORMATS[lang] with tmplocale(lang): title = formatters['title'](concert) anchor = f'concert-{concert.time.strftime("%F")}' return E.item( E.title(title), E.link(f'{concerts_url}#{anchor}'), E.description(cdata_concert(concert, lang)), ) def generate_concerts(concerts_src, concerts_url, lang): return tuple( generate_concert(c, concerts_url, lang) for c in read_concerts(concerts_src) ) def main(concerts_src, feed_dst, domain): lang = guess_language(concerts_src) text = LOCALIZED_TEXT[lang] url = f'https://{domain}' index_url = urljoin(url, text['indexpath']) concerts_url = urljoin(index_url, 'concerts.html') now_formatted = NOW.strftime(DATE_FORMAT) rss = E.rss( E.channel( E.title(text['title']), E.link(index_url), E.description(text['description']), E.image( E.url(urljoin(url, 'images/logo.svg')), E.link(concerts_url), ), E.lastBuildDate(now_formatted), E.pubDate(now_formatted), E.language(lang), *generate_concerts(concerts_src, concerts_url, lang), ), version='2.0', ) indent(rss) with open(feed_dst, 'wb') as feed: feed.write(tostring(rss, encoding='utf-8', xml_declaration=True)) if __name__ == '__main__': main(argv[1], argv[2], argv[3])