Commit 0b9307a

benny-dou <60535774+benny-dou@users.noreply.github.com>
2025-03-14 14:34:50
fix: avoid FloodWait when sending to telegram
1 parent 2c990ab
Changed files (1)
src
messages
src/messages/sender.py
@@ -6,6 +6,7 @@ from pathlib import Path
 
 from loguru import logger
 from pyrogram.client import Client
+from pyrogram.errors import FloodWait
 from pyrogram.parser.markdown import BLOCKQUOTE_EXPANDABLE_DELIM, BLOCKQUOTE_EXPANDABLE_END_DELIM
 from pyrogram.types import Message, ReplyParameters
 
@@ -88,7 +89,7 @@ async def send2tg(
     remaining_texts = texts.removeprefix(caption)
     if 1 < len(media) <= 10:
         group = await warp_media_group(media, caption=caption)
-        sent_messages.extend(await client.send_media_group(target_chat, media=group, reply_parameters=reply_parameters))
+        sent_messages.extend(await send_media_group(client, target_chat, group, reply_parameters))
     else:  # media > 10
         media_chunks = [media[i : i + 10] for i in range(0, len(media), 10)]
         num_chunk = len(media_chunks)
@@ -96,10 +97,10 @@ async def send2tg(
         for idx, batch in enumerate(media_chunks):
             if idx == 0:  # first chunk
                 group = await warp_media_group(batch)
-                sent_messages.extend(await client.send_media_group(target_chat, media=group, reply_parameters=reply_parameters))
+                sent_messages.extend(await send_media_group(client, target_chat, group, reply_parameters))
             elif idx != num_chunk - 1:  # disbale reply if not the last chunk
                 group = await warp_media_group(batch)
-                sent_messages.extend(await client.send_media_group(target_chat, media=group, reply_parameters=ReplyParameters()))
+                sent_messages.extend(await send_media_group(client, target_chat, group, ReplyParameters()))
             else:  # last chunk:  media <= 10, add caption here
                 sent_messages.extend(await send2tg(client, message, target_chat, reply_msg_id=-1, texts=caption, media=batch, cooldown=cooldown, **kwargs))
             await asyncio.sleep(cooldown)
@@ -136,11 +137,17 @@ async def send_texts(
             and texts.count(BLOCKQUOTE_EXPANDABLE_END_DELIM) == 1
         ):
             continue
-        if idx == 0:
+        if idx != 0:
+            reply_parameters = ReplyParameters()
+        try:
             sent_messages.append(await client.send_message(target_chat, texts, reply_parameters=reply_parameters))
-        else:  # disbale reply
-            sent_messages.append(await client.send_message(target_chat, texts, reply_parameters=ReplyParameters()))
-            await asyncio.sleep(cooldown)
+        except FloodWait as e:
+            logger.warning(e)
+            await asyncio.sleep(e.value)  # type: ignore
+            sent_messages.append(await client.send_message(target_chat, texts, reply_parameters=reply_parameters))
+        except Exception as e:
+            logger.warning(f"send_texts: {e}")
+        await asyncio.sleep(cooldown)
     return sent_messages
 
 
@@ -159,11 +166,12 @@ async def send_single_media(
     caption = (await smart_split(texts, CAPTION_LENGTH))[0]
     remaining_texts = texts.removeprefix(caption)
     caption = warp_comments(caption)
-    if photo := media.get("photo"):
-        sent_messages.append(await client.send_photo(chat_id=target_chat, photo=photo, caption=caption, reply_parameters=reply_parameters))
-    elif video := media.get("video"):
-        sent_messages.append(
-            await client.send_video(
+    message = None
+    try:
+        if photo := media.get("photo"):
+            message = await client.send_photo(chat_id=target_chat, photo=photo, caption=caption, reply_parameters=reply_parameters)
+        elif video := media.get("video"):
+            message = await client.send_video(
                 chat_id=target_chat,
                 reply_parameters=reply_parameters,
                 caption=caption,
@@ -171,10 +179,9 @@ async def send_single_media(
                 progress_args=(kwargs.get("progress", False), video, kwargs.get("detail_progress", True)),
                 **media,
             )
-        )
-    elif audio := media.get("audio"):
-        sent_messages.append(
-            await client.send_audio(
+
+        elif audio := media.get("audio"):
+            message = await client.send_audio(
                 chat_id=target_chat,
                 reply_parameters=reply_parameters,
                 caption=caption,
@@ -182,10 +189,9 @@ async def send_single_media(
                 progress_args=(kwargs.get("progress", False), audio, kwargs.get("detail_progress", True)),
                 **media,
             )
-        )
-    elif document := media.get("document"):
-        sent_messages.append(
-            await client.send_document(
+
+        elif document := media.get("document"):
+            message = await client.send_document(
                 chat_id=target_chat,
                 reply_parameters=reply_parameters,
                 caption=caption,
@@ -193,7 +199,13 @@ async def send_single_media(
                 progress_args=(kwargs.get("progress", False), document, kwargs.get("detail_progress", True)),
                 **media,
             )
-        )
+    except FloodWait as e:
+        logger.warning(e)
+        await asyncio.sleep(e.value)  # type: ignore
+        return await send_single_media(client, target_chat, reply_parameters, media=media, texts=texts, cooldown=cooldown, **kwargs)
+    except Exception as e:
+        logger.warning(f"send_single_media: {e}")
+    sent_messages.append(message)
     if remaining_texts:
         sent_messages.extend(await send_texts(client, target_chat, ReplyParameters(), texts=remaining_texts, cooldown=cooldown))
 
@@ -202,3 +214,15 @@ async def send_single_media(
             logger.trace(f"Deleting: {media[key]}")
             Path(media[key]).unlink(missing_ok=True)
     return sent_messages
+
+
+async def send_media_group(client: Client, target_chat: int | str, media_group: list, reply_parameters: ReplyParameters) -> list[Message]:
+    try:
+        return await client.send_media_group(target_chat, media=media_group, reply_parameters=reply_parameters)
+    except FloodWait as e:
+        logger.warning(e)
+        await asyncio.sleep(e.value)  # type: ignore
+        return await send_media_group(client, target_chat, media_group, reply_parameters)
+    except Exception as e:
+        logger.warning(f"send_media_group: {e}")
+    return []