diff --git a/archquise/H.Modules/AniLiberty.py b/archquise/H.Modules/AniLiberty.py
deleted file mode 100644
index 737456d..0000000
--- a/archquise/H.Modules/AniLiberty.py
+++ /dev/null
@@ -1,273 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2024-29 Archquise
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact archquise@gmail.com
-
-# ---------------------------------------------------------------------------------
-# Name: Aniliberty
-# Description: Searches and gives random anime on the Aniliberty database.
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# requires: dacite
-# scope: AniLiberty
-# scope: AniLiberty 0.0.1
-# ---------------------------------------------------------------------------------
-
-import logging
-
-from aiogram.types import CallbackQuery, InlineQueryResultPhoto
-from dataclasses import dataclass
-from json import JSONDecodeError
-from dacite import from_dict
-from typing import Optional
-
-
-import aiohttp
-
-from .. import loader
-from ..inline.types import InlineQuery
-
-logger = logging.getLogger(__name__)
-
-BASE_API_URL = "https://aniliberty.top/api/v1"
-
-
-# Датаклассы для парсинга и хранения json
-@dataclass
-class Genre:
- name: str
-
-
-@dataclass
-class Name:
- main: str
-
-
-@dataclass
-class Type:
- description: str
-
-
-@dataclass
-class Poster:
- preview: str
- thumbnail: str
-
-
-@dataclass
-class ReleaseInfo:
- id: int
- genres: Optional[list[Genre]]
- name: Name
- is_ongoing: bool
- type: Type
- description: str
- added_in_users_favorites: int
- alias: str
- poster: Poster
-
-
-@loader.tds
-class AniLibertyMod(loader.Module):
- """Ищет и возвращает случайное аниме из базы Aniliberty"""
-
- strings = {
- "name": "AniLiberty",
- "announce": "The announcement:",
- "ongoing": "Ongoing:",
- "type": "Type:",
- "genres": "Genres:",
- "favorite": "Favourites <3:", # < == <
- }
-
- strings_ru = {
- "announce": "Анонс:",
- "ongoing": "Онгоинг:",
- "type": "Тип:",
- "genres": "Жанры:",
- "favorite": "Избранное <3:", # < == <
- }
-
- def __init__(self):
- self._session: Optional[aiohttp.ClientSession] = None
-
- async def _get_session(self) -> aiohttp.ClientSession:
- if self._session is None or self._session.closed:
- self._session = aiohttp.ClientSession(
- timeout=aiohttp.ClientTimeout(total=15)
- )
- return self._session
-
- async def on_unload(self):
- if self._session and not self._session.closed:
- await self._session.close()
-
- async def search_title(self, query):
- session = await self._get_session()
- async with session.get(
- f"{BASE_API_URL}/app/search/releases?query={query}&include=id%2Cname.main%2Cis_ongoing%2Ctype.description%2Cdescription%2Cadded_in_users_favorites%2Calias%2Cposter.preview%2Cposter.thumbnail"
- ) as resp:
- json_answer = await resp.json()
- results = []
- for i in json_answer:
- obj = from_dict(data_class=ReleaseInfo, data=i)
- results.append(obj)
- return results
-
- async def get_title(self, release_id):
- session = await self._get_session()
- async with session.get(
- f"{BASE_API_URL}/anime/releases/{release_id}?include=id%2Cgenres.name%2Cname.main%2Cis_ongoing%2Ctype.description%2Cdescription%2Cadded_in_users_favorites%2Calias%2Cposter.preview%2Cposter.thumbnail"
- ) as resp:
- try:
- json_answer = await resp.json()
- data = from_dict(data_class=ReleaseInfo, data=json_answer)
- return data
- except JSONDecodeError:
- logger.error("Ошибка парсинга JSON!")
-
- async def get_random_title(self):
- session = await self._get_session()
- async with session.get(
- f"{BASE_API_URL}/anime/releases/random?limit=1&include=id"
- ) as resp:
- randid = await resp.json()
- data = await self.get_title(randid[0]["id"])
- return data
-
- @loader.command(
- ru_doc="Возвращает случайный релиз из базы",
- en_doc="Returns a random release from the database",
- )
- async def arandom(self, message) -> None:
- anime_release = await self.get_random_title()
- genres_str = ""
- for genre in anime_release.genres[:-1]:
- genres_str += f"{genre.name}, "
- genres_str += anime_release.genres[-1].name
-
- text = f"{anime_release.name.main} \n"
- text += f"{self.strings['ongoing']} {'Да' if anime_release.is_ongoing else 'Нет'}\n\n"
- text += f"{self.strings['type']} {anime_release.type.description}\n"
- text += f"{self.strings['genres']} {genres_str}\n\n"
-
- text += f"{anime_release.description}\n\n"
- text += (
- f"{self.strings['favorite']} {str(anime_release.added_in_users_favorites)}"
- )
-
- kb = [
- [
- {
- "text": "Ссылка",
- "url": f"https://aniliberty.top/anime/releases/release/{anime_release.alias}/episodes",
- }
- ]
- ]
-
- kb.append([{"text": "🔃 Обновить", "callback": self.inline__update}])
- kb.append([{"text": "🚫 Закрыть", "callback": self.inline__close}])
-
- await self.inline.form(
- text=text,
- photo=f"https://aniliberty.top{anime_release.poster.preview}",
- message=message,
- reply_markup=kb,
- silent=True,
- )
-
- @loader.inline_handler(
- ru_doc="Возвращает список найденных по названию тайтлов",
- en_doc="Returns a list of titles found by name",
- )
- async def asearch_inline_handler(self, query: InlineQuery) -> None:
- text = query.args
-
- if not text:
- return
-
- anime_releases = await self.search_title(text)
-
- inline_query = []
- for anime_release in anime_releases:
- """
- Приходится запрашивать по второму кругу, т.к. API в поиске не отдает жанры, даже если попросить через include
- """
- release_genres = await self.get_title(anime_release.id)
- genres_str = ""
- for genre in release_genres.genres[:-1]:
- genres_str += f"{genre.name}, "
- genres_str += release_genres.genres[-1].name
- release_text = (
- f"{anime_release.name.main}\n"
- f"{self.strings['ongoing']} {'Да' if anime_release.is_ongoing else 'Нет'}\n\n"
- f"{self.strings['type']} {anime_release.type.description}\n"
- f"{self.strings['genres']} {genres_str}\n\n"
- f"{anime_release.description}\n\n"
- f"{self.strings['favorite']} {anime_release.added_in_users_favorites}"
- )
-
- inline_query.append(
- InlineQueryResultPhoto(
- id=str(anime_release.id),
- title=anime_release.name.main,
- description=anime_release.type.description,
- caption=release_text,
- thumbnail_url=f"https://aniliberty.top{anime_release.poster.thumbnail}",
- photo_url=f"https://aniliberty.top{anime_release.poster.preview}",
- parse_mode="html",
- )
- )
- method = query.answer(inline_query, cache_time=0)
- await method.as_(self.inline.bot)
-
- async def inline__close(self, call: CallbackQuery) -> None:
- await call.delete()
-
- async def inline__update(self, call: CallbackQuery) -> None:
- anime_release = await self.get_random_title()
- genres_str = ""
- for genre in anime_release.genres[:-1]:
- genres_str += f"{genre.name}, "
- genres_str += anime_release.genres[-1].name
-
- text = f"{anime_release.name.main} \n"
- text += f"{self.strings['ongoing']} {'Да' if anime_release.is_ongoing else 'Нет'}\n\n"
- text += f"{self.strings['type']} {anime_release.type.description}\n"
- text += f"{self.strings['genres']} {genres_str}\n\n"
-
- text += f"{anime_release.description}\n\n"
- text += (
- f"{self.strings['favorite']} {str(anime_release.added_in_users_favorites)}"
- )
-
- kb = [
- [
- {
- "text": "Ссылка",
- "url": f"https://aniliberty.top/anime/releases/release/{anime_release.alias}/episodes",
- }
- ]
- ]
- kb.append([{"text": "🔃 Обновить", "callback": self.inline__update}])
- kb.append([{"text": "🚫 Закрыть", "callback": self.inline__close}])
-
- await call.edit(
- text=text,
- photo=f"https://aniliberty.top{anime_release.poster.preview}",
- reply_markup=kb,
- )
diff --git a/archquise/H.Modules/CodeShare.py b/archquise/H.Modules/CodeShare.py
deleted file mode 100644
index f22a523..0000000
--- a/archquise/H.Modules/CodeShare.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2026-2029 Archquise
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact archquise@gmail.com
-
-# ---------------------------------------------------------------------------------
-# Name: CodeShare
-# Description: Uploads your code at the kmi.aeza.net (Pastebin and GitHub Gist alternative)
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# requires: aiofiles
-# ---------------------------------------------------------------------------------
-
-import aiohttp
-import aiofiles
-import os
-import logging
-from typing import Optional
-
-from .. import loader, utils
-from telethon.types import MessageMediaDocument
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class CodeShareMod(loader.Module):
- """Uploads your code at the kmi.aeza.net (Pastebin and GitHub Gist alternative)"""
-
- strings = {
- "name": "CodeShare",
- "invalid_args": "❌ There is no arguments or reply with a file, or they are invalid",
- "_cls_doc": "Uploads your code at the kmi.aeza.net (Pastebin and GitHub Gist alternative)",
- "link_ready": "✅ Code uploaded! Link: {}",
- }
-
- strings_ru = {
- "_cls_doc": "Загружает ваш код на kmi.aeza.net (альтернатива Pastebin и GitHub Gist)",
- "invalid_args": "❌ Нет аргументов или реплая с файлом, или они неверны",
- "link_ready": "✅ Код загружен! Ссылка: {}",
- }
-
- def __init__(self):
- self._session: Optional[aiohttp.ClientSession] = None
-
- async def _get_session(self) -> aiohttp.ClientSession:
- if self._session is None or self._session.closed:
- self._session = aiohttp.ClientSession(
- timeout=aiohttp.ClientTimeout(total=15)
- )
- return self._session
-
- async def on_unload(self):
- if self._session and not self._session.closed:
- await self._session.close()
-
- async def upload_to_kmi(self, content: str) -> Optional[str]:
- url = "https://kmi.aeza.net"
- data = aiohttp.FormData()
- data.add_field("kmi", content)
-
- session = await self._get_session()
- async with session.post(url, data=data) as response:
- if response.status == 200:
- link = await response.text()
- return link
- else:
- logger.error(f"Error occurred! Status code: {response.status}")
- return None
-
- @loader.command(
- ru_doc="Загрузка кода на сайт",
- en_doc="Upload code to the site",
- )
- async def codesharecmd(self, message):
- args = utils.get_args(message)
- reply = await message.get_reply_message()
- if args:
- link = await self.upload_to_kmi(args)
- await utils.answer(message, self.strings["link_ready"].format(link))
- return
- if reply and isinstance(reply.media, MessageMediaDocument):
- file_name = await reply.download_media()
- async with aiofiles.open(file_name, mode="r") as f:
- content = await f.read()
- link = await self.upload_to_kmi(content)
- await os.remove(file_name)
- await utils.answer(message, self.strings["link_ready"].format(link))
- return
- await utils.answer(message, self.strings["invalid_args"])
diff --git a/archquise/H.Modules/FolderAutoRead.py b/archquise/H.Modules/FolderAutoRead.py
deleted file mode 100644
index fd742b7..0000000
--- a/archquise/H.Modules/FolderAutoRead.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2024-29 Archquise
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-# For any inquiries or requests for permissions, please contact archquise@gmail.com.
-
-# ---------------------------------------------------------------------------------
-# Name: FolderAutoRead
-# Description: Automatically reads chats in selected folders
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# ---------------------------------------------------------------------------------
-
-import logging
-
-from telethon import functions
-from telethon.tl.types import DialogFilter, InputPeerChannel
-
-from .. import loader, utils
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class FolderAutoReadMod(loader.Module):
- """Automatically reads chats in selected folders"""
-
- strings = {
- "name": "FolderAutoRead",
- "not_exists_or_already_added": "🚫 This folder does not exists or it is already added for tracking!",
- "_cls_doc": "Automatically reads chats in selected folders every 60 seconds!",
- "_cmd_doc_addfolder": "Adds folder to the tracking list by it's name. Usage: .addfolder FolderName",
- "_cmd_doc_listfolders": "Prints list of tracked folders",
- "_cmd_doc_delfolder": "Deletes folder from the tracking list",
- "wrong_args": "🚫 Wrong arguments! Usage: .addfolder/delfolder FolderName\n\nTip: If you trying to delete the folder from the tracking list, double-check that it really still tracking using .listfolders",
- "listfolders": "📁 List of tracked folders:\n",
- "delfolder": "🗑 Folder is successfully deleted from the tracking list!",
- "addfolder": "📁 Folder is successfully added to the tracking list!",
- }
-
- strings_ru = {
- "not_exists_or_already_added": "🚫 Такой папки не существует, или она уже добавлена для отслеживания!",
- "_cls_doc": "Автоматически читает чаты в выбранных папках каждые 60 секунд!",
- "_cmd_doc_addfolder": "Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки",
- "_cmd_doc_listfolders": "Выводит список отслеживаемых папок",
- "_cmd_doc_delfolder": "Удаляет папку из списка для отслежнивания",
- "wrong_args": "🚫 Неверные аргументы! Использование: .addfolder/delfolder НазваниеПапки\n\nСовет: Если вы пытаетесь удалить папку из списка отслеживания, проверьте, что она вообще отслеживается, используя .listfolders",
- "listfolders": "📁 Список отслеживаемых папок:\n",
- "delfolder": "🗑 Папка успешно удалена из листа отслеживания!",
- "addfolder": "📁 Папка успешно добавлена в лист отслеживания!",
- }
-
- def __init__(self):
- self.tracked_folders = []
-
- async def client_ready(self, client, db):
- self.tracked_folders = self.pointer("tracked_folders", [])
-
- async def _read_peers(self, peers):
- for peer in peers:
- try:
- await self._client(functions.messages.ReadMentionsRequest(peer=peer))
- await self._client(functions.messages.ReadReactionsRequest(peer=peer))
- if isinstance(peer, InputPeerChannel):
- await self._client(
- functions.channels.ReadHistoryRequest(channel=peer, max_id=0)
- )
- else:
- await self._client(
- functions.messages.ReadHistoryRequest(peer=peer, max_id=0)
- )
- except Exception as e:
- logger.debug(f"Failed to read peer {peer}: {e}")
-
- @loader.loop(interval=60, autostart=True)
- async def read_chats_in_folders(self):
- if self.tracked_folders:
- all_folders = await self._client(
- functions.messages.GetDialogFiltersRequest()
- )
- for folder_name in self.tracked_folders:
- match = next(
- (
- f
- for f in all_folders.filters
- if isinstance(f, DialogFilter) and f.title.text == folder_name
- ),
- None,
- )
- if match is None:
- continue
- await self._read_peers(match.pinned_peers)
- await self._read_peers(match.include_peers)
-
- @loader.command(
- ru_doc="Добавить папку в список отслеживания",
- en_doc="Add folder to the tracking list",
- )
- async def addfolder(self, message):
- arg = utils.get_args_raw(message)
- if arg:
- all_folders = await self._client(
- functions.messages.GetDialogFiltersRequest()
- )
- match = next(
- (
- f
- for f in all_folders.filters
- if isinstance(f, DialogFilter) and f.title.text == arg
- ),
- None,
- )
- if match and arg not in self.tracked_folders:
- self.tracked_folders.append(arg)
- await utils.answer(message, self.strings("addfolder"))
- else:
- await utils.answer(message, self.strings("not_exists_or_already_added"))
- else:
- await utils.answer(message, self.strings("wrong_args"))
-
- @loader.command(
- ru_doc="Удалить папку из списка отслеживания",
- en_doc="Delete folder from the tracking list",
- )
- async def delfolder(self, message):
- arg = utils.get_args_raw(message)
- if arg and arg in self.tracked_folders:
- self.tracked_folders.remove(arg)
- await utils.answer(message, self.strings("delfolder"))
- else:
- await utils.answer(message, self.strings("wrong_args"))
-
- @loader.command(
- ru_doc="Список отслеживаемых папок",
- en_doc="List tracked folders",
- )
- async def listfolders(self, message):
- await utils.answer(
- message,
- self.strings("listfolders")
- + "\n".join(f"• {folder}" for folder in self.tracked_folders),
- )
diff --git a/archquise/H.Modules/IrisSimpleMod.py b/archquise/H.Modules/IrisSimpleMod.py
deleted file mode 100644
index 662fe2c..0000000
--- a/archquise/H.Modules/IrisSimpleMod.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2024-29 CodWiz
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact codwiz@yandex.ru.
-
-# ---------------------------------------------------------------------------------
-# Name: IrisSimpleMod
-# Description: Module for basic interaction with Iris.
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# scope: IrisSimpleMod
-# scope: IrisSimpleMod 1.0.1
-# ---------------------------------------------------------------------------------
-
-import logging
-from typing import Optional
-
-from .. import loader, utils
-
-__version__ = (1, 0, 1)
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class IrisSimpleMod(loader.Module):
- """Module for basic interaction with Iris bot"""
-
- strings = {
- "name": "IrisSimpleMod",
- "checking_bag": "🌎 Checking bag...",
- "bag_result": "✅ Your bag: {}",
- "farming": "🌎 Farming iris-coins...",
- "farm_result": "✅ Farm result: {}",
- "getting_stats": "🌎 Getting user stats...",
- "stats_result": "✅ User stats: {}",
- "bot_stats": "🌎 Getting bot stats...",
- "bot_stats_result": "✅ Bot stats: {}",
- "error_no_response": "❌ No response from bot. Please try again.",
- "error_timeout": "❌ Request timeout. Please try again.",
- "error_general": "❌ An error occurred: {error}",
- }
-
- strings_ru = {
- "checking_bag": "🌎 Проверка мешка...",
- "bag_result": "✅ Ваш мешок: {}",
- "farming": "🌎 Фарм ирис-коинов...",
- "farm_result": "✅ Результат фарма: {}",
- "getting_stats": "🌎 Получение статистики пользователя...",
- "stats_result": "✅ Статистика пользователя: {}",
- "bot_stats": "🌎 Получение статистики ботов...",
- "bot_stats_result": "✅ Статистика ботов: {}",
- "error_no_response": "❌ Нет ответа от бота. Попробуйте еще раз.",
- "error_timeout": "❌ Таймаут запроса. Попробуйте еще раз.",
- "error_general": "❌ Произошла ошибка: {error}",
- }
-
- async def _send_and_delete(
- self, message, command_message: str, response_timeout: int = 15
- ) -> Optional[str]:
- """Send command to Iris and get response with timeout"""
- try:
- async with self.client.conversation(
- self._iris_user_id, timeout=self._timeout
- ) as conv:
- await conv.send_message(command_message)
- await message.delete()
-
- response_msg = await conv.get_response()
- if response_msg:
- await utils.answer(message, response_msg.text)
- return response_msg.text
- else:
- return None
- except Exception as e:
- logger.error(f"Error in conversation: {e}")
- await utils.answer(
- message, self.strings["error_general"].format(error=str(e))
- )
- return None
-
- @loader.command(
- ru_doc="Проверить мешок",
- en_doc="Check bag",
- )
- async def bag(self, message):
- """Check bag"""
- await utils.answer(message, self.strings["checking_bag"])
-
- result = await self._send_and_delete(message, "мешок", response_timeout=20)
-
- if result:
- await utils.answer(message, self.strings["bag_result"].format(result))
-
- @loader.command(
- ru_doc="Зафармить ирис-коины",
- en_doc="Farm iris-coins",
- )
- async def farm(self, message):
- """Farm iris-coins"""
- await utils.answer(message, self.strings["farming"])
-
- result = await self._send_and_delete(message, "ферма", response_timeout=25)
-
- if result:
- await utils.answer(message, self.strings["farm_result"].format(result))
-
- @loader.command(
- ru_doc="Вывести анкету",
- en_doc="Display user stats",
- )
- async def irisstats(self, message):
- """Display user stats"""
- await utils.answer(message, self.strings["getting_stats"])
-
- result = await self._send_and_delete(message, "анкета", response_timeout=20)
-
- if result:
- await utils.answer(message, self.strings["stats_result"].format(result))
diff --git a/archquise/H.Modules/TempChat.py b/archquise/H.Modules/TempChat.py
deleted file mode 100644
index 674daac..0000000
--- a/archquise/H.Modules/TempChat.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2024-29 CodWiz
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact codwiz@yandex.ru.
-
-# ---------------------------------------------------------------------------------
-# Name: TempChat
-# Description: Creates a temporary private chat with a message forwarding restriction and adds the specified user to it.
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# scope: TempChat
-# scope: TempChat 0.0.1
-# ---------------------------------------------------------------------------------
-
-import logging
-
-from hikkatl import functions
-from datetime import datetime as dt
-
-from .. import loader, utils
-
-logging.basicConfig(level=logging.ERROR)
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class TempChatMod(loader.Module):
- """Creates a temporary private chat with a message forwarding restriction and adds the specified user to it."""
-
- strings = {
- "name": "TempChat",
- "selfchat": "You can't create a chat with yourself.",
- "wrongargs": "❌ Wrong arguments. Use .tmpchat [@user/reply] [time]",
- "alreadychatting": "❌ You already have an active conversation with this person.",
- "invalidtime": "❌ Invalid time format. Use combinations like 1h30m.",
- "invitemsg": "🛡 You've been invited to a temporary private chat!\n\n⌛️ Auto-deletes in ",
- "joinlink": "🔗 Join link: ",
- "chatcreated": "✅ The temporary chat has been successfully created!",
- }
-
- strings_ru = {
- "selfchat": "Ты не можешь создать чат сам с собой.",
- "wrongargs": "❌ Неверные аргументы. Используй .tmpchat [@user/reply] [время]",
- "alreadychatting": "❌ У вас уже есть открытая переписка с этим человеком.",
- "invalidtime": "❌ Неверный формат времени. Убедитесь, что вы вводите время в формате 1h, 2h30m.",
- "invitemsg": "🛡 Вы были приглашены во временный приватный чат!\n\n⌛️ Авто-удаление через ",
- "joinlink": "🔗 Ссылка: ",
- "chatcreated": "✅ Временный чат успешно создан!",
- }
-
- def __init__(self):
- self.temp_chats = {}
-
- @loader.loop(interval=30, autostart=True)
- async def check_expired_chats(self):
- now = dt.now().timestamp()
- for chat_id in list(self.temp_chats.keys()):
- if self.temp_chats[chat_id][1] <= now:
- try:
- await self.client(
- functions.channels.DeleteChannelRequest(chat_id)
- )
- del self.temp_chats[chat_id]
- self.set("temp_chats", self.temp_chats)
- except Exception as e:
- logger.error(f"Error deleting chat {chat_id}: {e}")
- try:
- self.client(
- functions.channels.GetFullChannelRequest(
- channel=chat_id
- )
- )
- except Exception:
- del self.temp_chats[chat_id]
- self.set("temp_chats", self.temp_chats)
-
- async def client_ready(self, client, db):
- self.hmodslib = await self.import_lib(
- "https://files.archquise.ru/HModsLibrary.py"
- )
- self.temp_chats = self.get("temp_chats", {})
-
- @loader.command(
- ru_doc="Создает временный чат. Использование: .tmpchat [@user/reply] [time]"
- )
- async def tmpchat(self, message):
- """Create temporary chat. Usage: .tmpchat [@user/reply] [time]"""
- args = utils.get_args_raw(message)
- reply = await message.get_reply_message()
-
- if reply:
- user = await self.client.get_entity(reply.sender_id)
- time_str = args.strip() if args else None
- else:
- parts = args.split(",", 1) if "," in args else args.rsplit(" ", 1)
- if len(parts) != 2:
- return await utils.answer(message, self.strings["wrongargs"])
- user_str, time_str = parts[0].strip(), parts[1].strip()
- try:
- user = await self.client.get_entity(user_str)
- except Exception:
- return await utils.answer(message, self.strings["wrongargs"])
-
- if not time_str:
- return await utils.answer(message, self.strings["wrongargs"])
- seconds = await self.hmodslib.parse_time(time_str)
- if not seconds:
- return await utils.answer(message, self.strings["invalidtime"])
-
- if any(user.id == uid for uid, _ in self.temp_chats.values()):
- return await utils.answer(message, self.strings["alreadychatting"])
-
- try:
- created = await self.client(
- functions.channels.CreateChannelRequest(
- title=f"TempChat #{user.id}",
- about=f"Temporary private chat with {user.id} | Expires after: {time_str}",
- megagroup=True,
- )
- )
- chat_id = created.chats[0].id
- expires_at = dt.now().timestamp() + seconds
-
- await self.client(
- functions.messages.ToggleNoForwardsRequest(peer=chat_id, enabled=True)
- )
-
- self.temp_chats[chat_id] = (user.id, expires_at)
- self.set("temp_chats", self.temp_chats)
-
- invite = await self.client(
- functions.messages.ExportChatInviteRequest(peer=chat_id, usage_limit=1)
- )
- invite_message = (
- self.strings["invitemsg"]
- + time_str
- + f"\n{self.strings['joinlink']} {invite.link}"
- )
- await self.client.send_message(user.id, invite_message)
- await utils.answer(message, self.strings["chatcreated"])
-
- except Exception as e:
- logger.error(f"Error creating temp chat: {e}")
- await utils.answer(message, "❌ Error! Check log-chat.")
diff --git a/archquise/H.Modules/WindowsKeys.py b/archquise/H.Modules/WindowsKeys.py
deleted file mode 100644
index 26810db..0000000
--- a/archquise/H.Modules/WindowsKeys.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2024-29 CodWiz
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact codwiz@yandex.ru.
-
-# ---------------------------------------------------------------------------------
-# Name: WindowsKeys
-# Description: Provides you Windows activation keys
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# scope: WindowsKeys
-# scope: WindowsKeys 0.0.1
-# requires: requests
-# ---------------------------------------------------------------------------------
-
-import logging
-import time
-
-import aiohttp
-
-from .. import loader
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class WindowsKeysMod(loader.Module):
- """Windows activation keys"""
-
- strings = {
- "name": "WindowsKeys",
- "winkey": "✅ Key: {}\n\n⚠ For KMS activation only",
- "error": "❌ Failed to get key",
- "select": "🔓 Select version:",
- "close": "🎈 Close",
- "loading": "⌛ Loading...",
- }
-
- strings_ru = {
- "winkey": "✅ Ключ: {}\n\n⚠ Только для KMS активации",
- "error": "❌ Ошибка получения",
- "select": "🔓 Выберите версию:",
- "close": "🎈 Закрыть",
- "loading": "⌛ Загрузка...",
- }
-
- def __init__(self):
- self.cache = None
- self.cache_time = 0
- self.CACHE_TTL = 3600
-
- async def client_ready(self, client, db):
- self.client = client
- self.db = db
-
- @loader.command(ru_doc="Меню ключей Windows", en_doc="Windows keys menu")
- async def winkey(self, message):
- await self.inline.form(
- self.strings["select"],
- message=message,
- reply_markup=[
- [
- {
- "text": "Win 10/11 Pro",
- "callback": self._key,
- "args": ("win10_11pro",),
- }
- ],
- [
- {
- "text": "Win 10/11 LTSC",
- "callback": self._key,
- "args": ("win10_11enterpriseLTSC",),
- }
- ],
- [
- {
- "text": "Win 8.1 Pro",
- "callback": self._key,
- "args": ("win8.1pro",),
- }
- ],
- [{"text": "Win 8 Pro", "callback": self._key, "args": ("win8pro",)}],
- [{"text": "Win 7 Pro", "callback": self._key, "args": ("win7pro",)}],
- [
- {
- "text": "Vista Business",
- "callback": self._key,
- "args": ("winvistabusiness",),
- }
- ],
- [{"text": self.strings["close"], "action": "close"}],
- ],
- )
-
- async def _key(self, call, version):
- await call.edit(self.strings["loading"])
- keys = await self._get_keys()
- key = keys.get(version) if keys else None
- await call.edit(
- self.strings["winkey"].format(key) if key else self.strings["error"],
- reply_markup=[
- [{"text": "← Back", "callback": self.winkey}],
- [{"text": self.strings["close"], "action": "close"}],
- ],
- )
-
- async def _get_keys(self):
- if time.time() - self.cache_time < self.CACHE_TTL:
- return self.cache
-
- try:
- async with aiohttp.ClientSession(
- timeout=aiohttp.ClientTimeout(10)
- ) as session:
- async with session.get("https://files.archquise.ru/winkeys.json") as r:
- self.cache = await r.json()
- self.cache_time = time.time()
- return self.cache
- except Exception: # noqa: E722
- return None
diff --git a/archquise/H.Modules/face.py b/archquise/H.Modules/face.py
deleted file mode 100644
index 19007b1..0000000
--- a/archquise/H.Modules/face.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2024-29 CodWiz
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact codwiz@yandex.ru.
-
-# ---------------------------------------------------------------------------------
-# Name: face
-# Description: Random face
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# scope: Api face
-# scope: Api face 0.0.1
-# requires: aiohttp
-# ---------------------------------------------------------------------------------
-
-import logging
-from typing import Optional
-
-import aiohttp
-import re
-import random
-
-from .. import loader, utils
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class face(loader.Module):
- """random face"""
-
- strings = {
- "name": "face",
- "loading": (
- "🔍 I'm looking for you kaomoji"
- ),
- "random_face": (
- "🗿 Here is your random one kaomoji\n{}"
- ),
- "error": "An error has occurred!",
- }
-
- strings_ru = {
- "loading": (
- "🔍 Ищю вам kaomoji"
- ),
- "random_face": (
- "🗿 Вот ваш рандомный kaomoji\n{}"
- ),
- "error": "Произошла ошибка!",
- }
-
- def __init__(self):
- self._session: Optional[aiohttp.ClientSession] = None
-
- async def _get_session(self) -> aiohttp.ClientSession:
- if self._session is None or self._session.closed:
- self._session = aiohttp.ClientSession(
- timeout=aiohttp.ClientTimeout(total=15)
- )
- return self._session
-
- async def on_unload(self):
- if self._session and not self._session.closed:
- await self._session.close()
-
- @loader.command(
- ru_doc="Рандом kaomoji",
- en_doc="Random kaomoji",
- )
- async def rfacecmd(self, message):
- await utils.answer(message, self.strings("loading"))
-
- url = "https://files.archquise.ru/kaomoji.txt"
-
- session = await self._get_session()
- async with session.get(url) as response:
- if response.status == 200:
- data = await response.text()
- kaomoji_list = [
- s.strip() for s in re.split(r"[\t\r\n]+", data) if s.strip()
- ]
- kaomoji = random.choice(kaomoji_list)
- await utils.answer(message, self.strings("random_face").format(kaomoji))
- else:
- await utils.answer(message, self.strings("error"))
diff --git a/archquise/H.Modules/shortener.py b/archquise/H.Modules/shortener.py
deleted file mode 100644
index e97edd5..0000000
--- a/archquise/H.Modules/shortener.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2026-2029 Archquise
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact archquise@gmail.com
-
-# ---------------------------------------------------------------------------------
-# Name: Shortener
-# Description: Module for using bit.ly API
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# scope: Shortener
-# scope: Shortener 0.0.1
-# ---------------------------------------------------------------------------------
-
-import logging
-import re
-from typing import Optional
-
-import aiohttp
-
-from .. import loader, utils
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class Shortener(loader.Module):
- """Module for using bit.ly API"""
-
- strings = {
- "name": "Shortener",
- "no_api": "❌ You have not specified an API token from the site bit.ly",
- "statclcmd": "📊 Statistics on clicks for this link: {c}",
- "shortencmd": "✅ Your shortened link is ready: {c}",
- "no_args": "❌ Please provide a URL to shorten.",
- "invalid_url": "❌ Invalid URL format.",
- "api_error": "❌ API error: {error}",
- "_cls_doc": "Module for using bit.ly API",
- }
-
- strings_ru = {
- "no_api": "❌ Вы не указали api токен с сайта bit.ly",
- "statclcmd": "📊 Статистика о переходе по этой ссылке: {c}",
- "shortencmd": "✅ Ваша сокращённая ссылка готова: {c}",
- "no_args": "❌ Пожалуйста, укажите URL для сокращения.",
- "invalid_url": "❌ Неверный формат URL.",
- "api_error": "❌ Ошибка API: {error}",
- "_cls_doc": "Модуль для использования API bit.ly",
- }
-
- def __init__(self):
- self.config = loader.ModuleConfig(
- loader.ConfigValue(
- "token",
- None,
- lambda: "Need a token with https://app.bitly.com/settings/api/",
- validator=loader.validators.Hidden(),
- )
- )
- self._session: Optional[aiohttp.ClientSession] = None
-
- async def _get_session(self) -> aiohttp.ClientSession:
- if self._session is None or self._session.closed:
- self._session = aiohttp.ClientSession(
- timeout=aiohttp.ClientTimeout(total=15)
- )
- return self._session
-
- async def on_unload(self):
- if self._session and not self._session.closed:
- await self._session.close()
-
- def _validate_url(self, url: str) -> bool:
- """Validate URL format"""
- if not url:
- return False
-
- url_pattern = re.compile(
- r"^https?://"
- r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|"
- r"localhost|"
- r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
- r"(?::\d+)?"
- r"(?:/?|[/?]\S+)$",
- re.IGNORECASE,
- )
-
- return url_pattern.match(url) is not None
-
- async def shorten_url(self, url: str, token: str) -> Optional[str]:
- session = await self._get_session()
- async with session.post(
- "https://api-ssl.bitly.com/v4/shorten",
- json={"long_url": url},
- headers={"Authorization": f"Bearer {token}"},
- ) as resp:
- if resp.status == 201:
- json_response = await resp.json()
- return json_response["link"]
- else:
- logger.error(f"Error occurred! Status code: {resp.status}")
- return None
-
- async def get_bitlink_stats(self, bitlink: str, token: str) -> Optional[int]:
- session = await self._get_session()
- async with session.get(
- f"https://api-ssl.bitly.com/v4/bitlinks/{bitlink}/clicks/summary",
- headers={"Authorization": f"Bearer {token}"},
- ) as resp:
- if resp.status == 200:
- json_response = await resp.json()
- return json_response["total_clicks"]
- else:
- logger.error(f"Error occurred! Status code: {resp.status}")
- return None
-
- @loader.command(
- ru_doc="Сократить ссылку через bit.ly (ссылка с https://)",
- en_doc="Shorten the link via bit.ly (url with https://)",
- )
- async def shortencmd(self, message):
- """Shorten URL using bit.ly API"""
- if self.config["token"] is None:
- await utils.answer(message, self.strings("no_api"))
- return
-
- args = utils.get_args_raw(message)
- if not args:
- await utils.answer(message, self.strings("no_args"))
- return
-
- if not self._validate_url(args):
- await utils.answer(message, self.strings("invalid_url"))
- return
-
- try:
- short_url = await self.shorten_url(url=args, token=self.config["token"])
- if short_url is None:
- await utils.answer(
- message,
- self.strings("api_error").format(error="Failed to shorten URL"),
- )
- return
- await utils.answer(message, self.strings("shortencmd").format(c=short_url))
- except Exception as e:
- logger.error(f"Error shortening URL: {e}")
- await utils.answer(message, self.strings("api_error").format(error=str(e)))
-
- @loader.command(
- ru_doc="Посмотреть статистику ссылки через bit.ly (ссылка без https:// | Доступно только на платных аккаунтах)",
- en_doc="View link statistics via bit.ly (link without https:// | Works only on paid accounts)",
- )
- async def statclcmd(self, message):
- """Get click statistics for shortened URL"""
- if self.config["token"] is None:
- await utils.answer(message, self.strings("no_api"))
- return
-
- args = utils.get_args_raw(message)
- if not args:
- await utils.answer(message, self.strings("no_args"))
- return
-
- try:
- if not args.startswith("bit.ly/"):
- await utils.answer(message, self.strings("invalid_url"))
- return
- else:
- clicks = await self.get_bitlink_stats(
- bitlink=args, token=self.config["token"]
- )
- if clicks is None:
- await utils.answer(
- message,
- self.strings("api_error").format(
- error="Failed to get statistics"
- ),
- )
- return
- await utils.answer(message, self.strings("statclcmd").format(c=clicks))
- except Exception as e:
- logger.error(f"Error getting statistics: {e}")
- await utils.answer(message, self.strings("api_error").format(error=str(e)))
diff --git a/archquise/H.Modules/soundcloud.py b/archquise/H.Modules/soundcloud.py
index d4d9390..833a70d 100644
--- a/archquise/H.Modules/soundcloud.py
+++ b/archquise/H.Modules/soundcloud.py
@@ -633,7 +633,7 @@ class SoundCloudMod(loader.Module):
"oauth_token",
"",
"SoundCloud OAuth token",
- validator=loader.validators.String(),
+ validator=loader.validators.Hidden(),
),
loader.ConfigValue(
"history_count",
diff --git a/archquise/H.Modules/timezone.py b/archquise/H.Modules/timezone.py
deleted file mode 100644
index a53560d..0000000
--- a/archquise/H.Modules/timezone.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2026-2029 Archquise
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact archquise@gmail.com
-
-# ---------------------------------------------------------------------------------
-# Name: TimeZone
-# Description: Prints current time in selected timezone (UTC+n and tzdata formats supported)
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# requires: tzdata
-# ---------------------------------------------------------------------------------
-
-import logging
-import tzdata
-
-from datetime import datetime, timezone, timedelta
-from zoneinfo import ZoneInfo
-from .. import loader, utils
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class TimeZoneMod(loader.Module):
- """Prints current time in selected timezone (UTC+n and tzdata formats supported)"""
-
- strings = {
- "name": "TimeZone",
- "invalid_args": "❌ There is no arguments or they are invalid",
- "_cls_doc": "Prints current time in selected timezone (UTC+n and tzdata formats supported)",
- "time_utc": "🕓 Current time by UTC+{}: {}",
- "time_tzdata": "🕓 Current time in {}: {}",
- }
-
- strings_ru = {
- "_cls_doc": "Выводит текущее время в выбранном часовом поясе (поддерживаются форматы UTC+n и tzdata)",
- "invalid_args": "❌ Нет аргументов или они неверны",
- "tzdata_error": "❌ Произошла ошибка при получении времени по tzdata: {}\n\nУбедитесь, что часовой пояс указан верно",
- "time_utc": "🕓 Текущее время по UTC+{}: {}",
- "time_tzdata": "🕓 Текущее время в {}: {}",
- }
-
- @loader.command(
- ru_doc="Выводит время по UTC+n | Использование: .utc 4",
- en_doc="Prints UTC+n time | Usage: .utc 4",
- )
- async def utccmd(self, message):
- args = utils.get_args(message)
- if not args or not args[0].isdigit() or len(args) > 1:
- await utils.answer(message, self.strings["invalid_args"])
- return
- offset = timedelta(hours=int(args[0]))
- tz = timezone(offset)
- time = datetime.now(tz)
- await utils.answer(
- message, self.strings["time_utc"].format(args[0], time.strftime("%H:%M:%S"))
- )
-
- @loader.command(
- ru_doc="Выводит время по часовому поясу tzdata | Использование: .tzdata Europe/Moscow",
- en_doc="Prints time by tzdata timezone | Usage: .tzdata Europe/Moscow",
- )
- async def tzdatacmd(self, message):
- args = utils.get_args(message)
- if args[0].isdigit() or not args or len(args) > 1:
- await utils.answer(message, self.strings["invalid_args"])
- return
- try:
- time = datetime.now(ZoneInfo(args[0]))
- except Exception as e:
- await utils.answer(message, self.strings["tzdata_error"].format(e))
- logger.error(self.strings["tzdata_error"].format(e))
- return
- await utils.answer(
- message,
- self.strings["time_tzdata"].format(args[0], time.strftime("%H:%M:%S")),
- )
diff --git a/archquise/H.Modules/ytdl.py b/archquise/H.Modules/ytdl.py
deleted file mode 100644
index 9f35328..0000000
--- a/archquise/H.Modules/ytdl.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# Proprietary License Agreement
-
-# Copyright (c) 2026-2029
-
-# Permission is hereby granted to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal and non-commercial purposes, subject to the following conditions:
-
-# 1. The Software may not be modified, altered, or otherwise changed in any way without the explicit written permission of the author.
-
-# 2. Redistribution of the Software, in original or modified form, is strictly prohibited without the explicit written permission of the author.
-
-# 3. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
-
-# 4. Any use of the Software must include the above copyright notice and this permission notice in all copies or substantial portions of the Software.
-
-# 5. By using the Software, you agree to be bound by the terms and conditions of this license.
-
-# For any inquiries or requests for permissions, please contact archquise@gmail.com
-
-# ---------------------------------------------------------------------------------
-# Name: YTDL
-# Description: Downloads and sends audio/video from YouTube
-# Author: @hikka_mods
-# ---------------------------------------------------------------------------------
-# meta developer: @hikka_mods
-# requires: yt_dlp ffmpeg
-# ---------------------------------------------------------------------------------
-
-import shutil
-import platform
-import aiohttp
-import aiofiles
-import zipfile
-import os
-import re
-
-import logging
-
-from pathlib import Path
-from yt_dlp import YoutubeDL
-
-from .. import loader, utils
-
-logger = logging.getLogger(__name__)
-
-
-@loader.tds
-class YTDLMod(loader.Module):
- """Downloads and sends audio/video from YouTube"""
-
- strings = {
- "name": "YTDL",
- "_cls_doc": "Downloads and sends audio/video from YouTube",
- "invalid_args": "❌ There is no arguments or they are invalid",
- "downloading": "🕐 Downloading...",
- "done": "✅ Done!",
- }
-
- strings_ru = {
- "_cls_doc": "Скачивает и отправляет аудио/видео с Ютуба",
- "invalid_args": "❌ Нет аргументов или они неверны",
- "downloading": "🕐 Скачиваю...",
- "done": "✅ Готово!",
- }
-
- def _validate_url(self, url: str) -> bool:
- """Validate URL format"""
- if not url:
- return False
-
- url_pattern = re.compile(
- r"^(?:https?://)?(?:www\.|m\.)?(?:youtube\.com|youtu\.be|music\.youtube\.com)/(?:watch\?v=|playlist\?list=|channel/|@|live/|shorts/)?[\w-]+",
- re.IGNORECASE,
- )
-
- return url_pattern.match(url) is not None
-
- async def get_target(self):
- system = platform.system()
- machine = platform.machine().lower()
-
- if system == "Windows":
- return "Windows"
-
- if system == "Darwin":
- return (
- "aarch64-apple-darwin" if machine == "arm64" else "x86_64-apple-darwin"
- )
-
- if system == "Linux":
- return (
- "aarch64-unknown-linux-gnu"
- if machine in ("aarch64", "arm64")
- else "x86_64-unknown-linux-gnu"
- )
-
- return "x86_64-unknown-linux-gnu"
-
- def __init__(self):
- self.config = loader.ModuleConfig(
- loader.ConfigValue(
- "youtube_cookie",
- None,
- "Cookie вашего Ютуб-аккаунта (повышает стабильность и помогает скачивать видео с жесткими возрастными ограничениями) | Cookie of your YouTube-account (increases stability and helps downloading video with strict age rating restricrions)",
- validator=loader.validators.Hidden(),
- ),
- )
-
- async def client_ready(self, client, db):
- deno_path = Path("deno")
- deno_which = shutil.which("deno")
-
- # Trying to fix previous shitcode...
- if self.get("deno_source") == "file":
- self.set("deno_source", str(deno_path.resolve()))
-
- if not deno_which and not deno_path.is_file():
- logger.warning("Deno is not installed, attempting installation...")
- target = await self.get_target()
- if target == "Windows":
- logger.critical(
- "Windows platform is unsupported by this module. All future commands will fail. Please, unload the module."
- )
- return
- async with aiohttp.ClientSession() as session:
- download_link = f"https://github.com/denoland/deno/releases/latest/download/deno-{target}.zip"
- async with session.get(download_link) as resp:
- if resp.status == 200:
- async with aiofiles.open("deno.zip", mode="wb") as f:
- async for chunk in resp.content.iter_chunked(8192):
- await f.write(chunk)
- else:
- logger.critical(f"Failed to download Deno: HTTP {resp.status}")
- self.set("deno_source", "install_failed")
- return
- if Path("deno.zip").is_file():
- with zipfile.ZipFile("deno.zip", "r") as zip_ref:
- zip_ref.extractall()
- os.remove("deno.zip")
- os.chmod(deno_path, 0o755)
- self.set("deno_source", str(deno_path.resolve()))
- elif deno_which:
- self.set("deno_source", deno_which)
-
- @loader.command(en_doc="Download video", ru_doc="Скачать видео")
- async def ytdlvcmd(self, message):
- args = utils.get_args(message)
- if not args or not self._validate_url(args[0]) or len(args) > 1:
- await utils.answer(message, self.strings["invalid_args"])
- return
-
- source = self.get("deno_source")
- if source == "install_failed" or not Path(source).is_file():
- logger.critical(
- "Deno wasn't installed in auto-mode. Please, install it manually or resolve the issue and reboot userbot."
- )
- return
-
- await utils.answer(message, self.strings["downloading"])
-
- filename_prefix = f"video_{message.id}"
- ydl_opts = {
- "quiet": True,
- "outtmpl": f"{filename_prefix}.%(ext)s",
- "js_runtimes": {"deno": {"path": source}},
- "postprocessors": [
- {
- "key": "FFmpegVideoConvertor",
- "preferedformat": "mp4",
- }
- ],
- "postprocessor_args": {
- "video_convertor": [
- "-c:v",
- "libx264",
- "-pix_fmt",
- "yuv420p",
- "-preset",
- "veryfast",
- "-crf",
- "23",
- "-c:a",
- "aac",
- ],
- "merger": ["-movflags", "faststart"],
- },
- }
- if self.get("youtube_cookie"):
- ydl_opts["cookiefile"] = self.get("youtube_cookie")
- with YoutubeDL(ydl_opts) as ydl:
- info = ydl.extract_info(args[0], download=True)
- filename = ydl.prepare_filename(info).split(".")[0] + ".mp4"
- await utils.answer(message, self.strings['done'], file=filename, invert_media=True)
- os.remove(filename)
-
- @loader.command(en_doc="Download audio", ru_doc="Скачать аудио")
- async def ytdlacmd(self, message):
- args = utils.get_args(message)
- if not args or not self._validate_url(args[0]) or len(args) > 1:
- await utils.answer(message, self.strings["invalid_args"])
- return
-
- source = self.get("deno_source")
- if source == "install_failed" or not Path(source).is_file():
- logger.critical(
- "Deno wasn't installed in auto-mode. Please, install it manually or resolve the issue and reboot userbot."
- )
- return
-
- await utils.answer(message, self.strings["downloading"])
-
- filename_prefix = f"audio_{message.id}"
- ydl_opts = {
- "quiet": True,
- "outtmpl": f"{filename_prefix}.%(ext)s",
- "js_runtimes": {"deno": {"path": source}},
- "postprocessors": [
- {
- "key": "FFmpegExtractAudio",
- "preferredcodec": "mp3",
- "preferredquality": "0",
- },
- {
- "key": "FFmpegMetadata",
- "add_metadata": True,
- },
- {
- "key": "EmbedThumbnail",
- },
- ],
- "writethumbnail": True,
- }
- if self.get("youtube_cookie"):
- ydl_opts["cookiefile"] = self.get("youtube_cookie")
- with YoutubeDL(ydl_opts) as ydl:
- info = ydl.extract_info(args[0], download=True)
- filename = ydl.prepare_filename(info).split(".")[0] + ".mp3"
- await utils.answer(message, self.strings['done'], file=filename)
- os.remove(filename)
diff --git a/modules.json b/modules.json
index 9b248df..67d9b33 100644
--- a/modules.json
+++ b/modules.json
@@ -13278,74 +13278,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/timezone.py": {
- "name": "TimeZoneMod",
- "description": "Prints current time in selected timezone (UTC+n and tzdata formats supported)",
- "cls_doc": {
- "default": "Prints current time in selected timezone (UTC+n and tzdata formats supported)",
- "ru": "Выводит текущее время в выбранном часовом поясе (поддерживаются форматы UTC+n и tzdata)"
- },
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "utc": "(RU) Выводит время по UTC+n | Использование: .utc 4 | (EN) Prints UTC+n time | Usage: .utc 4"
- },
- {
- "tzdata": "(RU) Выводит время по часовому поясу tzdata | Использование: .tzdata Europe/Moscow | (EN) Prints time by tzdata timezone | Usage: .tzdata Europe/Moscow"
- }
- ],
- "new_commands": [
- {
- "name": "utc",
- "original_name": "utccmd",
- "description": {
- "default": "",
- "ru": "Выводит время по UTC+n | Использование: .utc 4",
- "en": "Prints UTC+n time | Usage: .utc 4"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "tzdata",
- "original_name": "tzdatacmd",
- "description": {
- "default": "",
- "ru": "Выводит время по часовому поясу tzdata | Использование: .tzdata Europe/Moscow",
- "en": "Prints time by tzdata timezone | Usage: .tzdata Europe/Moscow"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "TimeZone",
- "invalid_args": "❌ There is no arguments or they are invalid",
- "_cls_doc": "Prints current time in selected timezone (UTC+n and tzdata formats supported)",
- "time_utc": "🕓 Current time by UTC+{}: {}",
- "time_tzdata": "🕓 Current time in {}: {}",
- "invalid_args_ru": "❌ Нет аргументов или они неверны",
- "tzdata_error_ru": "❌ Произошла ошибка при получении времени по tzdata: {}\n\nУбедитесь, что часовой пояс указан верно",
- "time_utc_ru": "🕓 Текущее время по UTC+{}: {}",
- "time_tzdata_ru": "🕓 Текущее время в {}: {}"
- },
- "has_on_load": false,
- "has_on_unload": false,
- "class_cmd_names": {}
- },
"archquise/H.Modules/FakeActions.py": {
"name": "FakeActionsMod",
"description": "Module for simulating various actions in chat",
@@ -14013,103 +13945,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/IrisSimpleMod.py": {
- "name": "IrisSimpleMod",
- "description": "Module for basic interaction with Iris bot",
- "cls_doc": {},
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "bag": "Check bag | (RU) Проверить мешок | (EN) Check bag"
- },
- {
- "farm": "Farm iris-coins | (RU) Зафармить ирис-коины | (EN) Farm iris-coins"
- },
- {
- "irisstats": "Display user stats | (RU) Вывести анкету | (EN) Display user stats"
- }
- ],
- "new_commands": [
- {
- "name": "bag",
- "original_name": "bag",
- "description": {
- "default": "Check bag",
- "ru": "Проверить мешок",
- "en": "Check bag"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "farm",
- "original_name": "farm",
- "description": {
- "default": "Farm iris-coins",
- "ru": "Зафармить ирис-коины",
- "en": "Farm iris-coins"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "irisstats",
- "original_name": "irisstats",
- "description": {
- "default": "Display user stats",
- "ru": "Вывести анкету",
- "en": "Display user stats"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "IrisSimpleMod",
- "checking_bag": "🌎 Checking bag...",
- "bag_result": "✅ Your bag: {}",
- "farming": "🌎 Farming iris-coins...",
- "farm_result": "✅ Farm result: {}",
- "getting_stats": "🌎 Getting user stats...",
- "stats_result": "✅ User stats: {}",
- "bot_stats": "🌎 Getting bot stats...",
- "bot_stats_result": "✅ Bot stats: {}",
- "error_no_response": "❌ No response from bot. Please try again.",
- "error_timeout": "❌ Request timeout. Please try again.",
- "error_general": "❌ An error occurred: {error}",
- "checking_bag_ru": "🌎 Проверка мешка...",
- "bag_result_ru": "✅ Ваш мешок: {}",
- "farming_ru": "🌎 Фарм ирис-коинов...",
- "farm_result_ru": "✅ Результат фарма: {}",
- "getting_stats_ru": "🌎 Получение статистики пользователя...",
- "stats_result_ru": "✅ Статистика пользователя: {}",
- "bot_stats_ru": "🌎 Получение статистики ботов...",
- "bot_stats_result_ru": "✅ Статистика ботов: {}",
- "error_no_response_ru": "❌ Нет ответа от бота. Попробуйте еще раз.",
- "error_timeout_ru": "❌ Таймаут запроса. Попробуйте еще раз.",
- "error_general_ru": "❌ Произошла ошибка: {error}"
- },
- "has_on_load": false,
- "has_on_unload": false,
- "class_cmd_names": {}
- },
"archquise/H.Modules/sdsaver.py": {
"name": "SDSaverMod",
"description": "The module for automatically saving self-destructing media",
@@ -14585,107 +14420,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/FolderAutoRead.py": {
- "name": "FolderAutoReadMod",
- "description": "Automatically reads chats in selected folders",
- "cls_doc": {
- "default": "Automatically reads chats in selected folders every 60 seconds!",
- "ru": "Автоматически читает чаты в выбранных папках каждые 60 секунд!"
- },
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "addfolder": "Adds folder to the tracking list by it's name. Usage: .addfolder FolderName | (RU) Добавить папку в список отслеживания | (EN) Add folder to the tracking list | (R) Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки | (RU) Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки"
- },
- {
- "delfolder": "Deletes folder from the tracking list | (RU) Удалить папку из списка отслеживания | (EN) Delete folder from the tracking list | (R) Удаляет папку из списка для отслежнивания | (RU) Удаляет папку из списка для отслежнивания"
- },
- {
- "listfolders": "Prints list of tracked folders | (RU) Список отслеживаемых папок | (EN) List tracked folders | (R) Выводит список отслеживаемых папок | (RU) Выводит список отслеживаемых папок"
- }
- ],
- "new_commands": [
- {
- "name": "addfolder",
- "original_name": "addfolder",
- "description": {
- "default": "Adds folder to the tracking list by it's name. Usage: .addfolder FolderName",
- "ru": "Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки",
- "en": "Add folder to the tracking list",
- "r": "Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "delfolder",
- "original_name": "delfolder",
- "description": {
- "default": "Deletes folder from the tracking list",
- "ru": "Удаляет папку из списка для отслежнивания",
- "en": "Delete folder from the tracking list",
- "r": "Удаляет папку из списка для отслежнивания"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "listfolders",
- "original_name": "listfolders",
- "description": {
- "default": "Prints list of tracked folders",
- "ru": "Выводит список отслеживаемых папок",
- "en": "List tracked folders",
- "r": "Выводит список отслеживаемых папок"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "FolderAutoRead",
- "not_exists_or_already_added": "🚫 This folder does not exists or it is already added for tracking!",
- "_cls_doc": "Automatically reads chats in selected folders every 60 seconds!",
- "_cmd_doc_addfolder": "Adds folder to the tracking list by it's name. Usage: .addfolder FolderName",
- "_cmd_doc_listfolders": "Prints list of tracked folders",
- "_cmd_doc_delfolder": "Deletes folder from the tracking list",
- "wrong_args": "🚫 Wrong arguments! Usage: .addfolder/delfolder FolderName\n\nTip: If you trying to delete the folder from the tracking list, double-check that it really still tracking using .listfolders",
- "listfolders": "📁 List of tracked folders:\n",
- "delfolder": "🗑 Folder is successfully deleted from the tracking list!",
- "addfolder": "📁 Folder is successfully added to the tracking list!",
- "not_exists_or_already_added_ru": "🚫 Такой папки не существует, или она уже добавлена для отслеживания!",
- "_cmd_doc_ru_addfolder": "Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки",
- "_cmd_doc_addfolder_ru": "Добавляет папки в список отслеживания по их названию. Использование: .addfolder НазваниеПапки",
- "_cmd_doc_ru_listfolders": "Выводит список отслеживаемых папок",
- "_cmd_doc_listfolders_ru": "Выводит список отслеживаемых папок",
- "_cmd_doc_ru_delfolder": "Удаляет папку из списка для отслежнивания",
- "_cmd_doc_delfolder_ru": "Удаляет папку из списка для отслежнивания",
- "wrong_args_ru": "🚫 Неверные аргументы! Использование: .addfolder/delfolder НазваниеПапки\n\nСовет: Если вы пытаетесь удалить папку из списка отслеживания, проверьте, что она вообще отслеживается, используя .listfolders",
- "listfolders_ru": "📁 Список отслеживаемых папок:\n",
- "delfolder_ru": "🗑 Папка успешно удалена из листа отслеживания!",
- "addfolder_ru": "📁 Папка успешно добавлена в лист отслеживания!"
- },
- "has_on_load": false,
- "has_on_unload": false,
- "class_cmd_names": {}
- },
"archquise/H.Modules/MessageMonitor.py": {
"name": "MessageMonitor",
"description": "Monitor messages for trigger words in all chats.",
@@ -14959,51 +14693,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/face.py": {
- "name": "face",
- "description": "random face",
- "cls_doc": {},
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "rface": "(RU) Рандом kaomoji | (EN) Random kaomoji"
- }
- ],
- "new_commands": [
- {
- "name": "rface",
- "original_name": "rfacecmd",
- "description": {
- "default": "",
- "ru": "Рандом kaomoji",
- "en": "Random kaomoji"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "face",
- "loading": "🔍 I'm looking for you kaomoji",
- "random_face": "🗿 Here is your random one kaomoji\n{}",
- "error": "An error has occurred!",
- "loading_ru": "🔍 Ищю вам kaomoji",
- "random_face_ru": "🗿 Вот ваш рандомный kaomoji\n{}",
- "error_ru": "Произошла ошибка!"
- },
- "has_on_load": false,
- "has_on_unload": true,
- "class_cmd_names": {}
- },
"archquise/H.Modules/HAFK.py": {
"name": "HAFK",
"description": "",
@@ -15326,79 +15015,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/AniLiberty.py": {
- "name": "AniLibertyMod",
- "description": "Ищет и возвращает случайное аниме из базы Aniliberty",
- "cls_doc": {},
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "arandom": "(RU) Возвращает случайный релиз из базы | (EN) Returns a random release from the database"
- },
- {
- "asearchinlinehandler": ""
- }
- ],
- "new_commands": [
- {
- "name": "arandom",
- "original_name": "arandom",
- "description": {
- "default": "",
- "ru": "Возвращает случайный релиз из базы",
- "en": "Returns a random release from the database"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "asearchinlinehandler",
- "original_name": "asearch_inline_handler",
- "description": {
- "default": ""
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": true,
- "is_inline_handler": true,
- "decorators": []
- }
- ],
- "inline_handlers": [
- {
- "name": "asearchinlinehandler",
- "description": {
- "default": ""
- },
- "decorators": []
- }
- ],
- "strings": {
- "name": "AniLiberty",
- "announce": "The announcement:",
- "ongoing": "Ongoing:",
- "type": "Type:",
- "genres": "Genres:",
- "favorite": "Favourites <3:",
- "announce_ru": "Анонс:",
- "ongoing_ru": "Онгоинг:",
- "type_ru": "Тип:",
- "genres_ru": "Жанры:",
- "favorite_ru": "Избранное <3:"
- },
- "has_on_load": false,
- "has_on_unload": true,
- "class_cmd_names": {}
- },
"archquise/H.Modules/soundcloud.py": {
"name": "SoundCloudMod",
"description": "Display the currently playing SoundCloud track as a stylized card.",
@@ -16867,55 +16483,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/WindowsKeys.py": {
- "name": "WindowsKeysMod",
- "description": "Windows activation keys",
- "cls_doc": {},
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "winkey": "(RU) Меню ключей Windows | (EN) Windows keys menu"
- }
- ],
- "new_commands": [
- {
- "name": "winkey",
- "original_name": "winkey",
- "description": {
- "default": "",
- "ru": "Меню ключей Windows",
- "en": "Windows keys menu"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "WindowsKeys",
- "winkey": "✅ Key: {}\n\n⚠ For KMS activation only",
- "error": "❌ Failed to get key",
- "select": "🔓 Select version:",
- "close": "🎈 Close",
- "loading": "⌛ Loading...",
- "winkey_ru": "✅ Ключ: {}\n\n⚠ Только для KMS активации",
- "error_ru": "❌ Ошибка получения",
- "select_ru": "🔓 Выберите версию:",
- "close_ru": "🎈 Закрыть",
- "loading_ru": "⌛ Загрузка..."
- },
- "has_on_load": false,
- "has_on_unload": false,
- "class_cmd_names": {}
- },
"archquise/H.Modules/TimedEmojiStatus.py": {
"name": "TimedEmojiStatusMod",
"description": "Temporary emoji status with auto-revert using scheduler",
@@ -17683,125 +17250,6 @@
"has_on_unload": true,
"class_cmd_names": {}
},
- "archquise/H.Modules/ytdl.py": {
- "name": "YTDLMod",
- "description": "Downloads and sends audio/video from YouTube",
- "cls_doc": {
- "default": "Downloads and sends audio/video from YouTube",
- "ru": "Скачивает и отправляет аудио/видео с Ютуба"
- },
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "ytdlv": "(EN) Download video | (RU) Скачать видео"
- },
- {
- "ytdla": "(EN) Download audio | (RU) Скачать аудио"
- }
- ],
- "new_commands": [
- {
- "name": "ytdlv",
- "original_name": "ytdlvcmd",
- "description": {
- "default": "",
- "en": "Download video",
- "ru": "Скачать видео"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "ytdla",
- "original_name": "ytdlacmd",
- "description": {
- "default": "",
- "en": "Download audio",
- "ru": "Скачать аудио"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "YTDL",
- "_cls_doc": "Downloads and sends audio/video from YouTube",
- "invalid_args": "❌ There is no arguments or they are invalid",
- "downloading": "🕐 Downloading...",
- "done": "✅ Done!",
- "invalid_args_ru": "❌ Нет аргументов или они неверны",
- "downloading_ru": "🕐 Скачиваю...",
- "done_ru": "✅ Готово!"
- },
- "has_on_load": false,
- "has_on_unload": false,
- "class_cmd_names": {}
- },
- "archquise/H.Modules/TempChat.py": {
- "name": "TempChatMod",
- "description": "Creates a temporary private chat with a message forwarding restriction and adds the specified user to it.",
- "cls_doc": {},
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "tmpchat": "Create temporary chat. Usage: .tmpchat [@user/reply] [time] | (RU) Создает временный чат. Использование: .tmpchat [@user/reply] [time]"
- }
- ],
- "new_commands": [
- {
- "name": "tmpchat",
- "original_name": "tmpchat",
- "description": {
- "default": "Create temporary chat. Usage: .tmpchat [@user/reply] [time]",
- "ru": "Создает временный чат. Использование: .tmpchat [@user/reply] [time]"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "TempChat",
- "selfchat": "You can't create a chat with yourself.",
- "wrongargs": "❌ Wrong arguments. Use .tmpchat [@user/reply] [time]",
- "alreadychatting": "❌ You already have an active conversation with this person.",
- "invalidtime": "❌ Invalid time format. Use combinations like 1h30m.",
- "invitemsg": "🛡 You've been invited to a temporary private chat!\n\n⌛️ Auto-deletes in ",
- "joinlink": "🔗 Join link: ",
- "chatcreated": "✅ The temporary chat has been successfully created!",
- "selfchat_ru": "Ты не можешь создать чат сам с собой.",
- "wrongargs_ru": "❌ Неверные аргументы. Используй .tmpchat [@user/reply] [время]",
- "alreadychatting_ru": "❌ У вас уже есть открытая переписка с этим человеком.",
- "invalidtime_ru": "❌ Неверный формат времени. Убедитесь, что вы вводите время в формате 1h, 2h30m.",
- "invitemsg_ru": "🛡 Вы были приглашены во временный приватный чат!\n\n⌛️ Авто-удаление через ",
- "joinlink_ru": "🔗 Ссылка: ",
- "chatcreated_ru": "✅ Временный чат успешно создан!"
- },
- "has_on_load": false,
- "has_on_unload": false,
- "class_cmd_names": {}
- },
"archquise/H.Modules/search.py": {
"name": "Search",
"description": "Поисковик",
@@ -18013,79 +17461,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/shortener.py": {
- "name": "Shortener",
- "description": "Module for using bit.ly API",
- "cls_doc": {
- "default": "Module for using bit.ly API",
- "ru": "Модуль для использования API bit.ly"
- },
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "shorten": "Shorten URL using bit.ly API | (RU) Сократить ссылку через bit.ly (ссылка с https://) | (EN) Shorten the link via bit.ly (url with https://)"
- },
- {
- "statcl": "Get click statistics for shortened URL | (RU) Посмотреть статистику ссылки через bit.ly (ссылка без https:// | Доступно только на платных аккаунтах) | (EN) View link statistics via bit.ly (link without https:// | Works only on paid accounts)"
- }
- ],
- "new_commands": [
- {
- "name": "shorten",
- "original_name": "shortencmd",
- "description": {
- "default": "Shorten URL using bit.ly API",
- "ru": "Сократить ссылку через bit.ly (ссылка с https://)",
- "en": "Shorten the link via bit.ly (url with https://)"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- },
- {
- "name": "statcl",
- "original_name": "statclcmd",
- "description": {
- "default": "Get click statistics for shortened URL",
- "ru": "Посмотреть статистику ссылки через bit.ly (ссылка без https:// | Доступно только на платных аккаунтах)",
- "en": "View link statistics via bit.ly (link without https:// | Works only on paid accounts)"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "Shortener",
- "no_api": "❌ You have not specified an API token from the site bit.ly",
- "statclcmd": "📊 Statistics on clicks for this link: {c}",
- "shortencmd": "✅ Your shortened link is ready: {c}",
- "no_args": "❌ Please provide a URL to shorten.",
- "invalid_url": "❌ Invalid URL format.",
- "api_error": "❌ API error: {error}",
- "_cls_doc": "Module for using bit.ly API",
- "no_api_ru": "❌ Вы не указали api токен с сайта bit.ly",
- "statclcmd_ru": "📊 Статистика о переходе по этой ссылке: {c}",
- "shortencmd_ru": "✅ Ваша сокращённая ссылка готова: {c}",
- "no_args_ru": "❌ Пожалуйста, укажите URL для сокращения.",
- "invalid_url_ru": "❌ Неверный формат URL.",
- "api_error_ru": "❌ Ошибка API: {error}"
- },
- "has_on_load": false,
- "has_on_unload": true,
- "class_cmd_names": {}
- },
"archquise/H.Modules/Memes.py": {
"name": "MemesMod",
"description": "Random memes",
@@ -18131,53 +17506,6 @@
"has_on_unload": false,
"class_cmd_names": {}
},
- "archquise/H.Modules/CodeShare.py": {
- "name": "CodeShareMod",
- "description": "Uploads your code at the kmi.aeza.net (Pastebin and GitHub Gist alternative)",
- "cls_doc": {
- "default": "Uploads your code at the kmi.aeza.net (Pastebin and GitHub Gist alternative)",
- "ru": "Загружает ваш код на kmi.aeza.net (альтернатива Pastebin и GitHub Gist)"
- },
- "meta": {
- "pic": null,
- "banner": null,
- "developer": "@hikka_mods"
- },
- "commands": [
- {
- "codeshare": "(RU) Загрузка кода на сайт | (EN) Upload code to the site"
- }
- ],
- "new_commands": [
- {
- "name": "codeshare",
- "original_name": "codesharecmd",
- "description": {
- "default": "",
- "ru": "Загрузка кода на сайт",
- "en": "Upload code to the site"
- },
- "cmd_names": {},
- "aliases": [],
- "usage": null,
- "inline": false,
- "is_inline_handler": false,
- "decorators": []
- }
- ],
- "inline_handlers": [],
- "strings": {
- "name": "CodeShare",
- "invalid_args": "❌ There is no arguments or reply with a file, or they are invalid",
- "_cls_doc": "Uploads your code at the kmi.aeza.net (Pastebin and GitHub Gist alternative)",
- "link_ready": "✅ Code uploaded! Link: {}",
- "invalid_args_ru": "❌ Нет аргументов или реплая с файлом, или они неверны",
- "link_ready_ru": "✅ Код загружен! Ссылка: {}"
- },
- "has_on_load": false,
- "has_on_unload": true,
- "class_cmd_names": {}
- },
"archquise/H.Modules/passgen.py": {
"name": "PassgenMod",
"description": "generate random password",
@@ -85195,7 +84523,7 @@
}
},
"meta": {
- "total_modules": 1060,
- "generated_at": "2026-04-18T01:49:43.246930"
+ "total_modules": 1050,
+ "generated_at": "2026-04-19T02:02:03.488953"
}
}
\ No newline at end of file