feat: live progress bar every 5s, extended to 2h polling

#2
Files changed (1) hide show
  1. main.py +62 -110
main.py CHANGED
@@ -728,15 +728,18 @@ async def _process_archive(client: Client, message: Message, state: dict, reply_
728
  f"๐Ÿ†” `{archive_id}`\n"
729
  f"๐Ÿ“‚ **ุงู„ุญุณุงุจ:** {acc_info['label']}\n"
730
  f"๐ŸŒ **ุงู„ู…ุณุงุญุฉ:** `{user_space_name[:25]}-archiver`\n"
731
- f"๐Ÿ“ฆ **ุงู„ุฏุงุชุงุณูŠุช:** `{user_space_name[:20]}/archive`\n"
732
  f"๐Ÿ“ฅ **ุงู„ู…ุตุฏุฑ:** ุงู„ู‚ู†ุงุฉ (ุชู„ูŠุบุฑุงู…)\n"
733
- "โณ ุฌุงุฑู ู…ุชุงุจุนุฉ ุงู„ุชู‚ุฏู…..."
734
  )
735
 
736
  start_time = time.time()
737
  last_pct = -1
738
- for poll_i in range(60):
739
- await asyncio.sleep(3)
 
 
 
740
  progress = api_call("GET", f"archive/progress", params={"archive_id": archive_id})
741
  p = progress.get("progress", {})
742
  status = p.get("status", "")
