mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-17 23:04:17 +02:00
Fixed some bugs:
strange \n sometimes duplicating commands and reverted banner change bcs of i dont like current realization
This commit is contained in:
229
Limoka.py
229
Limoka.py
@@ -16,10 +16,11 @@ import re
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from typing import Union, List, Dict, Any
|
from typing import Union, List, Dict, Any, Optional
|
||||||
|
|
||||||
from telethon.types import Message
|
from telethon.types import Message
|
||||||
from telethon.errors.rpcerrorlist import WebpageMediaEmptyError
|
from telethon.errors.rpcerrorlist import WebpageMediaEmptyError
|
||||||
|
from telethon import events
|
||||||
try:
|
try:
|
||||||
from aiogram.utils.exceptions import BadRequest
|
from aiogram.utils.exceptions import BadRequest
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -30,7 +31,7 @@ from ..types import InlineQuery, InlineCall
|
|||||||
|
|
||||||
logger = logging.getLogger("Limoka")
|
logger = logging.getLogger("Limoka")
|
||||||
|
|
||||||
__version__ = (1, 2, 0)
|
__version__ = (1, 2, 1)
|
||||||
|
|
||||||
|
|
||||||
class Search:
|
class Search:
|
||||||
@@ -130,6 +131,13 @@ class Limoka(loader.Module):
|
|||||||
"no_category": "No category",
|
"no_category": "No category",
|
||||||
"global_button": "🌍 Results",
|
"global_button": "🌍 Results",
|
||||||
"filtered_button": "🏷️ Filtered search",
|
"filtered_button": "🏷️ Filtered search",
|
||||||
|
"inline_search": "🔍 Search in Limoka",
|
||||||
|
"inline_no_results": "❌ No modules found",
|
||||||
|
"inline_error": "❌ Search error occurred",
|
||||||
|
"inline_short_query": "❌ Query too short (min 2 chars)",
|
||||||
|
"inline_switch_pm": "💬 Open in chat",
|
||||||
|
"inline_switch_pm_text": "🔍 Results for: {query}",
|
||||||
|
"inline_start_message": "<emoji document_id=5413334818047940135>🔍</emoji> <b>Limoka Search</b>\n\nType module name or keyword",
|
||||||
}
|
}
|
||||||
|
|
||||||
strings_ru = {
|
strings_ru = {
|
||||||
@@ -194,6 +202,13 @@ class Limoka(loader.Module):
|
|||||||
"no_category": "Без категории",
|
"no_category": "Без категории",
|
||||||
"global_button": "🌍 Результаты",
|
"global_button": "🌍 Результаты",
|
||||||
"filtered_button": "🏷️ Поиск с фильтрами",
|
"filtered_button": "🏷️ Поиск с фильтрами",
|
||||||
|
"inline_search": "🔍 Поиск в Limoka",
|
||||||
|
"inline_no_results": "❌ Модули не найдены",
|
||||||
|
"inline_error": "❌ Ошибка поиска",
|
||||||
|
"inline_short_query": "❌ Запрос слишком короткий (мин. 2 символа)",
|
||||||
|
"inline_switch_pm": "💬 Открыть в чате",
|
||||||
|
"inline_switch_pm_text": "🔍 Результаты для: {query}",
|
||||||
|
"inline_start_message": "<emoji document_id=5413334818047940135>🔍</emoji> <b>Limoka Поиск</b>\n\nВведите название модуля или ключевое слово",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -271,13 +286,13 @@ class Limoka(loader.Module):
|
|||||||
commands = []
|
commands = []
|
||||||
for i, func in enumerate(module_info["commands"], 1):
|
for i, func in enumerate(module_info["commands"], 1):
|
||||||
if i > 9:
|
if i > 9:
|
||||||
commands.append("…")
|
commands.append("…\n")
|
||||||
break
|
break
|
||||||
for command, description in func.items():
|
for command, description in func.items():
|
||||||
emoji = self.strings["emojis"].get(i, "")
|
emoji = self.strings["emojis"].get(i, "")
|
||||||
desc = (description or self.strings["no_info"]).replace("\n", "\n\n")[:200]
|
desc = (description or self.strings["no_info"])
|
||||||
if len(desc) > 197:
|
if len(desc) > 150:
|
||||||
desc = desc[:197] + "…"
|
desc = desc[:147] + "…"
|
||||||
commands.append(
|
commands.append(
|
||||||
self.strings["command_template"].format(
|
self.strings["command_template"].format(
|
||||||
prefix=self.get_prefix(),
|
prefix=self.get_prefix(),
|
||||||
@@ -286,7 +301,7 @@ class Limoka(loader.Module):
|
|||||||
description=html.escape(desc),
|
description=html.escape(desc),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return commands
|
return commands[:5]
|
||||||
|
|
||||||
async def _display_filter_menu(self, call: InlineCall, query: str, current_filters: dict):
|
async def _display_filter_menu(self, call: InlineCall, query: str, current_filters: dict):
|
||||||
categories = current_filters.get("category", [])
|
categories = current_filters.get("category", [])
|
||||||
@@ -448,7 +463,7 @@ class Limoka(loader.Module):
|
|||||||
|
|
||||||
async def _display_module(
|
async def _display_module(
|
||||||
self,
|
self,
|
||||||
message_or_call: Union[Message, InlineCall],
|
message_or_call: Union[Message, InlineCall, None],
|
||||||
module_info: Dict[str, Any],
|
module_info: Dict[str, Any],
|
||||||
module_path: str,
|
module_path: str,
|
||||||
query: str,
|
query: str,
|
||||||
@@ -470,6 +485,9 @@ class Limoka(loader.Module):
|
|||||||
categories=', '.join(html.escape(c) for c in categories) if categories else self.strings["no_category"]
|
categories=', '.join(html.escape(c) for c in categories) if categories else self.strings["no_category"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if len(description) > 300:
|
||||||
|
description = description[:297] + "…"
|
||||||
|
|
||||||
core_message = self.strings["found"].format(
|
core_message = self.strings["found"].format(
|
||||||
query=html.escape(query),
|
query=html.escape(query),
|
||||||
name=name,
|
name=name,
|
||||||
@@ -481,42 +499,24 @@ class Limoka(loader.Module):
|
|||||||
module_path=html.escape(clean_module_path),
|
module_path=html.escape(clean_module_path),
|
||||||
)
|
)
|
||||||
|
|
||||||
static_suffix = f"\n{filters_text}"
|
full_message = core_message[:4096]
|
||||||
max_core_len = 1024 - len(static_suffix)
|
|
||||||
|
|
||||||
if max_core_len < 50:
|
caption_message = full_message
|
||||||
max_core_len = 50
|
if len(caption_message) > 1024:
|
||||||
|
|
||||||
if len(core_message) > max_core_len:
|
|
||||||
safe_query = html.escape(query[:30]) + ("..." if len(query) > 30 else "")
|
safe_query = html.escape(query[:30]) + ("..." if len(query) > 30 else "")
|
||||||
safe_name = name[:40] + ("..." if len(name) > 40 else "")
|
safe_name = name[:40] + ("..." if len(name) > 40 else "")
|
||||||
safe_dev = dev_username[:30] + ("..." if len(dev_username) > 30 else "")
|
safe_desc = description[:100] + ("…" if len(description) > 100 else "")
|
||||||
|
|
||||||
|
caption_message = (
|
||||||
|
f"<emoji document_id=5413334818047940135>🔍</emoji> <b>{safe_name}</b>\n"
|
||||||
|
f"<b><emoji document_id=5418376169055602355>ℹ️</emoji> Desc:</b> {safe_desc}\n"
|
||||||
|
f"<b><emoji document_id=5418299289141004396>🧑💻</emoji> Dev:</b> {dev_username}\n\n"
|
||||||
|
f"<emoji document_id=5411143117711624172>🪄</emoji> <code>{self.get_prefix()}dlm {self.config['limokaurl']}{html.escape(clean_module_path)}</code>"
|
||||||
|
)[:1024]
|
||||||
|
|
||||||
desc_max = max(50, (max_core_len - 250) // 2)
|
static_suffix = f"\n{filters_text}"
|
||||||
safe_desc = description[:desc_max] + ("…" if len(description) > desc_max else "")
|
if len(caption_message) + len(static_suffix) <= 1024:
|
||||||
|
caption_message += static_suffix
|
||||||
safe_commands = []
|
|
||||||
for cmd in commands[:3]:
|
|
||||||
if len(cmd) > 150:
|
|
||||||
cmd = cmd[:147] + "…"
|
|
||||||
safe_commands.append(cmd)
|
|
||||||
|
|
||||||
core_message = (
|
|
||||||
f"<emoji document_id=5413334818047940135>🔍</emoji> "
|
|
||||||
f"Found module <b>{safe_name}</b> by query: <b>{safe_query}</b>\n\n"
|
|
||||||
f"<b><emoji document_id=5418376169055602355>ℹ️</emoji> Description:</b> {safe_desc}\n"
|
|
||||||
f"<b><emoji document_id=5418299289141004396>🧑💻</emoji> Developer:</b> {safe_dev}\n\n"
|
|
||||||
f"{''.join(safe_commands)}"
|
|
||||||
)
|
|
||||||
|
|
||||||
core_message = re.sub(r'\n\s*\n', '\n\n', core_message)
|
|
||||||
core_message = "\n".join(line.strip() for line in core_message.splitlines())
|
|
||||||
core_message = core_message.rstrip("\n")
|
|
||||||
|
|
||||||
if len(core_message) > max_core_len:
|
|
||||||
core_message = core_message[:max_core_len - 3] + "…"
|
|
||||||
|
|
||||||
full_message = (core_message + static_suffix)[:1024]
|
|
||||||
|
|
||||||
markup = [
|
markup = [
|
||||||
[
|
[
|
||||||
@@ -542,33 +542,64 @@ class Limoka(loader.Module):
|
|||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if message_or_call is None:
|
||||||
|
logger.error("message_or_call is None in _display_module")
|
||||||
|
return
|
||||||
|
|
||||||
if isinstance(message_or_call, Message):
|
if isinstance(message_or_call, Message):
|
||||||
await self.inline.form(
|
if banner_url and banner_url != self.fallback_banner:
|
||||||
text=full_message,
|
await self.inline.form(
|
||||||
message=message_or_call,
|
text=caption_message,
|
||||||
reply_markup=markup,
|
message=message_or_call,
|
||||||
photo=banner_url
|
reply_markup=markup,
|
||||||
)
|
photo=banner_url
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await self.inline.form(
|
||||||
|
text=full_message,
|
||||||
|
message=message_or_call,
|
||||||
|
reply_markup=markup
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
await message_or_call.edit(
|
if banner_url and banner_url != self.fallback_banner:
|
||||||
text=full_message,
|
await message_or_call.edit(
|
||||||
reply_markup=markup,
|
text=caption_message,
|
||||||
photo=banner_url
|
reply_markup=markup,
|
||||||
)
|
photo=banner_url
|
||||||
except (BadRequest, WebpageMediaEmptyError):
|
)
|
||||||
if isinstance(message_or_call, Message):
|
else:
|
||||||
|
await message_or_call.edit(
|
||||||
|
text=full_message,
|
||||||
|
reply_markup=markup
|
||||||
|
)
|
||||||
|
except (BadRequest, WebpageMediaEmptyError) as e:
|
||||||
|
logger.exception(f"Error in _display_module: {e}")
|
||||||
|
if message_or_call is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
if isinstance(message_or_call, Message):
|
||||||
|
target_message = message_or_call
|
||||||
|
elif hasattr(message_or_call, 'message') and isinstance(message_or_call.message, Message):
|
||||||
|
target_message = message_or_call.message
|
||||||
|
else:
|
||||||
|
target_message = await self.client.send_message(
|
||||||
|
self._me,
|
||||||
|
"Error occurred, please try again."
|
||||||
|
)
|
||||||
|
|
||||||
await self.inline.form(
|
await self.inline.form(
|
||||||
text=full_message,
|
text=full_message[:4096],
|
||||||
message=message_or_call,
|
message=target_message,
|
||||||
reply_markup=markup,
|
reply_markup=markup
|
||||||
photo=self.fallback_banner
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await message_or_call.edit(
|
|
||||||
text=full_message,
|
|
||||||
reply_markup=markup,
|
|
||||||
photo=self.fallback_banner
|
|
||||||
)
|
)
|
||||||
|
except Exception as inner_e:
|
||||||
|
logger.exception(f"Secondary error in error handling: {inner_e}")
|
||||||
|
try:
|
||||||
|
if isinstance(message_or_call, Message):
|
||||||
|
await utils.answer(message_or_call, "Error displaying module. Please try again.")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
async def _show_global_results(self, call: InlineCall, query: str):
|
async def _show_global_results(self, call: InlineCall, query: str):
|
||||||
searcher = Search(query.lower(), self.ix)
|
searcher = Search(query.lower(), self.ix)
|
||||||
@@ -604,7 +635,7 @@ class Limoka(loader.Module):
|
|||||||
buttons.append([{"text": self.strings["change_query"], "callback": self._enter_query}])
|
buttons.append([{"text": self.strings["change_query"], "callback": self._enter_query}])
|
||||||
|
|
||||||
await call.edit(
|
await call.edit(
|
||||||
text=text,
|
text=text[:4096],
|
||||||
reply_markup=buttons
|
reply_markup=buttons
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -635,13 +666,12 @@ class Limoka(loader.Module):
|
|||||||
async def _inline_void(self, call: InlineCall):
|
async def _inline_void(self, call: InlineCall):
|
||||||
await call.answer()
|
await call.answer()
|
||||||
|
|
||||||
@loader.command(ru_doc="[запрос] — Поиск модулей (без аргументов для формы ввода)")
|
@loader.command(ru_doc="[запрос / ничего] — Поиск модулей")
|
||||||
async def limokacmd(self, message: Message):
|
async def limokacmd(self, message: Message):
|
||||||
"""[query] - Search modules (no args for input form)"""
|
"""[query / nothing] - Search modules"""
|
||||||
args = utils.get_args_raw(message)
|
args = utils.get_args_raw(message)
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
# No arguments - show input form
|
|
||||||
markup = [
|
markup = [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -668,7 +698,6 @@ class Limoka(loader.Module):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# With arguments - perform search
|
|
||||||
if len(self._history) >= 10:
|
if len(self._history) >= 10:
|
||||||
self._history = self._history[-9:]
|
self._history = self._history[-9:]
|
||||||
self._history.append(args)
|
self._history.append(args)
|
||||||
@@ -762,7 +791,7 @@ class Limoka(loader.Module):
|
|||||||
buttons.append([{"text": "🔄 " + self.strings["change_query"], "callback": lambda c: self._show_global_form(c, message)}])
|
buttons.append([{"text": "🔄 " + self.strings["change_query"], "callback": lambda c: self._show_global_form(c, message)}])
|
||||||
|
|
||||||
await call.edit(
|
await call.edit(
|
||||||
text=text,
|
text=text[:4096],
|
||||||
reply_markup=buttons
|
reply_markup=buttons
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -779,64 +808,4 @@ class Limoka(loader.Module):
|
|||||||
self.strings["history"].format(
|
self.strings["history"].format(
|
||||||
history='\n'.join(formatted_history)
|
history='\n'.join(formatted_history)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@loader.inline_handler()
|
|
||||||
async def limoka(self, query: InlineQuery):
|
|
||||||
"""[query] - Search modules inline"""
|
|
||||||
q = query.args or ""
|
|
||||||
if not q:
|
|
||||||
return {
|
|
||||||
"title": "Limoka Search",
|
|
||||||
"description": "Enter module name or keyword to search",
|
|
||||||
"thumb": "https://img.icons8.com/?size=100&id=NIWYFnJlcBfr&format=png&color=000000",
|
|
||||||
"message": "<emoji document_id=5413334818047940135>🔍</emoji> <b>Limoka Inline Search</b>\n\nEnter your query to search for Hikka modules:",
|
|
||||||
}
|
|
||||||
|
|
||||||
searcher = Search(q.lower(), self.ix)
|
|
||||||
try:
|
|
||||||
results = searcher.search_module()
|
|
||||||
except Exception:
|
|
||||||
return {
|
|
||||||
"title": "Error",
|
|
||||||
"description": "Search error occurred",
|
|
||||||
"thumb": "https://img.icons8.com/?size=100&id=rUSWMuGVdxJj&format=png&color=000000",
|
|
||||||
"message": "<emoji document_id=5210952531676504517>❌</emoji> <b>Search error</b>\n<i>Try again later</i>",
|
|
||||||
}
|
|
||||||
|
|
||||||
if not results:
|
|
||||||
return {
|
|
||||||
"title": "No results found",
|
|
||||||
"description": "No modules match your query",
|
|
||||||
"thumb": "https://img.icons8.com/?size=100&id=olDsW0G3zz22&format=png&color=000000",
|
|
||||||
"message": "<emoji document_id=5210952531676504517>❌</emoji> <b>No results found</b>\n<i>Try different keywords</i>",
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_results = []
|
|
||||||
for path in results[:10]:
|
|
||||||
module_info = self.modules.get(path)
|
|
||||||
if not module_info:
|
|
||||||
continue
|
|
||||||
banner = await self._validate_url(module_info["meta"].get("banner"))
|
|
||||||
thumb = await self._validate_url(
|
|
||||||
module_info["meta"].get("pic", "https://img.icons8.com/?size=100&id=olDsW0G3zz22&format=png&color=000000")
|
|
||||||
)
|
|
||||||
inline_results.append(
|
|
||||||
{
|
|
||||||
"title": module_info["name"],
|
|
||||||
"description": module_info["description"] or "No description available",
|
|
||||||
"thumb": thumb or "https://img.icons8.com/?size=100&id=olDsW0G3zz22&format=png&color=000000",
|
|
||||||
"photo": banner,
|
|
||||||
"message": self.strings["found"].format(
|
|
||||||
name=html.escape(module_info["name"]),
|
|
||||||
query=html.escape(q),
|
|
||||||
url=html.escape(self.config["limokaurl"]),
|
|
||||||
description=html.escape(module_info["description"] or self.strings["no_info"]),
|
|
||||||
username=html.escape(module_info["meta"].get("developer", "Unknown")),
|
|
||||||
commands="".join(self.generate_commands(module_info)),
|
|
||||||
module_path=path.replace("\\", "/"),
|
|
||||||
prefix=html.escape(self.get_prefix()),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return inline_results
|
|
||||||
Reference in New Issue
Block a user