Merge pull request #273 from MuRuLOSE/update-submodules_63944822139e8b6869fe2250ad8c650e9db06765

Update of repositories 2026-05-03 02:11:45
This commit is contained in:
Zahar Vanilovv
2026-05-03 05:14:12 +03:00
committed by GitHub
5 changed files with 1435 additions and 437 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,7 @@ import random
import string import string
import asyncio import asyncio
import logging import logging
import re
from PIL import Image, UnidentifiedImageError from PIL import Image, UnidentifiedImageError
from telethon.tl.functions.stickers import CreateStickerSetRequest from telethon.tl.functions.stickers import CreateStickerSetRequest
@@ -38,11 +39,12 @@ except AttributeError:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
STATIC_STICKER_LIMIT = 120
EMOJI_LIMIT = 200
async def process_to_webp(input_path: str, output_path: str, size: int = 512) -> bool: async def process_to_webp(input_path: str, output_path: str, size: int = 512) -> bool:
try: try:
is_video = input_path.lower().endswith(('.mp4', '.webm', '.mov')) or b'ftyp' in open(input_path, 'rb').read(32) is_video = input_path.lower().endswith((".mp4", ".webm", ".mov")) or b"ftyp" in open(input_path, "rb").read(32)
if is_video: if is_video:
cap = cv2.VideoCapture(input_path) cap = cv2.VideoCapture(input_path)
success, frame = cap.read() success, frame = cap.read()
@@ -87,7 +89,7 @@ async def process_to_webp(input_path: str, output_path: str, size: int = 512) ->
async def process_to_png(input_path: str, output_path: str, size: int = 100) -> bool: async def process_to_png(input_path: str, output_path: str, size: int = 100) -> bool:
try: try:
is_video = input_path.lower().endswith(('.mp4', '.webm', '.mov')) or b'ftyp' in open(input_path, 'rb').read(32) is_video = input_path.lower().endswith((".mp4", ".webm", ".mov")) or b"ftyp" in open(input_path, "rb").read(32)
if is_video: if is_video:
cap = cv2.VideoCapture(input_path) cap = cv2.VideoCapture(input_path)
success, frame = cap.read() success, frame = cap.read()
@@ -137,8 +139,10 @@ class CreatePacks(loader.Module):
"processing": "<b>[CreatePacks]</b> Collecting avatars of participants...", "processing": "<b>[CreatePacks]</b> Collecting avatars of participants...",
"no_avatars": "<b>[CreatePacks]</b> No members with avatars", "no_avatars": "<b>[CreatePacks]</b> No members with avatars",
"no_valid": "<b>[CreatePacks]</b> Could not process any avatars", "no_valid": "<b>[CreatePacks]</b> Could not process any avatars",
"done_pack": "<b>[CreatePacks]</b> Sticker pack is ready:\n<b>[CreatePacks]</b> Open: <a href='https://t.me/addstickers/{}'>here</a>", "done_pack": "<b>[CreatePacks]</b> Sticker pack is ready:\n<b>[CreatePacks]</b> Open: <a href=\'https://t.me/addstickers/{}\\'>here</a>",
"done_emoji_pack": "<b>[CreatePacks]</b> Emoji pack is ready:\n<b>[CreatePacks]</b> Open: <a href='https://t.me/addstickers/{}'>here</a>", "done_packs": "<b>[CreatePacks]</b> Sticker packs are ready:\n{}",
"done_emoji_pack": "<b>[CreatePacks]</b> Emoji pack is ready:\n<b>[CreatePacks]</b> Open: <a href=\'https://t.me/addstickers/{}\\''>here</a>",
"done_emoji_packs": "<b>[CreatePacks]</b> Emoji packs are ready:\n{}",
"already": "<b>[CreatePacks]</b> A sticker pack with this name already exists.", "already": "<b>[CreatePacks]</b> A sticker pack with this name already exists.",
"emoji_processing": "<b>[CreatePacks]</b> Creating emoji pack from avatars...", "emoji_processing": "<b>[CreatePacks]</b> Creating emoji pack from avatars...",
"emoji_no_emoji": "<b>[CreatePacks]</b> No emoji specified — using", "emoji_no_emoji": "<b>[CreatePacks]</b> No emoji specified — using",
@@ -149,8 +153,10 @@ class CreatePacks(loader.Module):
"processing": "<b>[CreatePacks]</b> Собираю аватарки участников...", "processing": "<b>[CreatePacks]</b> Собираю аватарки участников...",
"no_avatars": "<b>[CreatePacks]</b> Нет участников с аватарками", "no_avatars": "<b>[CreatePacks]</b> Нет участников с аватарками",
"no_valid": "<b>[CreatePacks]</b> Не удалось обработать ни одну аватарку", "no_valid": "<b>[CreatePacks]</b> Не удалось обработать ни одну аватарку",
"done_pack": "<b>[CreatePacks]</b> Стикерпак готов:\n<b>[CreatePacks]</b> Открыть: <a href='https://t.me/addstickers/{}'>здесь</a>", "done_pack": "<b>[CreatePacks]</b> Стикерпак готов:\n<b>[CreatePacks]</b> Открыть: <a href=\'https://t.me/addstickers/{}\\''>здесь</a>",
"done_emoji_pack": "<b>[CreatePacks]</b> Эмодзи-пак готов:\n<b>[CreatePacks]</b> Открыть: <a href='https://t.me/addstickers/{}'>здесь</a>", "done_packs": "<b>[CreatePacks]</b> Стикерпаки готовы:\n{}",
"done_emoji_pack": "<b>[CreatePacks]</b> Эмодзи-пак готов:\n<b>[CreatePacks]</b> Открыть: <a href=\'https://t.me/addstickers/{}\\''>здесь</a>",
"done_emoji_packs": "<b>[CreatePacks]</b> Эмодзи-паки готовы:\n{}",
"already": "<b>[CreatePacks]</b> Стикерпак с таким именем уже существует", "already": "<b>[CreatePacks]</b> Стикерпак с таким именем уже существует",
"emoji_processing": "<b>[CreatePacks]</b> Создаю эмодзи-пак из аватаров...", "emoji_processing": "<b>[CreatePacks]</b> Создаю эмодзи-пак из аватаров...",
"emoji_no_emoji": "<b>[CreatePacks]</b> Эмодзи не указан — используется", "emoji_no_emoji": "<b>[CreatePacks]</b> Эмодзи не указан — используется",
@@ -169,10 +175,6 @@ class CreatePacks(loader.Module):
if len(users) >= 100: if len(users) >= 100:
break break
if not users:
shutil.rmtree(tmp_dir, ignore_errors=True)
return [], tmp_dir
processed = [] processed = []
process_func = process_to_webp if format == "webp" else process_to_png process_func = process_to_webp if format == "webp" else process_to_png
@@ -224,6 +226,43 @@ class CreatePacks(loader.Module):
return processed, tmp_dir return processed, tmp_dir
async def _create_sticker_pack(self, message, stickers_to_add, is_emoji_pack: bool, pack_number: int = 1, emoji: str = "🖼️"):
random_str = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
short_name = f"pack_{random_str}_by_fcreate"
chat = await message.get_chat()
chat_title = getattr(chat, 'title', 'Chat')
title_prefix = "Ava" if not is_emoji_pack else "Emoji"
full_title = f"{chat_title} {title_prefix} #{pack_number}"
try:
await self._client(CreateStickerSetRequest(
user_id="me",
title=full_title,
short_name=short_name,
stickers=stickers_to_add,
emojis=is_emoji_pack
))
return short_name, full_title
except PackShortNameOccupiedError:
random_str = ''.join(random.choices(string.ascii_lowercase + string.digits, k=12))
short_name = f"pack_{random_str}_by_fcreate"
try:
await self._client(CreateStickerSetRequest(
user_id="me",
title=full_title,
short_name=short_name,
stickers=stickers_to_add,
emojis=is_emoji_pack
))
return short_name, full_title
except:
return "already_exists", None
except Exception as e:
logger.error(f"Error creating pack: {e}")
return None, None
@loader.command( @loader.command(
ru_doc="- Создать стикерпак из аватаров в группе", ru_doc="- Создать стикерпак из аватаров в группе",
only_groups=True only_groups=True
@@ -236,11 +275,7 @@ class CreatePacks(loader.Module):
if not files: if not files:
return await message.edit(self.strings("no_avatars")) return await message.edit(self.strings("no_avatars"))
tag = ''.join(random.choices(string.ascii_lowercase + string.digits, k=4)) all_stickers = []
short_name = f"f{abs(message.chat_id)}_{tag}_by_fcreateavatars"
title = f"AvaPack {tag}"
stickers = []
for path in files: for path in files:
try: try:
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
@@ -248,42 +283,42 @@ class CreatePacks(loader.Module):
msg = await self._client.send_file("me", file, force_document=True) msg = await self._client.send_file("me", file, force_document=True)
doc = msg.document doc = msg.document
await self._client.delete_messages("me", msg.id) await self._client.delete_messages("me", msg.id)
stickers.append(InputStickerSetItem( all_stickers.append(InputStickerSetItem(
document=InputDocument(doc.id, doc.access_hash, doc.file_reference), document=InputDocument(doc.id, doc.access_hash, doc.file_reference),
emoji="🖼️" emoji="🖼️"
)) ))
except Exception as e: except Exception as e:
logger.error(f"Sticker loading error {path}: {e}") logger.error(f"Sticker loading error {path}: {e}")
continue continue
if not stickers: if not all_stickers:
shutil.rmtree(tmp_dir, ignore_errors=True) shutil.rmtree(tmp_dir, ignore_errors=True)
return await message.edit(self.strings("no_valid")) return await message.edit(self.strings("no_valid"))
try: created_packs_links = []
await self._client(CreateStickerSetRequest( pack_number = 1
user_id="me", for i in range(0, len(all_stickers), STATIC_STICKER_LIMIT):
title=title, current_pack_stickers = all_stickers[i : i + STATIC_STICKER_LIMIT]
short_name=short_name, short_name, full_title = await self._create_sticker_pack(message, current_pack_stickers, False, pack_number)
stickers=stickers if short_name == "already_exists":
)) await message.edit(self.strings("already"))
await message.edit(self.strings("done_pack").format(short_name)) shutil.rmtree(tmp_dir, ignore_errors=True)
except PackShortNameOccupiedError: return
await message.edit(self.strings("already")) elif short_name:
except Exception as e: created_packs_links.append(f"<a href=\'https://t.me/addstickers/{short_name}\\''>{full_title}</a>")
error_details = f"❌ Ошибка создания стикерпака:\n<code>{type(e).__name__}: {e}</code>\n" pack_number += 1
error_details += f"Пак: {short_name}\nСтикеров: {len(stickers)}\n"
if files: if created_packs_links:
error_details += f"Последний файл: {files[-1]}\n" if len(created_packs_links) == 1:
try: # Extract short name for the single link format
error_details += f"Размер: {Image.open(files[-1]).size}\n" sn = created_packs_links[0].split('/')[-1].split("'")[0]
error_details += f"Вес: {os.path.getsize(files[-1])} байт" await message.edit(self.strings("done_pack").format(sn))
except: else:
pass await message.edit(self.strings("done_packs").format("\n".join(created_packs_links)))
await message.edit(error_details) else:
logger.exception("Error creating sticker pack") await message.edit(self.strings("no_valid"))
finally:
shutil.rmtree(tmp_dir, ignore_errors=True) shutil.rmtree(tmp_dir, ignore_errors=True)
@loader.command( @loader.command(
ru_doc="[эмодзи] - Создать эмодзи-пак из всех аватаров", ru_doc="[эмодзи] - Создать эмодзи-пак из всех аватаров",
@@ -303,11 +338,7 @@ class CreatePacks(loader.Module):
if not files: if not files:
return await message.edit(self.strings("no_avatars")) return await message.edit(self.strings("no_avatars"))
tag = ''.join(random.choices(string.ascii_lowercase + string.digits, k=4)) all_emojis = []
short_name = f"f{abs(message.chat_id)}_{tag}_by_fcreateemojis"
title = f"EmojiPack {tag}"
stickers = []
for path in files: for path in files:
try: try:
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
@@ -315,7 +346,7 @@ class CreatePacks(loader.Module):
msg = await self._client.send_file("me", file, force_document=True) msg = await self._client.send_file("me", file, force_document=True)
doc = msg.document doc = msg.document
await self._client.delete_messages("me", msg.id) await self._client.delete_messages("me", msg.id)
stickers.append(InputStickerSetItem( all_emojis.append(InputStickerSetItem(
document=InputDocument(doc.id, doc.access_hash, doc.file_reference), document=InputDocument(doc.id, doc.access_hash, doc.file_reference),
emoji=emoji emoji=emoji
)) ))
@@ -323,32 +354,30 @@ class CreatePacks(loader.Module):
logger.error(f"Error loading emoji {path}: {e}") logger.error(f"Error loading emoji {path}: {e}")
continue continue
if not stickers: if not all_emojis:
shutil.rmtree(tmp_dir, ignore_errors=True) shutil.rmtree(tmp_dir, ignore_errors=True)
return await message.edit(self.strings("no_valid")) return await message.edit(self.strings("no_valid"))
try: created_packs_links = []
await self._client(CreateStickerSetRequest( pack_number = 1
user_id="me", for i in range(0, len(all_emojis), EMOJI_LIMIT):
title=title, current_pack_emojis = all_emojis[i : i + EMOJI_LIMIT]
short_name=short_name, short_name, full_title = await self._create_sticker_pack(message, current_pack_emojis, True, pack_number, emoji)
stickers=stickers, if short_name == "already_exists":
emojis=True await message.edit(self.strings("already"))
)) shutil.rmtree(tmp_dir, ignore_errors=True)
await message.edit(self.strings("done_emoji_pack").format(short_name)) return
except PackShortNameOccupiedError: elif short_name:
await message.edit(self.strings("already")) created_packs_links.append(f"<a href=\'https://t.me/addstickers/{short_name}\\''>{full_title}</a>")
except Exception as e: pack_number += 1
error_details = f"❌ Ошибка создания эмодзи-пака:\n<code>{type(e).__name__}: {e}</code>\n"
error_details += f"Пак: {short_name}\nСмайликов: {len(stickers)}\n" if created_packs_links:
if files: if len(created_packs_links) == 1:
error_details += f"Последний файл: {files[-1]}\n" sn = created_packs_links[0].split('/')[-1].split("'")[0]
try: await message.edit(self.strings("done_emoji_pack").format(sn))
error_details += f"Размер: {Image.open(files[-1]).size}\n" else:
error_details += f"Вес: {os.path.getsize(files[-1])} байт" await message.edit(self.strings("done_emoji_packs").format("\n".join(created_packs_links)))
except: else:
pass await message.edit(self.strings("no_valid"))
await message.edit(error_details)
logger.exception("Error creating emoji pack") shutil.rmtree(tmp_dir, ignore_errors=True)
finally:
shutil.rmtree(tmp_dir, ignore_errors=True)

View File

@@ -57,6 +57,12 @@
"gifts":[ "gifts":[
{"id": 5969796561943660080, "emoji": "🧸", "name": "Пасхальный мишка", "price": 50} {"id": 5969796561943660080, "emoji": "🧸", "name": "Пасхальный мишка", "price": 50}
] ]
},
"may_1th": {
"name": "🛠 1 Мая",
"gifts":[
{"id": 6026193266406327981, "emoji": "🧸", "name": "1 Мая мишка", "price": 50}
]
} }
} }
} }