@@ -750,20 +753,42 @@ async def _process_archive(client: Client, message: Message, state: dict, reply_
750
  downloaded_bytes = p.get("downloaded_bytes", 0)
751
  total_bytes = p.get("total_bytes", 0)
752
  eta_seconds = p.get("eta_seconds", 0)
753
- dataset_size_gb = p.get("dataset_size_gb", 0)
754
 
755
  elapsed = time.time() - start_time
756
 
757
  if status in ("completed", "failed"):
758
- break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
759
 
760
- if pct > last_pct or (poll_i % 3 == 0):
761
  bar_len = 14
762
  filled = int(bar_len * pct / 100)
763
  bar = "โ–ˆ" * filled + "โ–‘" * (bar_len - filled)
764
 
765
- phase_icon = "๐Ÿ“ฅ" if "ุชุญู…ูŠู„" in msg_text else "๐Ÿ“‹" if "ู†ุณุฎ" in msg_text else "๐Ÿ“ค" if "ุฑูุน" in msg_text else "๐Ÿ“ฆ" if "ุฏุงุชุงุณูŠุช" in msg_text else "โณ"
766
- phase_name = "ุชุญู…ูŠู„ ู…ู† ุงู„ู‚ู†ุงุฉ" if "ุชุญู…ูŠู„" in msg_text else "ู†ุณุฎ ุฅู„ู‰ ุงู„ุฏุงุชุงุณูŠุช" if "ู†ุณุฎ" in msg_text else "ุฑูุน ุฅู„ู‰ HuggingFace" if "ุฑูุน" in msg_text else "ู‚ูŠุฏ ุงู„ุชุฌู‡ูŠุฒ"
 
 
 
 
 
 
 
 
 
767
 
768
  progress_text = (
769
  f"โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n"
@@ -773,21 +798,23 @@ async def _process_archive(client: Client, message: Message, state: dict, reply_
773
  f"๐Ÿ“ `{state['file_name'][:35]}`\n"
774
  f"๐Ÿ“‚ **{acc_info['label']}**\n"
775
  f"๐ŸŒ `{user_space_name[:25]}-archiver`\n"
776
- f"๐Ÿ“ฆ `{user_space_name[:20]}/archive`\n"
777
- f"๐Ÿ“ฅ ุนุจุฑ ุงู„ู‚ู†ุงุฉ\n\n"
778
  f"`{bar}` **{pct}%**\n"
779
  f"๐Ÿ“Œ **ุงู„ู…ุฑุญู„ุฉ:** {phase_name}\n"
780
  )
781
  if downloaded_bytes and total_bytes and total_bytes > 0:
782
- progress_text += f"๐Ÿ“Š **ุงู„ุญุฌู…:** {downloaded_bytes/1024/1024:.1f} / {total_bytes/1024/1024:.1f} MB\n"
783
  elif downloaded_bytes and not total_bytes:
784
- progress_text += f"๐Ÿ“Š **ุงู„ุญุฌู…:** {downloaded_bytes/1024/1024:.1f} MB\n"
785
  if speed and speed > 0:
786
  speed_mb = speed / 1024 / 1024
787
- progress_text += f"โšก **ุงู„ุณุฑุนุฉ:** {speed_mb:.1f} MB/s\n"
788
- if eta_seconds and eta_seconds > 0:
789
- eta_m, eta_s = divmod(eta_seconds, 60)
790
- progress_text += f"โฑ **๏ฟฝ๏ฟฝู„ูˆู‚ุช ุงู„ู…ุชุจู‚ูŠ:** {int(eta_m)}ุฏ {int(eta_s)}ุซ\n"
 
 
 
791
  if disk_free and disk_total:
792
  free_gb = disk_free / (1024**3)
793
  total_gb = disk_total / (1024**3)
@@ -795,108 +822,33 @@ async def _process_archive(client: Client, message: Message, state: dict, reply_
795
  disk_bar_len = 10
796
  disk_filled = int(disk_bar_len * used_gb / total_gb) if total_gb > 0 else 0
797
  disk_bar = "โ–ˆ" * disk_filled + "โ–‘" * (disk_bar_len - disk_filled)
798
- progress_text += f"๐Ÿ’พ **ุนุชุงุฏ ุงู„ู…ุณุงุญุฉ:** `{disk_bar}` {used_gb:.0f}/{total_gb:.0f} GB ({free_gb:.0f} GB ู…ุชุจู‚ูŠ)\n"
799
- if dataset_size_gb:
800
- progress_text += f"๐Ÿ“ฆ **ุญุฌู… ุงู„ุฏุงุชุงุณูŠุช:** {dataset_size_gb} GB\n"
801
- progress_text += f"โณ **ุงู„ูˆู‚ุช ุงู„ู…ู†ู‚ุถูŠ:** {elapsed:.0f}s\n"
802
  progress_text += f"โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n"
803
- progress_text += f"๐Ÿ“‹ `{msg_text[:60]}`"
804
-
805
- try:
806
- await msg.edit(progress_text, parse_mode=ParseMode.MARKDOWN)
807
- except Exception:
808
- pass
 
 
809
  last_pct = pct
810
-
811
- final_progress = api_call("GET", f"archive/progress", params={"archive_id": archive_id})
812
- pf = final_progress.get("progress", {})
813
- final_status = pf.get("status", "completed")
814
- final_msg = pf.get("message", "")
815
-
816
- title = metadata.get("title") or metadata.get("name", "N/A")
817
- release = metadata.get("release_date") or metadata.get("first_air_date", "")
818
- year = release[:4] if release else ""
819
-
820
- db_entry = {
821
- "archive_id": archive_id,
822
- "file_name": state["file_name"],
823
- "file_size": state.get("file_size", 0),
824
- "account": acc_info["name"],
825
- "media_id": str(metadata.get("id", "")),
826
- "media_type": metadata.get("media_type", ""),
827
- "title": title,
828
- "year": year,
829
- "quality": quality,
830
- "file_unique_id": state.get("file_unique_id", ""),
831
- "genres": ", ".join(g.get("name", "") for g in metadata.get("genres", [])),
832
- "rating": metadata.get("vote_average", 0),
833
- "overview": (metadata.get("overview") or "")[:500],
834
- "poster": metadata.get("poster_path", ""),
835
- "backdrop": metadata.get("backdrop_path", ""),
836
- "imdb_id": (metadata.get("external_ids") or {}).get("imdb_id", "") if isinstance(metadata.get("external_ids"), dict) else "",
837
- "tmdb_json": json.dumps(metadata, ensure_ascii=False, default=str),
838
- "timestamp": datetime.utcnow().isoformat(),
839
- "status": "archived" if final_status == "completed" else "failed",
840
- }
841
-
842
- sql = f"""
843
- INSERT OR REPLACE INTO archives
844
- (archive_id, file_name, file_size, account, media_id, media_type,
845
- title, year, genres, rating, overview, poster_path, backdrop_path,
846
- imdb_id, tmdb_json, timestamp, status, telegram_file_unique_id, quality)
847
- VALUES (
848
- '{db_entry['archive_id'].replace("'","''")}',
849
- '{db_entry['file_name'].replace("'","''")}',
850
- {db_entry['file_size']},
851
- '{db_entry['account'].replace("'","''")}',
852
- '{db_entry['media_id'].replace("'","''")}',
853
- '{db_entry['media_type'].replace("'","''")}',
854
- '{db_entry['title'].replace("'","''")}',
855
- '{db_entry['year'].replace("'","''")}',
856
- '{db_entry['genres'].replace("'","''")}',
857
- {db_entry['rating']},
858
- '{db_entry['overview'].replace("'","''")}',
859
- '{db_entry['poster'].replace("'","''")}',
860
- '{db_entry['backdrop'].replace("'","''")}',
861
- '{db_entry['imdb_id'].replace("'","''")}',
862
- '{db_entry['tmdb_json'].replace("'","''")}',
863
- '{db_entry['timestamp']}',
864
- '{db_entry['status']}',
865
- '{db_entry.get('file_unique_id', '').replace("'","''")}',
866
- '{db_entry['quality'].replace("'","''")}'
867
  )
868
- """
869
- db_result = api_call("POST", "db/exec", {"sql": sql})
870
-
871
- log_archive(archive_id, state["file_name"], acc_info["name"], title,
872
- "success" if final_status == "completed" else "failed",
873
- json.dumps({"progress": final_progress, "db_response": db_result}))
874
-
875
- elapsed = time.time() - start_time
876
- response = (
877
- f"โœ… **ุชู…ุช ุงู„ุฃุฑุดูุฉ ุจู†ุฌุงุญ!**\n\n"
878
- f"๐Ÿ“ **ุงู„ู…ู„ู:** `{state['file_name']}`\n"
879
- f"๐ŸŽฌ **ุงู„ุนู…ู„:** {title} ({year})\n"
880
- f"๐ŸŽฌ **ุงู„ุฌูˆุฏุฉ:** {quality}\n"
881
- f"๐Ÿ“‚ **ุงู„ุญุณุงุจ:** {acc_info['label']}\n"
882
- f"๐Ÿ†” **ุงู„ุฃุฑุดูŠู:** `{archive_id}`\n"
883
- f"๐Ÿ“Š **ุงู„ุญุฌู…:** {state.get('file_size', 0) / 1024 / 1024:.1f} MB\n"
884
- f"โญ **ุงู„ุชู‚ูŠูŠู…:** {metadata.get('vote_average', 'N/A')}/10\n"
885
- f"๐Ÿ“ฅ **ุงู„ู…ุตุฏุฑ:** ุงู„ู‚ู†ุงุฉ (ุชู„ูŠุบุฑุงู…)\n"
886
- f"โฑ **ุงู„ูˆู‚ุช:** {elapsed:.0f}s\n"
887
- )
888
- if metadata.get("poster_path"):
889
- response += f"๐Ÿ–ผ๏ธ https://image.tmdb.org/t/p/w500{metadata['poster_path']}\n"
890
 
891
- await msg.edit(response, parse_mode=ParseMode.MARKDOWN)
892
  delete_session(reply_id)
893
  USER_STATES.pop(reply_id, None)
894
  if message.chat:
895
  CURRENT_SESSION.pop(message.chat.id, None)
896
 
897
- stats = await _generate_stats()
898
- await message.reply(stats, parse_mode=ParseMode.MARKDOWN)
899
-
900
  async def _generate_stats() -> str:
901
  stats = api_call("GET", "stats/archive")
902
  if stats.get("error"):
 
728
  f"๐Ÿ†” `{archive_id}`\n"
729
  f"๐Ÿ“‚ **ุงู„ุญุณุงุจ:** {acc_info['label']}\n"
730
  f"๐ŸŒ **ุงู„ู…ุณุงุญุฉ:** `{user_space_name[:25]}-archiver`\n"
731
+ f"๐Ÿ“ฆ **ุงู„ุฏุงุชุงุณูŠุช:** `multimedia-cryptography-benchmarks/archive`\n"
732
  f"๐Ÿ“ฅ **ุงู„ู…ุตุฏุฑ:** ุงู„ู‚ู†ุงุฉ (ุชู„ูŠุบุฑุงู…)\n"
733
+ "โณ **ุจุงู†ุชุธุงุฑ ุจุฏุก ุงู„ุชุญู…ูŠู„...**"
734
  )
735
 
736
  start_time = time.time()
737
  last_pct = -1
738
+ last_progress_text = ""
739
+ max_poll_seconds = 7200
740
+
741
+ while time.time() - start_time < max_poll_seconds:
742
+ await asyncio.sleep(5)
743
  progress = api_call("GET", f"archive/progress", params={"archive_id": archive_id})
744
  p = progress.get("progress", {})
745
  status = p.get("status", "")
 
753
  downloaded_bytes = p.get("downloaded_bytes", 0)
754
  total_bytes = p.get("total_bytes", 0)
755
  eta_seconds = p.get("eta_seconds", 0)
 
756
 
757
  elapsed = time.time() - start_time
758
 
759
  if status in ("completed", "failed"):
760
+ elapsed_str = f"{int(elapsed // 60)}ุฏ {int(elapsed % 60)}ุซ"
761
+ await msg.edit(
762
+ f"{'โœ…' if status == 'completed' else 'โŒ'} **{'ุงูƒุชู…ู„ุช' if status == 'completed' else 'ูุดู„ุช'} ุงู„ุฃุฑุดูุฉ**\n\n"
763
+ f"๐Ÿ†” `{archive_id}`\n"
764
+ f"๐Ÿ“ `{state['file_name'][:35]}`\n"
765
+ f"๐Ÿ“‚ **{acc_info['label']}**\n"
766
+ f"โฑ **ุงู„ูˆู‚ุช:** {elapsed_str}\n"
767
+ f"{'๐Ÿ“‹' if status == 'completed' else 'โš ๏ธ'} `{msg_text[:80]}`",
768
+ parse_mode=ParseMode.MARKDOWN
769
+ )
770
+ delete_session(reply_id)
771
+ USER_STATES.pop(reply_id, None)
772
+ if message.chat:
773
+ CURRENT_SESSION.pop(message.chat.id, None)
774
+ return
775
 
776
+ if pct > last_pct or int(elapsed) % 10 == 0:
777
  bar_len = 14
778
  filled = int(bar_len * pct / 100)
779
  bar = "โ–ˆ" * filled + "โ–‘" * (bar_len - filled)
780
 
781
+ if "ุชุญู…ูŠู„" in msg_text:
782
+ phase_icon, phase_name = "๐Ÿ“ฅ", "ุชุญู…ูŠู„ ู…ู† ุงู„ู‚ู†ุงุฉ"
783
+ elif "ุฑูุน" in msg_text or "upload" in msg_text.lower():
784
+ phase_icon, phase_name = "๐Ÿ“ค", "ุฑูุน ุฅู„ู‰ HuggingFace"
785
+ elif "ู†ุณุฎ" in msg_text or "dataset" in msg_text.lower():
786
+ phase_icon, phase_name = "๐Ÿ“ฆ", "ู†ุณุฎ ุฅู„ู‰ ุงู„ุฏุงุชุงุณูŠุช"
787
+ else:
788
+ phase_icon, phase_name = "โณ", msg_text[:40] or "ู‚ูŠุฏ ุงู„ุชุฌู‡ูŠุฒ"
789
+
790
+ elapsed_m, elapsed_s = divmod(int(elapsed), 60)
791
+ elapsed_str = f"{elapsed_m:02d}:{elapsed_s:02d}"
792
 
793
  progress_text = (
794
  f"โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n"
 
798
  f"๐Ÿ“ `{state['file_name'][:35]}`\n"
799
  f"๐Ÿ“‚ **{acc_info['label']}**\n"
800
  f"๐ŸŒ `{user_space_name[:25]}-archiver`\n"
801
+ f"๐Ÿ“ฅ ุงู„ุชุญู…ูŠู„ ุนุจุฑ ุงู„ู‚ู†ุงุฉ\n\n"
 
802
  f"`{bar}` **{pct}%**\n"
803
  f"๐Ÿ“Œ **ุงู„ู…ุฑุญู„ุฉ:** {phase_name}\n"
804
  )
805
  if downloaded_bytes and total_bytes and total_bytes > 0:
806
+ progress_text += f"๐Ÿ“Š {downloaded_bytes/1024/1024:.1f} / {total_bytes/1024/1024:.1f} MB\n"
807
  elif downloaded_bytes and not total_bytes:
808
+ progress_text += f"๐Ÿ“Š {downloaded_bytes/1024/1024:.1f} MB\n"
809
  if speed and speed > 0:
810
  speed_mb = speed / 1024 / 1024
811
+ progress_text += f"โšก {speed_mb:.1f} MB/s"
812
+ if downloaded_bytes and total_bytes and total_bytes > 0:
813
+ remaining = total_bytes - downloaded_bytes
814
+ eta = remaining / speed if speed > 0 else 0
815
+ eta_m, eta_s = divmod(int(eta), 60)
816
+ progress_text += f" | โฑ ู…ุชุจู‚ูŠ {eta_m:02d}:{eta_s:02d}"
817
+ progress_text += "\n"
818
  if disk_free and disk_total:
819
  free_gb = disk_free / (1024**3)
820
  total_gb = disk_total / (1024**3)
 
822
  disk_bar_len = 10
823
  disk_filled = int(disk_bar_len * used_gb / total_gb) if total_gb > 0 else 0
824
  disk_bar = "โ–ˆ" * disk_filled + "โ–‘" * (disk_bar_len - disk_filled)
825
+ progress_text += f"๐Ÿ’พ `{disk_bar}` {used_gb:.0f}/{total_gb:.0f} GB ู…ุชุจู‚ูŠ {free_gb:.0f} GB\n"
826
+ progress_text += f"โณ ุงู„ูˆู‚ุช: {elapsed_str}\n"
 
 
827
  progress_text += f"โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n"
828
+ progress_text += f"๐Ÿ“‹ `{msg_text[:80]}`"
829
+
830
+ if progress_text != last_progress_text:
831
+ try:
832
+ await msg.edit(progress_text, parse_mode=ParseMode.MARKDOWN)
833
+ last_progress_text = progress_text
834
+ except Exception:
835
+ pass
836
  last_pct = pct
837
+ else:
838
+ await msg.edit(
839
+ f"โš ๏ธ **ุงู†ุชู‡ุช ู…ู‡ู„ุฉ ุงู„ุงู†ุชุธุงุฑ** ({max_poll_seconds//60} ุฏู‚ูŠู‚ุฉ)\n\n"
840
+ f"๐Ÿ†” `{archive_id}`\n"
841
+ f"๐Ÿ“ `{state['file_name'][:35]}`\n"
842
+ f"๐Ÿ“‚ **{acc_info['label']}**\n\n"
843
+ f"ู‚ุฏ ูŠูƒูˆู† ุงู„ุชุญู…ูŠู„ ู„ุง ูŠุฒุงู„ ุฌุงุฑูŠุงู‹. ุงุณุชุฎุฏู… `/status {archive_id}` ู„ู„ุชุญู‚ู‚.",
844
+ parse_mode=ParseMode.MARKDOWN
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
845
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
846
 
 
847
  delete_session(reply_id)
848
  USER_STATES.pop(reply_id, None)
849
  if message.chat:
850
  CURRENT_SESSION.pop(message.chat.id, None)
851
 
 
 
 
852
  async def _generate_stats() -> str:
853
  stats = api_call("GET", "stats/archive")
854
  if stats.get("error"):