import re
import os
import time
import shelve
import requests
import html as _html
from datetime import datetime
from aiogram.methods import AnswerGuestQuery, SendPoll
from aiogram.types import InlineQueryResultArticle, InputTextMessageContent, InputRichMessageContent, InputRichMessage, Message
from aiogram.enums import ChatType
from vars import *
from config import *
def is_blocked(user_id):
current_time = time.time()
if user_id and user_id in last_command_time:
time_diff = current_time - last_command_time[user_id][0]
if user_id in last_error_time:
time_error_diff = current_time - last_error_time[user_id]
else:
last_error_time[user_id] = current_time
time_error_diff = 1984
if time_diff < 3:
alo = "π« *ΡΠ°ΠΉΠ» Π½Π΅ Π²ΠΎΡΡΠ».* Ρ
Π²Π°ΡΠΈΡ ΡΠ°ΠΊ Π±ΡΡΡΡΠΎ ΡΠ»Π°ΡΡ ΡΠ²ΠΎΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ.\n" \
f"ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ {round(3 - time_diff, 3)} ΡΠ΅ΠΊΡΠ½Π΄, Π±ΡΠ°Ρπ‘π‘"
elif last_command_time[user_id][1] and time_diff < 5:
alo = "π« *ΡΠ°ΠΉΠ» Π½Π΅ Π²ΠΎΡΡΠ».* Ρ Π΅ΡΡ Π½Π΅ ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π» ΠΏΡΠΎΡΠ»ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅.\n" \
f"ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ {round(10 - time_diff, 3)} ΡΠ΅ΠΊΡΠ½Π΄, ΡΡΠΎΠ±Ρ Ρ Π·Π°ΠΊΡΡΠ» Π³Π»Π°Π·Π° " \
"Π½Π° ΡΡΠΎ da."
elif len(last_command_time[user_id][2]) > 1 and time_diff > 5:
last_command_time[user_id] = [current_time, False, []]
return "", False
elif len(last_command_time[user_id][2]) > 1:
alo = "π« *ΡΠ°ΠΉΠ» Π½Π΅ Π²ΠΎΡΡΠ».* Ρ
Π²Π°ΡΠΈΡ ΡΠ°ΠΊ Π±ΡΡΡΡΠΎ ΡΠ»Π°ΡΡ ΡΠ²ΠΎΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ."
else:
return "", False
if time_error_diff < 2:
return "", True
else:
last_error_time[user_id] = current_time
return alo, True
return "", False
def is_replied_bot(message, is_channel, user_text, config=None):
if message.chat.type in [ChatType.GROUP, ChatType.SUPERGROUP, ChatType.CHANNEL]:
if not is_channel:
is_reply_to_bot = (
message.reply_to_message
and message.reply_to_message.from_user
and message.reply_to_message.from_user.is_bot
and message.reply_to_message.from_user.username == BOT_USERNAME
)
if config:
if config.get("call") == "da":
calls = config.get("calling") or BOT_CALLS
mentions_bot = any(
user_text.lower().split(" ", 1)[0] == call.lower() for call in calls
)
for call in calls:
if call.startswith("@"):
if call.lower() in user_text.lower():
mentions_bot = True
else:
mentions_bot = False
else:
mentions_bot = any(
user_text.lower().startswith(call.lower()) for call in BOT_CALLS
)
for call in BOT_CALLS:
if call.startswith("@"):
if call.lower() in user_text.lower():
mentions_bot = True
if not (is_reply_to_bot or mentions_bot):
return False
return True
async def g_answer(
message,
text,
title="da",
id="1",
parse_mode="Markdown",
reply_markup=None,
user_id=None
):
input_message_content = InputTextMessageContent(
message_text=text,
parse_mode=parse_mode
)
if user_id:
config = get_user_config(user_id)
if config["markdown"] == "new":
input_message_content=InputRichMessageContent(
rich_message=InputRichMessage(markdown=text)
)
return await message.answer_guest_query(
result=InlineQueryResultArticle(
id=id,
reply_markup=reply_markup,
title=title,
input_message_content=input_message_content
)
)
async def answer_poll(
data,
message,
question,
options,
is_anonymous=True,
poll_type="regular",
allows_multiple_answers=False,
correct_option_id=None,
user_id=None
):
return await data["bot"](
SendPoll(
chat_id=user_id,
question=question,
options=options,
is_anonymous=is_anonymous,
type=poll_type,
allows_multiple_answers=allows_multiple_answers,
correct_option_id=correct_option_id,
)
)
def send_to_vosk(audio):
files = {
"audio": (
"voice.ogg",
audio,
"audio/ogg"
)
}
r = requests.post(
VOSK_API,
files=files,
timeout=15
)
return r.json()
async def mans(message, text):
if message.guest_query_id:
return await message.answer_guest_query(
result=InlineQueryResultArticle(
id=1,
reply_markup=None,
title="da",
input_message_content=InputTextMessageContent(
message_text=text,
parse_mode="Markdown"
)
)
)
else:
return await message.reply(text)
def graph_emoji(status):
match status:
case "done":
return "β
"
case "error":
return "π«"
case "make":
return "π"
case "wait":
return "β³"
case _:
return "π₯Ί"
def make_graph(message, process):
text = ""
replied = message.reply_to_message or None
user_id = message.from_user.id
config = get_user_config(user_id)
im_model = IMAGE_MODEL.split("*", 1)
model = config["model"].split("*", 1)
photo_a = process.get("photo_a", None)
photo = process.get("photo", None)
stt = process.get("stt", None)
t = process.get("text", None)
if photo_a:
text += f"{graph_emoji(photo_a)} Π°Π½Π°Π»ΠΈΠ· ΡΠΎΡΠΎ (Π² ΠΎΡΠ²Π΅ΡΠ΅)\n"
if photo:
text += f"{graph_emoji(photo)} Π°Π½Π°Π»ΠΈΠ· ΡΠΎΡΠΎ\n"
if stt:
text += f"{graph_emoji(stt)} stt (Π³ΠΎΠ»ΠΎΡ -> ΡΠ΅ΠΊΡΡ)\n"
text += f"{graph_emoji(t)} Π·Π°ΠΏΡΠΎΡ `{model[1]}` (`{model[0]}`)\n"
if replied and replied.document:
text += f"β³ {replied.document.file_size} ΡΠ°ΠΉΠ» (Π² ΠΎΡΠ²Π΅ΡΠ΅)\n"
if message.document:
text += f"β³ {message.document.file_size} ΡΠ°ΠΉΠ»\n"
if replied and replied.photo:
text += "β³ ΡΠΎΡΠΎ (Π² ΠΎΡΠ²Π΅ΡΠ΅)\n"
if message.photo:
text += "β³ ΡΠΎΡΠΎ\n"
if replied and replied.location:
text += "β³ Π³Π΅ΠΎΠ»ΠΎΠΊΠ°ΡΠΈΡ (Π² ΠΎΡΠ²Π΅ΡΠ΅)\n"
if message.location:
text += "β³ Π³Π΅ΠΎΠ»ΠΎΠΊΠ°ΡΠΈΡ\n"
if replied and replied.poll:
text += "β³ ΠΎΠΏΡΠΎΡ (Π² ΠΎΡΠ²Π΅ΡΠ΅)\n"
if message.poll:
text += "β³ ΠΎΠΏΡΠΎΡ\n"
if replied and replied.voice:
text += "β³ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ (Π² ΠΎΡΠ²Π΅ΡΠ΅)\n"
if message.voice:
text += "β³ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅\n"
if replied and replied.text:
text += f"β³ {len(replied.text)} ΡΠ΅ΠΊΡΡ Π² ΠΎΡΠ²Π΅ΡΠ΅\n"
return text
def clean_tail_repeats(text: str, max_repeat: int = 10):
if not text:
return text, 0
original_length = len(text)
cleaned = text
pattern = rf"(.)\1{{{max_repeat},}}$"
def limit_repeats(match):
char = match.group(1)
return char * max_repeat
cleaned = re.sub(pattern, limit_repeats, cleaned)
pattern_space = rf"((\S)\s+)\2{{{max_repeat},}}$"
cleaned = re.sub(
pattern_space,
lambda m: (m.group(2) + " ") * min(max_repeat, len(m.group(1))),
cleaned,
)
words = cleaned.split()
if len(words) >= 2:
for i in range(1, min(len(words), 10)):
if all(words[-j] == words[-j - 1] for j in range(i)):
unique_words = words[: -(i + 1)]
cleaned = " ".join(unique_words + [words[-1]])
break
removed_count = original_length - len(cleaned)
cleaned = re.sub(r" +", " ", cleaned)
cleaned = cleaned.strip()
return cleaned, removed_count
def get_key(provider, model_full):
prov = PROVIDERS.get(provider, {})
key = prov.get("key", "")
if isinstance(key, list):
parts = model_full.split("*")
if len(parts) >= 3:
try:
idx = int(parts[2]) - 1
except ValueError:
return key[0]
if 0 <= idx < len(key):
return key[idx]
return key[0]
return key
_expanded_auto_models = None
def expand_auto_models():
global _expanded_auto_models
if _expanded_auto_models is not None:
return _expanded_auto_models
result = []
for entry in AUTO_MODELS:
parts = entry.split("*", 2)
if len(parts) < 2:
continue
provider = parts[0]
model = parts[1]
suffix = parts[2] if len(parts) >= 3 else None
prov_key = PROVIDERS.get(provider, {}).get("key", "")
if isinstance(prov_key, list) and not suffix:
for i in range(len(prov_key)):
result.append(f"{provider}*{model}*{i + 1}")
else:
result.append(entry)
_expanded_auto_models = result
return result
def parse_response(text: str):
if "connection error." in text:
return {
"type": "connection",
"message": "ΠΎΡΠΈΠ±ΠΊΠ° ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΠΊ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΡ. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° Π² Π½Π°ΡΡΡΠΎΠΉΠΊΠ°Ρ
ΡΠ·Π±Π΅ΠΊΠ³ΠΏΡ.",
}
elif "model quota exceeded" in text:
return {
"type": "quota",
"message": "Π»ΠΈΠΌΠΈΡ ΡΠΎΠΊΠ΅Π½ΠΎΠ² Π·Π°ΠΊΠΎΠ½ΡΠΈΠ»ΡΡ. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
elif "tier capacity exceeded." in text:
return {"type": "tier", "message": "ΠΏΠΎΠΏΡΠΎΠ±ΡΠΉ Π΅ΡΡ ΡΠ°Π·!"}
elif "internal server" in text:
return {
"type": "int",
"message": "ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»Π° ΠΎΡΠΈΠ±ΠΊΠ° Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ°. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° Π² Π½Π°ΡΡΡΠΎΠΉΠΊΠ°Ρ
ΡΠ·Π±Π΅ΠΊΠ³ΠΏΡ.",
}
elif "(incomplete chunked read)" in text:
return {
"type": "incomplete",
"message": "ΡΠ΅ΡΠ²Π΅Ρ ΠΏΠ΅ΡΡΡ
ΠΈ ΠΎΠ±ΠΎΡΠ²Π°Π» ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° Π² Π½Π°ΡΡΡΠΎΠΉΠΊΠ°Ρ
ΡΠ·Π±Π΅ΠΊΠ³ΠΏΡ.",
}
elif "provider error" in text:
return {
"type": "provider",
"message": "Π²ΡΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠ° Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° ΠΌΠΎΠ΄Π΅Π»ΠΈ. ΡΠΌΠ΅Π½ΠΈ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° ΠΈΠ»ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
elif "rate limit" in text:
return {
"type": "quota",
"message": "Π»ΠΈΠΌΠΈΡ ΡΠΎΠΊΠ΅Π½ΠΎΠ² Π·Π°ΠΊΠΎΠ½ΡΠΈΠ»ΡΡ Ρ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° Π²ΡΠ°Ρ. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
elif "response payload is not completed" in text or "not enough data to satisfy" in text or "server disconnected" in text or "connection reset" in text or "serverdisconnectederror" in text:
return {
"type": "incomplete",
"message": "ΡΠ΅ΡΠ²Π΅Ρ ΠΏΠ΅ΡΡΡ
ΠΈ ΠΎΠ±ΠΎΡΠ²Π°Π» ΠΎΡΠ²Π΅Ρ Π½Π° ΡΠ΅ΡΠ΅Π΄ΠΈΠ½Π΅. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
elif "timeout" in text or "timed out" in text:
return {
"type": "timeout",
"message": "ΡΠ΅ΡΠ²Π΅Ρ Π΄ΡΠΌΠ°Π» ΡΠ»ΠΈΡΠΊΠΎΠΌ Π΄ΠΎΠ»Π³ΠΎ ΠΈ ΡΠΌΠ΅Ρ. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
elif "not found" in text or " 404" in text or "404 " in text or "no such model" in text or "does not exist" in text:
return {
"type": "notfound",
"message": "ΠΌΠΎΠ΄Π΅Π»Ρ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Π° Ρ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ°. ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ Π² Π½Π°ΡΡΡΠΎΠΉΠΊΠ°Ρ
.",
}
elif "forbidden" in text or "unauthorized" in text or " 403" in text or "403 " in text or " 401" in text or "401 " in text or "invalid api key" in text or "incorrect api key" in text:
return {
"type": "key",
"message": "ΠΊΠ»ΡΡ ΠΈΠ»ΠΈ Π΄ΠΎΡΡΡΠΏ ΠΊ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΡ ΡΠ΄ΠΎΡ
. ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ ΠΈΠ»ΠΈ Π½Π°ΠΏΠΈΡΠΈ Ρ
ΠΎΡΡΠ΅ΡΡ.",
}
elif " 429" in text or "429 " in text or "exhausted" in text or "quota" in text:
return {
"type": "quota",
"message": "Π»ΠΈΠΌΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² Ρ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ° Π·Π°ΠΊΠΎΠ½ΡΠΈΠ»ΡΡ. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
elif " 500" in text or "500 " in text or " 502" in text or "502 " in text or " 503" in text or "503 " in text or "bad gateway" in text:
return {
"type": "int",
"message": "ΠΎΡΠΈΠ±ΠΊΠ° Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΠ°. ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈ ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»Ρ.",
}
else:
return {
"type": "unknown",
"message": f"ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»Π° ΠΊΠ°ΠΊΠ°Ρ-ΡΠΎ ΠΎΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ... {text}",
}
def galockinator(text):
for _ in range(random.randint(1, 3)):
if random.random() < 0.3:
text += "βοΈ"
else:
text += "β
"
return text
def remove_think_tags(text):
result = re.sub(r"