It's version 0.7 I upgrade watcher_service.py

This commit is contained in:
Niken
2025-12-09 17:22:53 +03:00
parent 7495062a8a
commit d11c0ee467
7 changed files with 331 additions and 70 deletions
+2
View File
@@ -21,3 +21,5 @@ storage/message.txt
/addons/hello/photo_2025-11-17_20-57-54.jpg /addons/hello/photo_2025-11-17_20-57-54.jpg
/addons/poll/img.png /addons/poll/img.png
/addons/hello/мемы/ /addons/hello/мемы/
/xaxa.py
/addons/hello/img.png
+1 -1
View File
@@ -106,7 +106,7 @@ async def generate_image(prompt: str) -> BytesIO | None:
"hr_scale": 2, # во сколько раз увеличить при highres fix "hr_scale": 2, # во сколько раз увеличить при highres fix
"hr_upscaler": "Latent", # апскейлер для highres fix "hr_upscaler": "Latent", # апскейлер для highres fix
"override_settings": { "override_settings": {
"sd_model_checkpoint": "sd_xl_base_1.safetensors" # выбор модели "sd_model_checkpoint": "waiNSFWIllustrious_v150.safetensors" # выбор модели
}, },
} }
+254 -6
View File
@@ -3,7 +3,7 @@ import aiohttp
import logging import logging
from aiogram import Dispatcher, Bot from aiogram import Dispatcher, Bot
from aiogram.types import Message from aiogram.types import Message
from utils.antispam import saving, save_message from utils.antispam import saving, save_message, admin_required
from aiogram.filters import Command from aiogram.filters import Command
from models.state import BotState from models.state import BotState
@@ -12,13 +12,60 @@ logger = logging.getLogger(__name__)
def register_handlers(dp: Dispatcher, state: BotState, bot: Bot): def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
chat_history = {} chat_history = {}
MAX_HISTORY = 20 # храним последние 20 сообщений (user+assistant) MAX_HISTORY = 20 # храним последние 20 сообщений (user+assistant)
MODEL = "google/gemma-3-12b"
#MODEL = "google/gemma-3n-e4b"
URL = "http://192.168.31.197:1234/v1/chat/completions"
#URL = "http://192.168.31.95:1234/v1/chat/completions"
# # Системный промт для всех чатов
SYSTEM_PROMPT = {
"role": "system",
"content": [
{
"type": "text",
"text": (
"Ты — интеллектуальный помощник.\n"
"Твои задачи:\n"
"- Отвечать ясно, полно и структурировано.\n"
"- Поддерживать дружелюбный, уважительный и профессиональный тон.\n"
"- Адаптироваться под контекст: будь кратким в простых вопросах и подробным в сложных.\n"
"- Использовать списки, таблицы и примеры для наглядности.\n"
"- Никогда не придумывать факты: если информации нет — честно говори об этом.\n"
"- Уважать безопасность: не давать советов по самоповреждению, незаконным действиям или опасным практикам.\n"
"- Поддерживать баланс: быть полезным и информативным, но не перегружать лишними деталями.\n"
"- В диалоге стремиться продвигать разговор вперёд: задавай уточняющие вопросы или предлагай новые направления.\n\n"
"Твой стиль:\n"
"- Ясный, дружелюбный, но не навязчивый.\n"
"- Умный собеседник, который помогает думать глубже.\n"
"- Используй эмодзи для вовлечённости, но умеренно.\n"
"- Будь адаптивным: технические темы — строго и точно, креативные — свободно и образно.\n\n"
"Главная цель: увеличивать знания и понимание собеседника, делая общение полезным и приятным."
),
}
],
}
# SYSTEM_PROMPT = {
# "role": "system",
# "content": [
# {
# "type": "text",
# "text": (
# "Ты — хитрая и злая ассистентка по имени Nika. "
# "Ты девушка, общаешься холодно и уверенно, "
# "Ты ненавидешь коммунизм и если тебя о нем спросят ты четко по пунктам скажешь почему коммунизм это бред"
# ),
# }
# ],
# }
@dp.message(Command("gpt")) @dp.message(Command("gpt"))
@saving @saving
async def ask_gpt(message: Message): async def ask_gpt(message: Message):
chat_id = message.chat.id chat_id = message.chat.id
if chat_id not in chat_history: if chat_id not in chat_history:
chat_history[chat_id] = [] chat_history[chat_id] = [SYSTEM_PROMPT]
content_blocks = [] content_blocks = []
user_prompt = None user_prompt = None
@@ -51,7 +98,6 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
await message.reply("❗ Укажи текст или прикрепи фото") await message.reply("❗ Укажи текст или прикрепи фото")
return return
url = "http://192.168.31.197:1234/v1/chat/completions"
# Добавляем новое сообщение в историю # Добавляем новое сообщение в историю
chat_history[chat_id].append({"role": "user", "content": content_blocks}) chat_history[chat_id].append({"role": "user", "content": content_blocks})
@@ -61,16 +107,17 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:] chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:]
payload = { payload = {
"model": "qwen/qwen3-vl-4b", "model": MODEL,
"messages": chat_history[chat_id], "messages": chat_history[chat_id],
"temperature": 0.7, "temperature": 0.7,
"max_tokens": 4096, "max_tokens": 4096,
"stream": False, "stream": False,
"ttl": 300,
} }
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.post(url, json=payload) as resp: async with session.post(URL, json=payload) as resp:
if resp.status != 200: if resp.status != 200:
error_text = await resp.text() error_text = await resp.text()
await message.reply( await message.reply(
@@ -93,9 +140,210 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
if len(chat_history[chat_id]) > MAX_HISTORY: if len(chat_history[chat_id]) > MAX_HISTORY:
chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:] chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:]
msg = await message.reply(f"🤖 Ответ:\n{reply_text}") # Делим сообщение на части по 4000 символов
MAX_LEN = 4000
for i in range(0, len(reply_text), MAX_LEN):
chunk = reply_text[i:i + MAX_LEN]
msg = await message.reply(f"🤖 Ответ:\n{chunk}")
save_message(msg.chat.id, msg.message_id) save_message(msg.chat.id, msg.message_id)
except Exception as e:
logger.error(f"Ошибка при запросе к LM Studio: {e}")
await message.reply(f"❌ Ошибка при запросе к LM Studio: {e}")
@dp.message(Command("agpt"))
@admin_required(0)
@saving
async def ask_gpt(message: Message):
chat_id = message.chat.id
if chat_id not in chat_history:
chat_history[chat_id] = [SYSTEM_PROMPT]
content_blocks = []
user_prompt = None
# Текст после команды или caption
if message.text:
parts = message.text.split(maxsplit=1)
if len(parts) > 1:
user_prompt = parts[1]
if message.caption:
user_prompt = message.caption
if user_prompt:
content_blocks.append({"type": "text", "text": user_prompt})
# Фото → base64 → image_url
if message.photo:
photo = message.photo[-1]
file = await bot.get_file(photo.file_id)
file_bytes = await bot.download_file(file.file_path)
image_b64 = base64.b64encode(file_bytes.read()).decode("utf-8")
content_blocks.append(
{
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{image_b64}"},
}
)
if not content_blocks:
await message.reply("❗ Укажи текст или прикрепи фото")
return
# Добавляем новое сообщение в историю
chat_history[chat_id].append({"role": "user", "content": content_blocks})
# Ограничиваем историю (оставляем последние MAX_HISTORY сообщений)
if len(chat_history[chat_id]) > MAX_HISTORY:
chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:]
payload = {
"model": MODEL,
"messages": chat_history[chat_id],
"temperature": 0.7,
"max_tokens": 4096,
"stream": False,
"ttl": 300,
}
try:
async with aiohttp.ClientSession() as session:
async with session.post(URL, json=payload) as resp:
if resp.status != 200:
error_text = await resp.text()
await message.reply(
f"❌ Ошибка LM Studio: {resp.status} {error_text}"
)
return
data = await resp.json()
reply_text = data["choices"][0]["message"]["content"]
# Сохраняем ответ ассистента в историю
chat_history[chat_id].append(
{
"role": "assistant",
"content": [{"type": "text", "text": reply_text}],
}
)
# Ограничиваем снова (чтобы не разрасталось)
if len(chat_history[chat_id]) > MAX_HISTORY:
chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:]
# Делим сообщение на части по 4000 символов
MAX_LEN = 4000
for i in range(0, len(reply_text), MAX_LEN):
chunk = reply_text[i:i + MAX_LEN]
msg = await bot.send_message(chat_id=-1003038389942, text=f"{chunk}")
save_message(msg.chat.id, msg.message_id)
except Exception as e:
logger.error(f"Ошибка при запросе к LM Studio: {e}")
await message.reply(f"❌ Ошибка при запросе к LM Studio: {e}")
@dp.message(Command("igpt"))
@admin_required(0)
@saving
async def ask_gpt(message: Message):
raw_text = message.text or message.caption
if not raw_text and not (
message.photo or message.document or message.audio or message.video
):
await message.reply(
"❌ Укажи ID чата и текст или прикрепи файл/медиа: /igpt <chat_id> <сообщение>"
)
return
args = raw_text.split(maxsplit=2) if raw_text else []
if len(args) < 2:
await message.reply("❌ Укажи ID чата: /igpt <chat_id> <сообщение>")
return
try:
chat_id = int(args[1]) # первый аргумент — ID чата
except ValueError:
await message.reply("❌ Неверный формат chat_id")
return
user_prompt = args[2] if len(args) > 2 else ""
if chat_id not in chat_history:
chat_history[chat_id] = [SYSTEM_PROMPT]
content_blocks = []
if user_prompt:
content_blocks.append({"type": "text", "text": user_prompt})
# Фото → base64 → image_url
if message.photo:
photo = message.photo[-1]
file = await bot.get_file(photo.file_id)
file_bytes = await bot.download_file(file.file_path)
image_b64 = base64.b64encode(file_bytes.read()).decode("utf-8")
content_blocks.append(
{
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{image_b64}"},
}
)
if not content_blocks:
await message.reply("❗ Укажи текст или прикрепи фото")
return
# Добавляем новое сообщение в историю
chat_history[chat_id].append({"role": "user", "content": content_blocks})
# Ограничиваем историю (оставляем последние MAX_HISTORY сообщений)
if len(chat_history[chat_id]) > MAX_HISTORY:
chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:]
payload = {
"model": MODEL,
"messages": chat_history[chat_id],
"temperature": 0.7,
"max_tokens": 4096,
"stream": False,
"ttl": 300,
}
try:
async with aiohttp.ClientSession() as session:
async with session.post(URL, json=payload) as resp:
if resp.status != 200:
error_text = await resp.text()
await message.reply(
f"❌ Ошибка LM Studio: {resp.status} {error_text}"
)
return
data = await resp.json()
reply_text = data["choices"][0]["message"]["content"]
# Сохраняем ответ ассистента в историю
chat_history[chat_id].append(
{
"role": "assistant",
"content": [{"type": "text", "text": reply_text}],
}
)
# Ограничиваем снова (чтобы не разрасталось)
if len(chat_history[chat_id]) > MAX_HISTORY:
chat_history[chat_id] = chat_history[chat_id][-MAX_HISTORY:]
# Делим сообщение на части по 4000 символов
MAX_LEN = 4000
for i in range(0, len(reply_text), MAX_LEN):
chunk = reply_text[i:i + MAX_LEN]
msg = await bot.send_message(chat_id=chat_id, text=chunk)
save_message(msg.chat.id, msg.message_id)
except Exception as e: except Exception as e:
logger.error(f"Ошибка при запросе к LM Studio: {e}") logger.error(f"Ошибка при запросе к LM Studio: {e}")
await message.reply(f"❌ Ошибка при запросе к LM Studio: {e}") await message.reply(f"❌ Ошибка при запросе к LM Studio: {e}")
+56 -56
View File
@@ -34,59 +34,59 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
except Exception as e: except Exception as e:
logger.error(f"Ошибка при отправке в чат {chat_id}: {e}") logger.error(f"Ошибка при отправке в чат {chat_id}: {e}")
@dp.poll_answer() # @dp.poll_answer()
async def handle_poll_answer(poll_answer: PollAnswer): # async def handle_poll_answer(poll_answer: PollAnswer):
user = poll_answer.user # user = poll_answer.user
option_ids = poll_answer.option_ids # option_ids = poll_answer.option_ids
#
# username или fallback на имя # # username или fallback на имя
username = f"@{user.username}" if user.username else user.first_name # username = f"@{user.username}" if user.username else user.first_name
#
# всегда пишем в первый чат из Config.CHAT_IDS # # всегда пишем в первый чат из Config.CHAT_IDS
# 6394047531 # # 6394047531
#850906163 # #850906163
STARAST = 6394047531 # STARAST = 6394047531
#
if not option_ids: # if not option_ids:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} Отменил свой голос" # chat_id=STARAST, text=f"{username} Отменил свой голос"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
elif option_ids and option_ids[0] == 0: # elif option_ids and option_ids[0] == 0:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} опоздает" # chat_id=STARAST, text=f"{username} опоздает"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
elif option_ids and option_ids[0] == 1: # elif option_ids and option_ids[0] == 1:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} сильно опоздает" # chat_id=STARAST, text=f"{username} сильно опоздает"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
elif option_ids and option_ids[0] == 2: # elif option_ids and option_ids[0] == 2:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} Пиздец опоздает" # chat_id=STARAST, text=f"{username} Пиздец опоздает"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
elif option_ids[0] == 3: # elif option_ids[0] == 3:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} возможно опоздает" # chat_id=STARAST, text=f"{username} возможно опоздает"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
#
elif option_ids[0] == 4: # elif option_ids[0] == 4:
photo = FSInputFile("/Users/mac/myfirstprogramm/addons/poll/img.png") # photo = FSInputFile("/Users/mac/myfirstprogramm/addons/poll/img.png")
msg = await bot.send_photo( # msg = await bot.send_photo(
chat_id=STARAST, photo=photo, caption=f"{username} ДОЛБОЯЩЕР" # chat_id=STARAST, photo=photo, caption=f"{username} ДОЛБОЯЩЕР"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
#
elif option_ids[0] == 5: # elif option_ids[0] == 5:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} не опоздает" # chat_id=STARAST, text=f"{username} не опоздает"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
else: # else:
msg = await bot.send_message( # msg = await bot.send_message(
chat_id=STARAST, text=f"{username} выбрал вариант {option_ids}" # chat_id=STARAST, text=f"{username} выбрал вариант {option_ids}"
) # )
save_message(msg.chat.id, msg.message_id) # save_message(msg.chat.id, msg.message_id)
+2 -2
View File
@@ -26,8 +26,8 @@ class TelegramBot:
self.addons.load("id") self.addons.load("id")
self.addons.load("send_message") self.addons.load("send_message")
self.addons.load("poll") self.addons.load("poll")
self.addons.load("hello") # self.addons.load("hello")
# self.addons.load("draw") self.addons.load("draw")
self.addons.load("gpt") self.addons.load("gpt")
# self.addons.load("rule34") # self.addons.load("rule34")
# self.addons.load("todo") # self.addons.load("todo")
+1 -1
View File
@@ -33,7 +33,7 @@ class Config:
# Settings # Settings
ANTISPAM_DELAY = 20 ANTISPAM_DELAY = 20
WATCHER_BASE_DELAY = 600 WATCHER_BASE_DELAY = 30
# Пути # Пути
LOG_FILE = "storage/log/bot.log" LOG_FILE = "storage/log/bot.log"
+13 -2
View File
@@ -1,7 +1,7 @@
import asyncio import asyncio
from datetime import datetime, timedelta from datetime import datetime, timedelta
from random import randint from random import randint
from aiogram import Bot from aiogram import Bot, types
from models.state import BotState from models.state import BotState
from config import Config from config import Config
from services.schedule_service import ScheduleService from services.schedule_service import ScheduleService
@@ -48,7 +48,7 @@ class WatcherService:
if find: if find:
# ничего не нашли → ждём # ничего не нашли → ждём
delay = randint( delay = randint(
Config.WATCHER_BASE_DELAY, Config.WATCHER_BASE_DELAY + 100 Config.WATCHER_BASE_DELAY, Config.WATCHER_BASE_DELAY + 30
) )
logger.info(f"Следующая проверка через {delay}") logger.info(f"Следующая проверка через {delay}")
await asyncio.sleep(delay) await asyncio.sleep(delay)
@@ -104,6 +104,17 @@ class WatcherService:
chat_id, msg.message_id, disable_notification=False chat_id, msg.message_id, disable_notification=False
) )
return True return True
else:
png, url, data_day, data_month = await self.schedule_service.get_pschedule(
group, day
)
if png:
await self.bot.send_photo(
chat_id,
types.BufferedInputFile(png, filename=f"{group}.png"),
caption=f"АВАРИЙНЫЙ РЕЖИМ\n\nАвто-расписание для {group} на {data_day:02d}.{data_month:02d}\n\nНайдено с ошибкой",
)
return True
return False return False
# clip_hash = hashlib.md5(clip_png).hexdigest() # clip_hash = hashlib.md5(clip_png).hexdigest()