Thaimozhi commited on
Commit
4aa5df4
·
1 Parent(s): 3526668

Improve leech progress stats and rename templates

Browse files
Files changed (2) hide show
  1. plugins/file_rename.py +32 -7
  2. tests/test_file_rename.py +17 -0
plugins/file_rename.py CHANGED
@@ -287,6 +287,22 @@ async def resolve_remote_filename(url: str, fallback: str = "downloaded_file") -
287
  return guess_filename_from_url(url, fallback=fallback)
288
 
289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  async def _update_leech_status(task: dict, status: str, current: int = 0, total: int = 0, speed: float = 0.0, elapsed: float = 0.0):
291
  if not task.get("status_message"):
292
  return
@@ -317,9 +333,14 @@ async def _update_leech_status(task: dict, status: str, current: int = 0, total:
317
  else:
318
  size_text = humanbytes(current) if current else "0 B"
319
 
 
 
 
 
 
320
  text = (
321
  f"🧲 Task {task['task_id']}\n"
322
- f"Name: {task.get('display_name', 'Unknown')}\n"
323
  f"Status: {status}\n"
324
  f"Progress: {bar} {percent:.0f}%\n"
325
  f"Speed: {humanbytes(speed) if speed else '—'}/s\n"
@@ -354,6 +375,7 @@ async def _download_url_with_progress(url: str, output_path: str, task: dict):
354
  raise RuntimeError(f"Download failed with status {resp.status}")
355
  total = int(resp.headers.get("Content-Length", 0) or 0)
356
  downloaded = 0
 
357
  with open(output_path, "wb") as handle:
358
  async for chunk in resp.content.iter_chunked(1024 * 64):
359
  if task.get("cancelled"):
@@ -365,8 +387,9 @@ async def _download_url_with_progress(url: str, output_path: str, task: dict):
365
  now = time.time()
366
  elapsed = max(1, int(now - task.get("started_at", now)))
367
  speed = downloaded / elapsed if elapsed else 0
368
- if (now - task.get("last_status_update", 0)) >= 2 or downloaded >= total:
369
  await _update_leech_status(task, "Downloading", current=downloaded, total=total, speed=speed, elapsed=elapsed)
 
370
  return output_path
371
 
372
 
@@ -447,7 +470,9 @@ async def _process_leech_file(client, user_id, input_path, display_name, origina
447
 
448
  season, episode = extract_season_episode(file_name)
449
  quality = extract_quality(file_name)
450
- format_template = await codeflixbots.get_format_template(user_id) or os.path.splitext(file_name)[0]
 
 
451
 
452
  replacements = {
453
  '{season}': season or 'XX',
@@ -462,10 +487,9 @@ async def _process_leech_file(client, user_id, input_path, display_name, origina
462
  stem = format_template
463
  if task.get('custom_name'):
464
  stem = task['custom_name']
465
- new_filename = _apply_prefix_suffix_to_name(stem, ext_original, prefix, suffix)
466
-
467
- if not os.path.splitext(new_filename)[1]:
468
- new_filename = f"{new_filename}{ext_original}"
469
 
470
  metadata_path = f"metadata/{new_filename}"
471
  thumb_path = None
@@ -594,6 +618,7 @@ async def _run_leech_task(client, task: dict):
594
 
595
  display_name = await resolve_remote_filename(url, fallback=task.get("requested_name", "downloaded_file"))
596
  task["display_name"] = display_name
 
597
  await _update_leech_status(task, "Preparing")
598
 
599
  ext = os.path.splitext(display_name)[1].lower()
 
287
  return guess_filename_from_url(url, fallback=fallback)
288
 
289
 
290
+ def build_leech_output_name(stem: str, ext_original: str, prefix: str = None, suffix: str = None) -> str:
291
+ if not stem:
292
+ stem = 'downloaded_file'
293
+ if not os.path.splitext(stem)[1]:
294
+ stem = f"{stem}{ext_original or '.bin'}"
295
+ return _apply_prefix_suffix_to_name(stem, '', prefix, suffix).rstrip('.')
296
+
297
+
298
+ def resolve_leech_format_template(rename_formats, original_name: str, default_template: str):
299
+ for fmt in rename_formats:
300
+ hint = fmt.get("hint", "")
301
+ if hint and hint.lower() in (original_name or "").lower():
302
+ return fmt.get("template", default_template), hint
303
+ return default_template, None
304
+
305
+
306
  async def _update_leech_status(task: dict, status: str, current: int = 0, total: int = 0, speed: float = 0.0, elapsed: float = 0.0):
307
  if not task.get("status_message"):
308
  return
 
333
  else:
334
  size_text = humanbytes(current) if current else "0 B"
335
 
336
+ if task.get("display_name"):
337
+ display_name = task["display_name"]
338
+ else:
339
+ display_name = "Unknown"
340
+
341
  text = (
342
  f"🧲 Task {task['task_id']}\n"
343
+ f"Name: {display_name}\n"
344
  f"Status: {status}\n"
345
  f"Progress: {bar} {percent:.0f}%\n"
346
  f"Speed: {humanbytes(speed) if speed else '—'}/s\n"
 
375
  raise RuntimeError(f"Download failed with status {resp.status}")
376
  total = int(resp.headers.get("Content-Length", 0) or 0)
377
  downloaded = 0
378
+ await _update_leech_status(task, "Downloading", current=downloaded, total=total, speed=0, elapsed=0)
379
  with open(output_path, "wb") as handle:
380
  async for chunk in resp.content.iter_chunked(1024 * 64):
381
  if task.get("cancelled"):
 
387
  now = time.time()
388
  elapsed = max(1, int(now - task.get("started_at", now)))
389
  speed = downloaded / elapsed if elapsed else 0
390
+ if (now - task.get("last_status_update", 0)) >= 1 or downloaded >= total:
391
  await _update_leech_status(task, "Downloading", current=downloaded, total=total, speed=speed, elapsed=elapsed)
392
+ await _update_leech_status(task, "Downloading", current=downloaded, total=total, speed=0, elapsed=max(1, int(time.time() - task.get("started_at", time.time()))))
393
  return output_path
394
 
395
 
 
470
 
471
  season, episode = extract_season_episode(file_name)
472
  quality = extract_quality(file_name)
473
+ default_template = await codeflixbots.get_format_template(user_id) or os.path.splitext(file_name)[0]
474
+ rename_formats = await codeflixbots.get_rename_formats(user_id)
475
+ format_template, selected_hint = resolve_leech_format_template(rename_formats, original_file_name, default_template)
476
 
477
  replacements = {
478
  '{season}': season or 'XX',
 
487
  stem = format_template
488
  if task.get('custom_name'):
489
  stem = task['custom_name']
490
+ new_filename = build_leech_output_name(stem, ext_original, prefix, suffix)
491
+ if selected_hint:
492
+ task['last_selected_hint'] = selected_hint
 
493
 
494
  metadata_path = f"metadata/{new_filename}"
495
  thumb_path = None
 
618
 
619
  display_name = await resolve_remote_filename(url, fallback=task.get("requested_name", "downloaded_file"))
620
  task["display_name"] = display_name
621
+ task["requested_name"] = task.get("custom_name") or display_name
622
  await _update_leech_status(task, "Preparing")
623
 
624
  ext = os.path.splitext(display_name)[1].lower()
tests/test_file_rename.py CHANGED
@@ -89,6 +89,8 @@ from plugins.file_rename import (
89
  guess_filename_from_url,
90
  prepare_leech_workspace,
91
  infer_media_type_hint,
 
 
92
  )
93
 
94
 
@@ -130,3 +132,18 @@ def test_infer_media_type_hint_prefers_video_extension():
130
 
131
  def test_infer_media_type_hint_falls_back_to_hint_when_no_extension():
132
  assert infer_media_type_hint('random-token', fallback_hint='video') == 'video'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  guess_filename_from_url,
90
  prepare_leech_workspace,
91
  infer_media_type_hint,
92
+ build_leech_output_name,
93
+ resolve_leech_format_template,
94
  )
95
 
96
 
 
132
 
133
  def test_infer_media_type_hint_falls_back_to_hint_when_no_extension():
134
  assert infer_media_type_hint('random-token', fallback_hint='video') == 'video'
135
+
136
+
137
+ def test_build_leech_output_name_uses_custom_name_with_extension():
138
+ assert build_leech_output_name('aaa.mkv', '.mkv', None, None) == 'aaa.mkv'
139
+
140
+
141
+ def test_build_leech_output_name_uses_template_when_custom_name_has_no_extension():
142
+ assert build_leech_output_name('aaa', '.mkv', None, None) == 'aaa.mkv'
143
+
144
+
145
+ def test_resolve_leech_format_template_uses_matching_hint():
146
+ templates = [
147
+ {'hint': 'Agents', 'template': 'Agents of the Four Seasons Dance of Spring S{season}E{episode} {quality} WEB-DL Multi Audio ESub'},
148
+ ]
149
+ assert resolve_leech_format_template(templates, 'Agents of the Four Seasons Dance of Spring S01E12 720p.mkv', 'default') == ('Agents of the Four Seasons Dance of Spring S{season}E{episode} {quality} WEB-DL Multi Audio ESub', 'Agents')