db-pkpass

Convert Deutsche Bahn PDF tickets to PKPass
git clone https://git.ce9e.org/db-pkpass.git

commit
dbd1d7b3b2525fd28e171d4b2d744c77e069144e
parent
bb66b9015d5f46086151dc7a22d1eed5fb701b24
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2025-05-30 15:31
consider position in extract_legs()

Diffstat

M db_pkpass.py 102 ++++++++++++++++++++++++++++++-------------------------------

1 files changed, 50 insertions, 52 deletions


diff --git a/db_pkpass.py b/db_pkpass.py

@@ -60,12 +60,6 @@ def dump_pkpass(files: dict[str, bytes]) -> bytes:
   60    60     return buf.getvalue()
   61    61 
   62    62 
   63    -1 def pdf_iter_text_lines(pdf):
   64    -1     for page in pdf:
   65    -1         text = page.get_text()
   66    -1         yield from text.split('\n')
   67    -1 
   68    -1 
   69    63 def extract_barcodes(pdf):
   70    64     barcodes = []
   71    65     for page in pdf:
@@ -94,57 +88,63 @@ def parse_leg_dt(datestr, timestr, prefix):
   94    88 
   95    89 
   96    90 def extract_legs(pdf):
   97    -1     raw = []
   98    -1     started = False
   99    -1     lines = pdf_iter_text_lines(pdf)
  100    -1     for line in lines:
  101    -1         line = line.strip()
  102    -1         if line.startswith('Ihre Reiseverbindung und Reservierung'):
  103    -1             assert next(lines) == 'Halt'
  104    -1             assert next(lines) == 'Datum'
  105    -1             assert next(lines) == 'Zeit'
  106    -1             assert next(lines) == 'Gleis'
  107    -1             assert next(lines) == 'Produkte'
  108    -1             assert next(lines) == 'Reservierung / Hinweise'
  109    -1             started = True
  110    -1         elif started and not line:
  111    -1             break
  112    -1         elif started:
  113    -1             raw.append(line)
  114    -1 
  115    -1     i = 0
  116    91     legs = []
  117    -1     while True:
  118    -1         legs.append({
  119    -1             'train': raw[i + 8],
  120    -1             'start': {
  121    -1                 'station': raw[i],
  122    -1                 'datetime': parse_leg_dt(raw[i + 2], raw[i + 4], 'ab'),
  123    -1                 'platform': raw[i + 6],
  124    -1             },
  125    -1             'destination': {
  126    -1                 'station': raw[i + 1],
  127    -1                 'datetime': parse_leg_dt(raw[i + 3], raw[i + 5], 'an'),
  128    -1                 'platform': raw[i + 7],
  129    -1             },
  130    -1         })
  131    -1 
  132    -1         if i + 13 >= len(raw):
  133    -1             break
  134    -1         elif raw[i + 13].startswith('ab '):
  135    -1             i += 9
  136    -1         else:
  137    -1             legs[-1]['comment'] = raw[i + 9]
  138    -1             i += 10
   -1    92     state = 0
   -1    93     last_x = 0
   -1    94     for page in pdf:
   -1    95         for x, _, _, _, text, _, _ in page.get_text('blocks'):
   -1    96             if text.startswith('Halt\nDatum\nZeit\nGleis'):
   -1    97                 state = 1
   -1    98             elif text.startswith('Wichtige Nutzungshinweise'):
   -1    99                 break
   -1   100             elif state == 0:
   -1   101                 pass
   -1   102             elif state == 1 or (state > 0 and x < last_x):
   -1   103                 v1, v2 = text.rstrip('\n').split('\n')
   -1   104                 legs.append({
   -1   105                     'start': {
   -1   106                         'station': v1,
   -1   107                     },
   -1   108                     'destination': {
   -1   109                         'station': v2,
   -1   110                     },
   -1   111                 })
   -1   112                 state = 2
   -1   113             elif state == 2:
   -1   114                 v1, v2 = text.rstrip('\n').split('\n')
   -1   115                 legs[-1]['start']['date'] = v1
   -1   116                 legs[-1]['destination']['date'] = v2
   -1   117                 state = 3
   -1   118             elif state == 3:
   -1   119                 v1, v2 = text.rstrip('\n').split('\n')
   -1   120                 legs[-1]['start']['datetime'] = parse_leg_dt(legs[-1]['start'].pop('date'), v1, 'ab')
   -1   121                 legs[-1]['destination']['datetime'] = parse_leg_dt(legs[-1]['destination'].pop('date'), v2, 'an')
   -1   122                 state = 4
   -1   123             elif state == 4:
   -1   124                 v1, v2 = text.rstrip('\n').split('\n')
   -1   125                 legs[-1]['start']['platform'] = v1
   -1   126                 legs[-1]['destination']['platform'] = v2
   -1   127                 state = 5
   -1   128             elif state == 5:
   -1   129                 legs[-1]['train'] = text.strip()
   -1   130                 state = 6
   -1   131             elif state == 6:
   -1   132                 legs[-1]['comment'] = text.strip()
   -1   133                 state = 7
   -1   134             else:
   -1   135                 raise ValueError((text, state))
   -1   136 
   -1   137             last_x = x
  139   138 
  140   139     return legs
  141   140 
  142   141 
  143   142 def extract_order_id(pdf):
  144   143     key = 'Auftragsnummer: '
  145    -1     for line in pdf_iter_text_lines(pdf):
  146    -1         if line.startswith(key):
  147    -1             return line[len(key):]
   -1   144     for page in pdf:
   -1   145         for text in page.get_text().split('\n'):
   -1   146             if text.startswith(key):
   -1   147                 return text[len(key):]
  148   148 
  149   149 
  150   150 def format_stop(stop, train=None):
@@ -164,8 +164,6 @@ def format_legs(legs):
  164   164 
  165   165 
  166   166 def extract_content(pdf):
  167    -1     # https://developer.apple.com/documentation/walletpasses/pass
  168    -1 
  169   167     order_id = extract_order_id(pdf)
  170   168 
  171   169     legs = extract_legs(pdf)