...
 
Commits (5)
......@@ -19,7 +19,9 @@ To use this module, you need at least:
## CLI
For convenience and testing purposes, a simple CLI is included:
```
usage: jht_flyergen [-h] [-p PRINT] (-u [URL] | -f PATH) [output]
usage: jht_flyergen [-h] [-d [DAY]] [-l] [-m HOMEPAGE] [-p PRINT] [-t]
(-U | -u [URL] | -f PATH)
[output]
positional arguments:
output path to output file; if omitted raw PDF data is
......@@ -27,17 +29,45 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
-d [DAY], --day [DAY]
day of month (default: 28)
-l, --links generate QR codes with links to sessions' wiki pages
-m HOMEPAGE, --homepage HOMEPAGE
JHT homepage URL
-p PRINT, --print PRINT
print filtered data of session with index PRINT,
starting at 1; 0 prints all sessions
-t, --tex print tex document to stdout
data sources:
-U, --print-default-url
print default URL and exit
-u [URL], --url [URL]
URL to fetch JSON data from; if URL is omitted, a
hard-coded URL returning test data is used
hard-coded default URL is used
-f PATH, --file PATH path to file containing JSON data
```
## Data source
Default URL was generated with Semantic Wiki's [Special:Ask](https://events.ccc.de/congress/2019/wiki/index.php?title=Special:Ask) page using the following settings:
* Condition:
```
[[Category:Session]] [[Is for kids::yes]]
```
* Printout selection:
```
?Has description=description
?Has subobject.Has session location=location
?Has subobject.Has start time=starts
?Has subobject.Has end time=ends
```
* limit: 128
* offset: 0
* link: all
Sorting is done by the script, so we don't care about it here.
## Templates
At the moment the module uses a bundled, "hard-coded" [LaTeX template](jht_flyergen/template.tex).
Maybe support for custom templates will be added once the thing works as expected and was tested
......
......@@ -20,11 +20,12 @@
from argparse import ArgumentParser
from json import dumps
from sys import argv
from sys import exit as sysexit
from sys import stdout
from jht_flyergen.engine import fetch_data, render, generate_tex, process_sessions, read_data
DEFAULT_URL = 'https://events.ccc.de/congress/2019/wiki/index.php/Special:Ask/cl:YzpVT9tKxFAM_KKaouzLQl5ERH1QYb8gp03t2Z5LSVJK_XrTdRcUcplhhjAZqmQyPGstkGKOhofWQZmQUoKRqWdR1LGuoEzSjYkCJ3w7fbxDl0hdq2IUEjf37RqneMOa1wuEXUeo4oeQtIM6DMqGLTSHR69XdfNQxecUez0eTRZuDk9e0Dw87_1Cu6dn7STOFmvBP_hm-pTasSr3bg2bD8_GOaQNq3xRid9X5f9RXUINZ-7s7sqNxHxbzIynnUCmWH6fhlnYbJslFsM9JizFg9DMF_YD' # pylint: disable=line-too-long
DEFAULT_URL = 'https://events.ccc.de/congress/2019/wiki/index.php/Special:Ask/format%3Djson/limit%3D128/link%3Dall/headers%3Dshow/searchlabel%3DJSON/class%3Dsortable-20wikitable-20smwtable/sort%3D/order%3Dasc/offset%3D0/-5B-5BCategory:Session-5D-5D-20-5B-5BIs-20for-20kids::true-5D-5D/-3FHas-20description%3Ddescription/-3FHas-20subobject.Has-20session-20location%3Dlocation/-3FHas-20subobject.Has-20start-20time%3Dstarts/-3FHas-20subobject.Has-20end-20time%3Dends/mainlabel%3D/prettyprint%3Dtrue/unescape%3Dtrue' # pylint: disable=line-too-long
def parse_arguments(args):
"""Parses command-line arguments.
......@@ -45,6 +46,8 @@ def parse_arguments(args):
help='path to output file; if omitted raw PDF data is written to stdout')
sources = parser.add_argument_group('data sources').add_mutually_exclusive_group(required=True)
sources.add_argument('-U', '--print-default-url', action='store_true',
help='print default URL and exit')
sources.add_argument('-u', '--url', nargs='?', const=DEFAULT_URL,
help='URL to fetch JSON data from; '
'if URL is omitted, a hard-coded default URL is used')
......@@ -62,6 +65,10 @@ def main():
"""
args = parse_arguments(argv[1:])
if args.print_default_url:
print(DEFAULT_URL)
sysexit()
sessions = None
if args.url:
sessions = fetch_data(args.url)
......@@ -71,7 +78,7 @@ def main():
if args.print:
end = int(args.print)
pretty_print(sessions[0 : end if end else -1])
pretty_print(sessions[0 : end if end else None])
tex = generate_tex(sessions, args.homepage, args.links)
if args.tex:
......
......@@ -68,9 +68,9 @@ def process_sessions(sessions: List[Dict], day: int) -> List[Dict]:
a list of filtered, re-organized session data
"""
def is_correct_date(start: Dict) -> bool:
return datetime.fromtimestamp(int(start['timestamp'])).day == day
return datetime.utcfromtimestamp(int(start['timestamp'])).day == day
def relevant(session: Dict) -> bool:
return bool(list(filter(is_correct_date, session['printouts']['Start'])))
return bool(list(filter(is_correct_date, session['printouts']['starts'])))
sessionss = [transform_session(s, day) for s in sessions if relevant(s)]
sessions = [s for ss in sessionss for s in ss]
sessions.sort(key=lambda a: a['start'])
......@@ -110,20 +110,24 @@ def transform_session(session: Dict, day: int) -> List[Dict]:
Returns:
an uncluttered, organized version of the input dict containing only relevant data
"""
def build_session(title, url, providers, start):
def build_session(title, url, location, start, end):
result = {}
result['title'] = title
result['url'] = url
result['providers'] = providers
result['location'] = location
result['start'] = start
result['end'] = end
return result
def parse_date(start: Dict) -> datetime:
return datetime.fromtimestamp(int(start['timestamp']))
return datetime.utcfromtimestamp(int(start['timestamp']))
def process_provider(provider: Dict) -> str:
return sub('Assembly:', '', sub('Static:', '', provider['fulltext']))
return sub('Assembly:', '', sub('Room:', '', provider['fulltext']))
title = sub('Session:', '', session['fulltext'])
url = session['fullurl']
providers = ', '.join(map(process_provider, session['printouts']['organized by']))
start_dates = list(map(parse_date, session['printouts']['Start']))
location = session['printouts']['location']
location = process_provider(location[0]) if location else ''
start_dates = list(map(parse_date, session['printouts']['starts']))
starts = [s.strftime('%H:%M') for s in filter(lambda d: d.day == day, start_dates)]
return [build_session(title, url, providers, s) for s in starts]
end_dates = list(map(parse_date, session['printouts']['ends']))
ends = [s.strftime('%H:%M') for s in filter(lambda d: d.day == day, end_dates)]
return [build_session(title, url, location, s, e) for s, e in zip(starts, ends)]
......@@ -35,19 +35,19 @@
\textbf{Wann?} & \textbf{Was?} & \textbf{Wo?} & \textbf{URL}
\\ \hline \hline
%- for session in sessions
\VAR{session.start | e} & \VAR{session.title | e} & \VAR{session.providers | e}
\VAR{session.start | e} & \VAR{session.title | e} & \VAR{session.location | e}
& \qrcode{\VAR{session.url | e}}
\\ \hline
%- endfor
\end{longtable}
%- else
\begin{longtable}{|l|p{0.55\linewidth}|p{0.3\linewidth}|}
\begin{longtable}{|l|l|p{0.45\linewidth}|p{0.3\linewidth}|}
\hline
\textbf{Wann?} & \textbf{Was?} & \textbf{Wo?}
\textbf{Von} & \textbf{Bis} & \textbf{Was} & \textbf{Wo}
\\ \hline \hline
%- for session in sessions
\VAR{session.start | e} & \VAR{session.title | e} & \VAR{session.providers | e}
\VAR{session.start | e} & \VAR{session.end | e} & \VAR{session.title | e} & \VAR{session.location | e}
\\ \hline
%- endfor
\end{longtable}
......