@@ -79,7 +79,7 @@ def preview(response, num_lines=5):
79
79
def check_version (installed_version ):
80
80
log = get_logger (__name__ )
81
81
try :
82
- r = requests .get ('https://api.github.com/repos/marzzzello /pytr/tags' , timeout = 1 )
82
+ r = requests .get ('https://api.github.com/repos/pytr-org /pytr/tags' , timeout = 1 )
83
83
except Exception as e :
84
84
log .error ('Could not check for a newer version' )
85
85
log .debug (str (e ))
@@ -290,7 +290,7 @@ def export_transactions(input_path, output_path, lang='auto'):
290
290
291
291
292
292
class Timeline :
293
- def __init__ (self , tr ):
293
+ def __init__ (self , tr , max_age_timestamp ):
294
294
self .tr = tr
295
295
self .log = get_logger (__name__ )
296
296
self .received_detail = 0
@@ -301,21 +301,20 @@ def __init__(self, tr):
301
301
self .num_timelines = 0
302
302
self .timeline_events = {}
303
303
self .timeline_events_iter = None
304
+ self .max_age_timestamp = max_age_timestamp
304
305
305
- async def get_next_timeline_transactions (self , response = None , max_age_timestamp = 0 ):
306
+ async def get_next_timeline_transactions (self , response = None ):
306
307
'''
307
308
Get timelines transactions and save time in list timelines.
308
309
Extract timeline transactions events and save them in list timeline_events
309
310
310
311
'''
311
-
312
312
if response is None :
313
313
# empty response / first timeline
314
- self .log .info ('Awaiting #1 timeline transactions' )
314
+ self .log .info ('Subscribing to #1 timeline transactions' )
315
315
self .num_timelines = 0
316
316
await self .tr .timeline_transactions ()
317
317
else :
318
- timestamp = response ['items' ][- 1 ]['timestamp' ]
319
318
self .num_timelines += 1
320
319
# print(json.dumps(response))
321
320
self .num_timeline_details += len (response ['items' ])
@@ -324,30 +323,37 @@ async def get_next_timeline_transactions(self, response=None, max_age_timestamp=
324
323
self .timeline_events [event ['id' ]] = event
325
324
326
325
after = response ['cursors' ].get ('after' )
327
- if after is None :
328
- # last timeline is reached
329
- await self .get_next_timeline_activity_log ()
330
- else :
326
+
327
+ last_transaction_time = response ['items' ][- 1 ]['timestamp' ][:19 ]
328
+ timestamp = datetime .fromisoformat (last_transaction_time ).timestamp ()
329
+ self .log .info (
330
+ f'Received #{ self .num_timelines :<2} timeline transactions until { last_transaction_time } '
331
+ )
332
+ if (after is not None ) and ((self .max_age_timestamp == 0 ) or (timestamp >= self .max_age_timestamp )):
331
333
self .log .info (
332
- f'Received # { self . num_timelines :<2 } timeline transactions, awaiting #{ self .num_timelines + 1 :<2} timeline transactions'
334
+ f'Subscribing #{ self .num_timelines + 1 :<2} timeline transactions'
333
335
)
334
- await self .tr .timeline_transactions (after )
336
+ await self .tr .timeline_transactions (after )
337
+ else :
338
+ # last timeline is reached
339
+ self .log .info ('Received last relevant timeline transaction' )
340
+ await self .get_next_timeline_activity_log ()
335
341
336
342
337
- async def get_next_timeline_activity_log (self , response = None , max_age_timestamp = 0 ):
343
+ async def get_next_timeline_activity_log (self , response = None ):
338
344
'''
339
345
Get timelines acvtivity log and save time in list timelines.
340
346
Extract timeline acvtivity log events and save them in list timeline_events
341
347
342
348
'''
343
-
344
349
if response is None :
345
350
# empty response / first timeline
346
351
self .log .info ('Awaiting #1 timeline activity log' )
347
352
self .num_timelines = 0
348
353
await self .tr .timeline_activity_log ()
349
354
else :
350
- timestamp = datetime .fromisoformat (response ['items' ][- 1 ]['timestamp' ][:19 ]).timestamp ()
355
+ last_transaction_time = response ['items' ][- 1 ]['timestamp' ][:19 ]
356
+ timestamp = datetime .fromisoformat (last_transaction_time ).timestamp ()
351
357
self .num_timelines += 1
352
358
# print(json.dumps(response))
353
359
self .num_timeline_details += len (response ['items' ])
@@ -357,49 +363,26 @@ async def get_next_timeline_activity_log(self, response=None, max_age_timestamp=
357
363
self .timeline_events [event ['id' ]] = event
358
364
359
365
after = response ['cursors' ].get ('after' )
360
- if after is None :
361
- # last timeline is reached
362
- self .log .info (f'Received #{ self .num_timelines :<2} (last) timeline activity log' )
363
- self .timeline_events_iter = iter (self .timeline_events .values ())
364
- await self ._get_timeline_details (5 )
365
- elif max_age_timestamp != 0 and timestamp < max_age_timestamp :
366
- self .log .info (f'Received #{ self .num_timelines + 1 :<2} timeline activity log' )
367
- self .log .info ('Reached last relevant timeline activity log' )
368
- self .timeline_events_iter = iter (self .timeline_events .values ())
369
- await self ._get_timeline_details (5 , max_age_timestamp = max_age_timestamp )
370
- else :
366
+ self .log .info (f'Received #{ self .num_timelines :<2} timeline activity log unitl { last_transaction_time } ' )
367
+ if (after is not None ) and ((self .max_age_timestamp == 0 ) or (timestamp >= self .max_age_timestamp )):
371
368
self .log .info (
372
- f'Received # { self . num_timelines :<2 } timeline activity log, awaiting #{ self .num_timelines + 1 :<2} timeline activity log'
369
+ f'Subscribing #{ self .num_timelines + 1 :<2} timeline activity log'
373
370
)
374
371
await self .tr .timeline_activity_log (after )
372
+ else :
373
+ self .log .info ('Received last relevant timeline activity log' )
374
+ await self ._get_timeline_details ()
375
375
376
- async def _get_timeline_details (self , num_torequest , max_age_timestamp = 0 ):
376
+ async def _get_timeline_details (self ):
377
377
'''
378
378
request timeline details
379
379
'''
380
- while num_torequest > 0 :
381
-
382
- try :
383
- event = next (self .timeline_events_iter )
384
- except StopIteration :
385
- self .log .info ('All timeline details requested' )
386
- return False
387
-
380
+ for event in self .timeline_events .values ():
388
381
action = event .get ('action' )
389
- # icon = event.get('icon')
390
382
msg = ''
391
383
timestamp_field = datetime .fromisoformat (event ['timestamp' ][:19 ]).timestamp ()
392
- if max_age_timestamp != 0 and timestamp_field > max_age_timestamp :
384
+ if self . max_age_timestamp != 0 and ( timestamp_field < self . max_age_timestamp ) :
393
385
msg += 'Skip: too old'
394
- # elif icon is None:
395
- # pass
396
- # elif icon.endswith('/human.png'):
397
- # msg += 'Skip: human'
398
- # elif icon.endswith('/CashIn.png'):
399
- # msg += 'Skip: CashIn'
400
- # elif icon.endswith('/ExemptionOrderChanged.png'):
401
- # msg += 'Skip: ExemptionOrderChanged'
402
-
403
386
elif action is None :
404
387
if event .get ('actionLabel' ) is None :
405
388
msg += 'Skip: no action'
@@ -416,11 +399,12 @@ async def _get_timeline_details(self, num_torequest, max_age_timestamp=0):
416
399
self .num_timeline_details -= 1
417
400
continue
418
401
419
- num_torequest -= 1
420
402
self .requested_detail += 1
421
403
await self .tr .timeline_detail_v2 (event ['id' ])
404
+ self .log .info ('All timeline details requested' )
405
+ return False
422
406
423
- async def timelineDetail (self , response , dl , max_age_timestamp = 0 ):
407
+ async def timelineDetail (self , response , dl ):
424
408
'''
425
409
process timeline response and request timelines
426
410
'''
@@ -429,26 +413,15 @@ async def timelineDetail(self, response, dl, max_age_timestamp=0):
429
413
event = self .timeline_events [response ['id' ]]
430
414
event ['details' ] = response
431
415
432
- # when all requested timeline events are received request 5 new
433
- if self .received_detail == self .requested_detail :
434
- remaining = len (self .timeline_events )
435
- if remaining < 5 :
436
- await self ._get_timeline_details (remaining )
437
- else :
438
- await self ._get_timeline_details (5 )
439
-
440
- isSavingsPlan = (event ["eventType" ] == "SAVINGS_PLAN_EXECUTED" )
441
-
442
- if not isSavingsPlan and event ['subtitle' ] is not None :
443
- isSavingsPlan = 'Sparplan' in event ['subtitle' ]
444
-
416
+ is_savings_plan = (event ["eventType" ] == "SAVINGS_PLAN_EXECUTED" )
417
+
445
418
max_details_digits = len (str (self .num_timeline_details ))
446
419
self .log .info (
447
420
f"{ self .received_detail :>{max_details_digits }} /{ self .num_timeline_details } : "
448
- + f"{ event ['title' ]} -- { event ['subtitle' ]} [ { event [ 'eventType' ] } ] "
421
+ + f"{ event ['title' ]} -- { event ['subtitle' ]} "
449
422
)
450
423
451
- if isSavingsPlan :
424
+ if is_savings_plan :
452
425
subfolder = 'Sparplan'
453
426
else :
454
427
subfolder = {
@@ -462,14 +435,12 @@ async def timelineDetail(self, response, dl, max_age_timestamp=0):
462
435
for section in response ['sections' ]:
463
436
if section ['type' ] != 'documents' :
464
437
continue
465
-
466
438
for doc in section ['data' ]:
467
439
try :
468
- timestamp = datetime .strptime (doc ['detail' ], '%d.%m.%Y' ).timestamp () * 1000
440
+ timestamp = datetime .strptime (doc ['detail' ], '%d.%m.%Y' ).timestamp ()
469
441
except (ValueError , KeyError ):
470
- timestamp = datetime .now ().timestamp () * 1000
471
- if max_age_timestamp == 0 or max_age_timestamp < timestamp :
472
- # save all savingsplan documents in a subdirectory
442
+ timestamp = datetime .now ().timestamp ()
443
+ if self .max_age_timestamp == 0 or self .max_age_timestamp < timestamp :
473
444
title = f"{ doc ['title' ]} - { event ['title' ]} "
474
445
if event ['eventType' ] in ["ACCOUNT_TRANSFER_INCOMING" , "ACCOUNT_TRANSFER_OUTGOING" , "CREDIT" ]:
475
446
title += f" - { event ['subtitle' ]} "
0 commit comments