View File

@@ -3981,16 +3981,20 @@
"processing": "<b>[CreatePacks]</b> Collecting avatars of participants...", "processing": "<b>[CreatePacks]</b> Collecting avatars of participants...",
"no_avatars": "<b>[CreatePacks]</b> No members with avatars", "no_avatars": "<b>[CreatePacks]</b> No members with avatars",
"no_valid": "<b>[CreatePacks]</b> Could not process any avatars", "no_valid": "<b>[CreatePacks]</b> Could not process any avatars",
"done_pack": "<b>[CreatePacks]</b> Sticker pack is ready:\n<b>[CreatePacks]</b> Open: <a href='https://t.me/addstickers/{}'>here</a>", "done_pack": "<b>[CreatePacks]</b> Sticker pack is ready:\n<b>[CreatePacks]</b> Open: <a href='https://t.me/addstickers/{}\\'>here</a>",
"done_emoji_pack": "<b>[CreatePacks]</b> Emoji pack is ready:\n<b>[CreatePacks]</b> Open: <a href='https://t.me/addstickers/{}'>here</a>", "done_packs": "<b>[CreatePacks]</b> Sticker packs are ready:\n{}",
"done_emoji_pack": "<b>[CreatePacks]</b> Emoji pack is ready:\n<b>[CreatePacks]</b> Open: <a href='https://t.me/addstickers/{}\\''>here</a>",
"done_emoji_packs": "<b>[CreatePacks]</b> Emoji packs are ready:\n{}",
"already": "<b>[CreatePacks]</b> A sticker pack with this name already exists.", "already": "<b>[CreatePacks]</b> A sticker pack with this name already exists.",
"emoji_processing": "<b>[CreatePacks]</b> Creating emoji pack from avatars...", "emoji_processing": "<b>[CreatePacks]</b> Creating emoji pack from avatars...",
"emoji_no_emoji": "<b>[CreatePacks]</b> No emoji specified — using", "emoji_no_emoji": "<b>[CreatePacks]</b> No emoji specified — using",
"processing_ru": "<b>[CreatePacks]</b> Собираю аватарки участников...", "processing_ru": "<b>[CreatePacks]</b> Собираю аватарки участников...",
"no_avatars_ru": "<b>[CreatePacks]</b> Нет участников с аватарками", "no_avatars_ru": "<b>[CreatePacks]</b> Нет участников с аватарками",
"no_valid_ru": "<b>[CreatePacks]</b> Не удалось обработать ни одну аватарку", "no_valid_ru": "<b>[CreatePacks]</b> Не удалось обработать ни одну аватарку",
"done_pack_ru": "<b>[CreatePacks]</b> Стикерпак готов:\n<b>[CreatePacks]</b> Открыть: <a href='https://t.me/addstickers/{}'>здесь</a>", "done_pack_ru": "<b>[CreatePacks]</b> Стикерпак готов:\n<b>[CreatePacks]</b> Открыть: <a href='https://t.me/addstickers/{}\\''>здесь</a>",
"done_emoji_pack_ru": "<b>[CreatePacks]</b> Эмодзи-пак готов:\n<b>[CreatePacks]</b> Открыть: <a href='https://t.me/addstickers/{}'>здесь</a>", "done_packs_ru": "<b>[CreatePacks]</b> Стикерпаки готовы:\n{}",
"done_emoji_pack_ru": "<b>[CreatePacks]</b> Эмодзи-пак готов:\n<b>[CreatePacks]</b> Открыть: <a href='https://t.me/addstickers/{}\\''>здесь</a>",
"done_emoji_packs_ru": "<b>[CreatePacks]</b> Эмодзи-паки готовы:\n{}",
"already_ru": "<b>[CreatePacks]</b> Стикерпак с таким именем уже существует", "already_ru": "<b>[CreatePacks]</b> Стикерпак с таким именем уже существует",
"emoji_processing_ru": "<b>[CreatePacks]</b> Создаю эмодзи-пак из аватаров...", "emoji_processing_ru": "<b>[CreatePacks]</b> Создаю эмодзи-пак из аватаров...",
"emoji_no_emoji_ru": "<b>[CreatePacks]</b> Эмодзи не указан — используется" "emoji_no_emoji_ru": "<b>[CreatePacks]</b> Эмодзи не указан — используется"
@@ -12019,6 +12023,12 @@
{ {
"g": "[текст или reply] — спросить у Gemini. Может анализировать ссылки." "g": "[текст или reply] — спросить у Gemini. Может анализировать ссылки."
}, },
{
"gask": "[текст или reply] — быстрый вопрос без сохранения в память."
},
{
"gmusic": "<промпт> — сгенерировать музыку/аудио через Gemini Lyria."
},
{ {
"gimg": "<промпт> [реплай на фото] — Генерация/Редактирование изображений через Gemini." "gimg": "<промпт> [реплай на фото] — Генерация/Редактирование изображений через Gemini."
}, },
@@ -12038,7 +12048,7 @@
"gautochats": "— Показать чаты с активным режимом авто-ответа." "gautochats": "— Показать чаты с активным режимом авто-ответа."
}, },
{ {
"gclear": "[auto] — очистить память в чате. auto для памяти gauto." "gclear": "[global/auto] — очистить память в чате. auto для памяти gauto."
}, },
{ {
"gpresets": "<save/load/del/list> — Управление пресетами (профилями)." "gpresets": "<save/load/del/list> — Управление пресетами (профилями)."
@@ -12067,11 +12077,17 @@
{ {
"gmemshow": "[auto] — Показать память чата (до 20 последних запросов). auto для gauto." "gmemshow": "[auto] — Показать память чата (до 20 последних запросов). auto для gauto."
}, },
{
"gprovider": "[gemini/openrouter] — сменить провайдера API."
},
{
"gprofile": "[auto|balanced|fast|reasoning|coding|vision|manual] — профиль авто-подбора модели."
},
{ {
"gmodel": "[model] [-s] — Узнать/сменить модель. -s — список. Авто-проверка совместимости." "gmodel": "[model] [-s] — Узнать/сменить модель. -s — список. Авто-проверка совместимости."
}, },
{ {
"gres": "[auto] — Очистить ВСЮ память. auto для всей памяти gauto." "gres": "[global/auto] — Очистить ВСЮ память. auto для всей памяти gauto."
} }
], ],
"new_commands": [ "new_commands": [
@@ -12088,6 +12104,32 @@
"is_inline_handler": false, "is_inline_handler": false,
"decorators": [] "decorators": []
}, },
{
"name": "gask",
"original_name": "gask",
"description": {
"default": "[текст или reply] — быстрый вопрос без сохранения в память."
},
"cmd_names": {},
"aliases": [],
"usage": null,
"inline": false,
"is_inline_handler": false,
"decorators": []
},
{
"name": "gmusic",
"original_name": "gmusic",
"description": {
"default": "<промпт> — сгенерировать музыку/аудио через Gemini Lyria."
},
"cmd_names": {},
"aliases": [],
"usage": null,
"inline": false,
"is_inline_handler": false,
"decorators": []
},
{ {
"name": "gimg", "name": "gimg",
"original_name": "gimg", "original_name": "gimg",
@@ -12170,7 +12212,7 @@
"name": "gclear", "name": "gclear",
"original_name": "gclear", "original_name": "gclear",
"description": { "description": {
"default": "[auto] — очистить память в чате. auto для памяти gauto." "default": "[global/auto] — очистить память в чате. auto для памяти gauto."
}, },
"cmd_names": {}, "cmd_names": {},
"aliases": [], "aliases": [],
@@ -12296,6 +12338,32 @@
"is_inline_handler": false, "is_inline_handler": false,
"decorators": [] "decorators": []
}, },
{
"name": "gprovider",
"original_name": "gprovider",
"description": {
"default": "[gemini/openrouter] — сменить провайдера API."
},
"cmd_names": {},
"aliases": [],
"usage": null,
"inline": false,
"is_inline_handler": false,
"decorators": []
},
{
"name": "gprofile",
"original_name": "gprofile",
"description": {
"default": "[auto|balanced|fast|reasoning|coding|vision|manual] — профиль авто-подбора модели."
},
"cmd_names": {},
"aliases": [],
"usage": null,
"inline": false,
"is_inline_handler": false,
"decorators": []
},
{ {
"name": "gmodel", "name": "gmodel",
"original_name": "gmodel", "original_name": "gmodel",
@@ -12313,7 +12381,7 @@
"name": "gres", "name": "gres",
"original_name": "gres", "original_name": "gres",
"description": { "description": {
"default": "[auto] — Очистить ВСЮ память. auto для всей памяти gauto." "default": "[global/auto] — Очистить ВСЮ память. auto для всей памяти gauto."
}, },
"cmd_names": {}, "cmd_names": {},
"aliases": [], "aliases": [],
@@ -12377,10 +12445,10 @@
}, },
"commands": [ "commands": [
{ {
"chatcopy": "<src> <dest> [start_id:final_id] [-n] [-dmc] [--now] [--media|--photo_video|--docs|--text] — Добавить задачу в очередь. --now: начать сразу, без полного подсчёта." "chatcopy": "<src> <dest> [start_id:final_id] [-n] [-dmc] [--now] [--itopic 1] [-theme123] [--media|--photo_video|--docs|--text] — Добавить задачу в очередь."
}, },
{ {
"ccwatch": "<src> <dest> [start_id:final_id] [-n] [-dmc][--media|--photo_video|--docs|--text] — Наблюдение за чатом" "ccwatch": "<src> <dest> [start_id:final_id] [-n] [-dmc] [--itopic 1] [-theme123] [--media|--photo_video|--docs|--text] — Наблюдение за чатом"
}, },
{ {
"cchelp": "— Подробная документация по модулю ChatCopy" "cchelp": "— Подробная документация по модулю ChatCopy"
@@ -12397,7 +12465,7 @@
"name": "chatcopy", "name": "chatcopy",
"original_name": "chatcopy", "original_name": "chatcopy",
"description": { "description": {
"default": "<src> <dest> [start_id:final_id] [-n] [-dmc] [--now] [--media|--photo_video|--docs|--text] — Добавить задачу в очередь. --now: начать сразу, без полного подсчёта." "default": "<src> <dest> [start_id:final_id] [-n] [-dmc] [--now] [--itopic 1] [-theme123] [--media|--photo_video|--docs|--text] — Добавить задачу в очередь."
}, },
"cmd_names": {}, "cmd_names": {},
"aliases": [], "aliases": [],
@@ -12410,7 +12478,7 @@
"name": "ccwatch", "name": "ccwatch",
"original_name": "ccwatch", "original_name": "ccwatch",
"description": { "description": {
"default": "<src> <dest> [start_id:final_id] [-n] [-dmc][--media|--photo_video|--docs|--text] — Наблюдение за чатом" "default": "<src> <dest> [start_id:final_id] [-n] [-dmc] [--itopic 1] [-theme123] [--media|--photo_video|--docs|--text] — Наблюдение за чатом"
}, },
"cmd_names": {}, "cmd_names": {},
"aliases": [], "aliases": [],
@@ -12465,8 +12533,9 @@
"cfg_batch": "Размер пачки сообщений (1-100)", "cfg_batch": "Размер пачки сообщений (1-100)",
"cfg_delay": "Задержка ОТПРАВКИ между пачками (сек)", "cfg_delay": "Задержка ОТПРАВКИ между пачками (сек)",
"cfg_flood_buffer": "Дополнительное время к FloodWait (сек)", "cfg_flood_buffer": "Дополнительное время к FloodWait (сек)",
"copy_start_prem": "<emoji document_id=5372917041193828849>🚀</emoji><b> ChatCopy: Запуск копирования</b>\n\n<b>Источник:</b> {src}\n<emoji document_id=5116204921766544244>⏬</emoji><emoji document_id=5116204921766544244>⏬</emoji><emoji document_id=5116204921766544244>⏬</emoji><emoji document_id=5116204921766544244>⏬</emoji>\n<b>Цель:</b> {dest}\n\n<emoji document_id=5258096772776991776>⚙️</emoji> <b>Режим:</b> {mode}\n<emoji document_id=5226513232549664618>🔢</emoji> <b>Старт с ID:</b> {start_id}\n<emoji document_id=6035191085452497972>👤</emoji> <b>Без автора:</b> {no_auth}\n<emoji document_id=6028504027531055196>💬</emoji> <b>Без подписей:</b> {no_capt}\n📎 <b>Фильтр:</b> {filter_type}\n📦 <b>Всего сообщений:</b> {total_msgs}\n⏱ <b>Оценка времени:</b> {estimated_time}\n\n<i>Задача добавлена в очередь. Позиция: {position}</i>", "cfg_timezone": "Часовой пояс для времени в статусах (UTC offset, например 3 для MSK)",
"copy_start_no_prem": "🚀 <b>ChatCopy: Запуск копирования</b>\n\n<b>Источник:</b> {src}\n⏬⏬⏬⏬\n<b>Цель:</b> {dest}\n\n⚙ <b>Режим:</b> {mode}\n🔢 <b>Старт с ID:</b> {start_id}\n👤 <b>Без автора:</b> {no_auth}\n💬 <b>Без подписей:</b> {no_capt}\n📎 <b>Фильтр:</b> {filter_type}\n📦 <b>Всего сообщений:</b> {total_msgs}\n⏱ <b>Оценка времени:</b> {estimated_time}\n\n<i>Задача добавлена в очередь. Позиция: {position}</i>", "copy_start_prem": "<emoji document_id=5372917041193828849>🚀</emoji><b> ChatCopy: Запуск копирования</b>\n\n<b>Источник:</b> {src}\n<emoji document_id=5116204921766544244>⏬</emoji><emoji document_id=5116204921766544244>⏬</emoji><emoji document_id=5116204921766544244>⏬</emoji><emoji document_id=5116204921766544244>⏬</emoji>\n<b>Цель:</b> {dest}\n\n<emoji document_id=5258096772776991776>⚙️</emoji> <b>Режим:</b> {mode}\n<emoji document_id=5226513232549664618>🔢</emoji> <b>Старт с ID:</b> {start_id}\n<emoji document_id=6035191085452497972>👤</emoji> <b>Без автора:</b> {no_auth}\n<emoji document_id=6028504027531055196>💬</emoji> <b>Без подписей:</b> {no_capt}\n📎 <b>Фильтр:</b> {filter_type}\n🚫 <b>Игнор топиков:</b> {ignored_topics}\n📦 <b>Всего сообщений:</b> {total_msgs}\n⏱ <b>Оценка времени:</b> {estimated_time}\n\n<i>Задача добавлена в очередь. Позиция: {position}</i>",
"copy_start_no_prem": "🚀 <b>ChatCopy: Запуск копирования</b>\n\n<b>Источник:</b> {src}\n⏬⏬⏬⏬\n<b>Цель:</b> {dest}\n\n⚙ <b>Режим:</b> {mode}\n🔢 <b>Старт с ID:</b> {start_id}\n👤 <b>Без автора:</b> {no_auth}\n💬 <b>Без подписей:</b> {no_capt}\n📎 <b>Фильтр:</b> {filter_type}\n🚫 <b>Игнор топиков:</b> {ignored_topics}\n📦 <b>Всего сообщений:</b> {total_msgs}\n⏱ <b>Оценка времени:</b> {estimated_time}\n\n<i>Задача добавлена в очередь. Позиция: {position}</i>",
"copy_done_detailed_prem": "<emoji document_id=5208422125924275090>✅</emoji> <b>Задача выполнена</b>\n<blockquote>{src} → {dest}\nБез автора: {no_auth}\nБез подписей: {no_capt}\nСтарт с ID: {start_id}\nРежим: {mode}\nФильтр: {filter_type}</blockquote>\n<emoji document_id=5123248930124989216>✅</emoji> <b>Перенесено сообщений: {count}</b> <emoji document_id=5123248930124989216>✅</emoji>\n⏱ <b>Длительность:</b> {duration}\n⚡ <b>Средняя скорость:</b> {avg_speed} сообщений/мин{flood_info}", "copy_done_detailed_prem": "<emoji document_id=5208422125924275090>✅</emoji> <b>Задача выполнена</b>\n<blockquote>{src} → {dest}\nБез автора: {no_auth}\nБез подписей: {no_capt}\nСтарт с ID: {start_id}\nРежим: {mode}\nФильтр: {filter_type}</blockquote>\n<emoji document_id=5123248930124989216>✅</emoji> <b>Перенесено сообщений: {count}</b> <emoji document_id=5123248930124989216>✅</emoji>\n⏱ <b>Длительность:</b> {duration}\n⚡ <b>Средняя скорость:</b> {avg_speed} сообщений/мин{flood_info}",
"copy_done_detailed_no_prem": "<b>Задача выполнена</b>\n<blockquote>{src} → {dest}\nБез автора: {no_auth}\nБез подписей: {no_capt}\nСтарт с ID: {start_id}\nРежим: {mode}\nФильтр: {filter_type}</blockquote>\n✔ <b>Перенесено сообщений: {count}</b> ✔️\n⏱ <b>Длительность:</b> {duration}\n⚡ <b>Средняя скорость:</b> {avg_speed} сообщений/мин{flood_info}", "copy_done_detailed_no_prem": "<b>Задача выполнена</b>\n<blockquote>{src} → {dest}\nБез автора: {no_auth}\nБез подписей: {no_capt}\nСтарт с ID: {start_id}\nРежим: {mode}\nФильтр: {filter_type}</blockquote>\n✔ <b>Перенесено сообщений: {count}</b> ✔️\n⏱ <b>Длительность:</b> {duration}\n⚡ <b>Средняя скорость:</b> {avg_speed} сообщений/мин{flood_info}",
"flood_wait_notice": "⏸ <b>FloodWait</b>\n📊 <b>Задержка:</b> <code>{minutes}m {seconds}s</code>\n🕐 <b>Возобновление:</b> <code>{resume_time}</code>\n📨 <b>Переслано:</b> <code>{count}</code> сообщений\n⏳ <b>Осталось:</b> <code>{remaining}</code> сообщений\n⚡ <b>Скорость:</b> <code>{speed}</code> сообщений/мин", "flood_wait_notice": "⏸ <b>FloodWait</b>\n📊 <b>Задержка:</b> <code>{minutes}m {seconds}s</code>\n🕐 <b>Возобновление:</b> <code>{resume_time}</code>\n📨 <b>Переслано:</b> <code>{count}</code> сообщений\n⏳ <b>Осталось:</b> <code>{remaining}</code> сообщений\n⚡ <b>Скорость:</b> <code>{speed}</code> сообщений/мин",
@@ -12485,8 +12554,9 @@
"forum_enable_failed": "❌ Не удалось включить топики в {chat}. Нужны права администратора.", "forum_enable_failed": "❌ Не удалось включить топики в {chat}. Нужны права администратора.",
"forum_not_channel": "❌ {chat} не является каналом/группой", "forum_not_channel": "❌ {chat} не является каналом/группой",
"err_ent": "❌ Ошибка: Чат не найден или нет доступа.", "err_ent": "❌ Ошибка: Чат не найден или нет доступа.",
"args_err": "❌ Синтаксис: .chatcopy <src> <dest>[start_id:final_id] [-n] [-dmc] [--now] [--media|--photo_video|--docs|--text]", "args_err": "❌ Синтаксис: .chatcopy <src> <dest> [start_id:final_id] [-n] [-dmc] [--now] [--itopic 1|\"Имя\"] [-theme123] [--media|--photo_video|--docs|--text]",
"watch_added": "<b>👀 Наблюдение активировано</b>\nID: <code>{src_id}</code>\n{src} -> {dest}\nРежим топиков: {topics}\nБез подписей: {no_capt}\nФильтр: {filter_type}", "watch_added": "<b>👀 Наблюдение активировано</b>\nID: <code>{src_id}</code>\n{src} -> {dest}\nРежим топиков: {topics}\nБез подписей: {no_capt}\nФильтр: {filter_type}\nИгнор топиков: {ignored}",
"copy_restricted": "❌ <b>Источник защищён запретом копирования/пересылки Telegram.</b>\n\nМодуль остановлен до добавления в очередь: скрытый обход этой защиты не выполняется. Используй источник, где копирование разрешено, или отключи защиту в своём чате.",
"queue_wait": "⏳ <b>Задача в очереди...</b> ({pos})", "queue_wait": "⏳ <b>Задача в очереди...</b> ({pos})",
"topic_created": "📂 Создан топик: <b>{title}</b>", "topic_created": "📂 Создан топик: <b>{title}</b>",
"topic_error": "❌ Ошибка создания топика: {error}", "topic_error": "❌ Ошибка создания топика: {error}",
@@ -78702,6 +78772,6 @@
}, },
"meta": { "meta": {
"total_modules": 995, "total_modules": 995,
"generated_at": "2026-04-24T17:42:27.132273" "generated_at": "2026-05-03T02:11:26.683417"
} }
} }