aboutsummaryrefslogtreecommitdiffstats
path: root/tg_backup.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-07-31 08:52:55 +0200
committerDanilo M. <danix@danix.xyz>2026-07-31 08:52:55 +0200
commit0a5464c523618c66ef2736683db38731282d8d35 (patch)
tree90cb1439889dda74401d907ecad41792a51cbb38 /tg_backup.py
parent1b7325fec54a419b7773b31e1032717279713b29 (diff)
downloadtg_backup-0a5464c523618c66ef2736683db38731282d8d35.tar.gz
tg_backup-0a5464c523618c66ef2736683db38731282d8d35.zip
feat: remember target in state.json for bare-dir resume
An archive dir that has been backed up once now records its target in state.json, so later runs can be just --archive-dir. --target is still required the first time, and still wins when given. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'tg_backup.py')
-rw-r--r--tg_backup.py18
1 files changed, 15 insertions, 3 deletions
diff --git a/tg_backup.py b/tg_backup.py
index e038b92..6c77878 100644
--- a/tg_backup.py
+++ b/tg_backup.py
@@ -188,7 +188,10 @@ async def run_backup(target, archive_dir):
"chat is in the session's entity cache.")
state = load_state(archive_dir)
+ # Remember the target so later runs can resume with just --archive-dir.
+ state['target'] = target
last_id = state['last_id']
+ save_state(archive_dir, state)
print(f"Resuming from message ID: {last_id}")
# reverse=True ensures oldest-to-newest processing.
@@ -236,10 +239,14 @@ def main():
args = parser.parse_args()
if args.list_chats:
asyncio.run(list_chats(args.archive_dir))
- elif args.target:
- asyncio.run(run_backup(args.target, args.archive_dir))
+ return
+ # An archive dir already backed up once knows its own target.
+ target = args.target or load_state(args.archive_dir).get('target')
+ if target:
+ asyncio.run(run_backup(target, args.archive_dir))
else:
- parser.error("--target is required (or use --list-chats)")
+ parser.error(f"--target is required the first time ({args.archive_dir}/state.json "
+ "has no saved target), or use --list-chats")
def _self_check():
"""Run with --self-check. Guards the path-traversal and state-write logic."""
@@ -280,6 +287,11 @@ def _self_check():
assert not list(archive.glob('*.tmp')), "temp state file left behind"
assert load_state(Path(tempfile.mkdtemp())) == {'last_id': 0}
+ # A saved target survives, and a fresh dir has none to fall back on.
+ save_state(archive, {'last_id': 9, 'target': '-1001234567890'})
+ assert load_state(archive).get('target') == '-1001234567890'
+ assert load_state(Path(tempfile.mkdtemp())).get('target') is None
+
print("self-check OK")
if __name__ == "__main__":