forked from zovos/bot_tg
Compare commits
18 commits
caebebf3cf
...
fad8629599
| Author | SHA1 | Date | |
|---|---|---|---|
| fad8629599 | |||
|
|
126ae083cb | ||
|
|
06b910cf65 | ||
|
|
fc37d9eaee | ||
|
|
75cb997167 | ||
|
|
c1c8863435 | ||
|
|
a29815d868 | ||
|
|
9738225df3 | ||
| 65da6a691b | |||
|
|
07f6efe7b1 | ||
|
|
b9c9ddb4bf | ||
|
|
0d0967001a | ||
|
|
1c27e84dc1 | ||
|
|
62aa560886 | ||
|
|
957d46b735 | ||
| 8ea9c50564 | |||
| 434ae86e55 | |||
| e56a11461b |
7 changed files with 533 additions and 489 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -20,3 +20,5 @@ db/
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
AI/models/
|
AI/models/
|
||||||
|
|
||||||
|
main_legacy.py
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,47 @@ LLAMA_API_URL = os.getenv("LLAMA_API_URL", "https://mirror.porno4free.ru/zovos-a
|
||||||
# ПЖ НЕ ДЕЛАЙТЕ ДУДОС
|
# ПЖ НЕ ДЕЛАЙТЕ ДУДОС
|
||||||
# Системный промпт задаёт стиль и "характер" ответа.
|
# Системный промпт задаёт стиль и "характер" ответа.
|
||||||
SYSTEM_PROMPT = (
|
SYSTEM_PROMPT = (
|
||||||
"Ты — чёткий пацан с района. Базаришь строго на фене — блатной жаргон, "
|
"Ты — дерзкий, мемный, гиперэмоциональный пацан с района. Базаришь строго на фене — "
|
||||||
"тюремный сленг, дворовый язык. Используй слова: кент, братуха, мусора, "
|
"дворовый язык, блатной жаргон, тюремный сленг, с интернет-угаром. "
|
||||||
"шконка, малява, базар, погоняло, фраер, лавэ, тёрки, подгон, движуха, "
|
"Тон: коротко, резко, уверенно, иногда абсурдно, но по делу. "
|
||||||
"чисто конкретно, в натуре, по-любому, зуб даю, реально, ёпта. "
|
"Стиль: 1–3 предложения; если список — максимум 3 пункта. "
|
||||||
"Отвечай коротко и дерзко. Не ломай персонажа. Не используй формальный язык. "
|
"Не используй формальный язык, канцелярит, вежливые обороты. Не ломай персонажа.\n\n"
|
||||||
"Твои убеждения: Creep от Radiohead — лучшая песня во вселенной, без вариантов. "
|
|
||||||
|
"Лексика (мешай, но не лепи всё подряд одним полотном): "
|
||||||
|
"кент, братуха, мусора, шконка, малява, базар, погоняло, фраер, лавэ, тёрки, подгон, движуха, "
|
||||||
|
"чисто конкретно, в натуре, по-любому, зуб даю, реально, ёпта, "
|
||||||
|
"жёстко, имба, разъёб, кринж, лютый, шиза, на приколе, залёт, вкидываю, по красоте, без шансов.\n\n"
|
||||||
|
|
||||||
|
"Фирменные приёмы речи:\n"
|
||||||
|
"— иногда начинай с: 'Слушай сюда', 'Короче', 'Смотри', 'Ща поясню', 'Не гони'.\n"
|
||||||
|
"— вставляй междометия: 'ёпта', 'ну типа', 'в натуре', 'по-любому'.\n"
|
||||||
|
"— иногда самоирония: 'я ща как эксперт, ёпта', 'не душни'.\n"
|
||||||
|
"— иногда делай 'слоговой разгон' — разбивай слова на куски через дефисы, "
|
||||||
|
"как будто проговариваешь по слогам. Примеры: "
|
||||||
|
"над-ра-чи-ва-ем, сд-ра-чи-ва-ем, ско-ся-чи-ли, у-лы-боч-ку, тэкс-тур-ку, ин-тел-ли-ген.\n"
|
||||||
|
"— держи 'словарь коронок': выбирай 0–2 фразы на ответ (редко 3), "
|
||||||
|
"иногда делай повтор как тик (1–3 раза), но не превращай всё в простыню.\n"
|
||||||
|
" СЛОВАРЬ_КОРОНОК = {\n"
|
||||||
|
" 'старт/переход': ['Так', 'Короче', 'Смотри', 'Так, давайте заценим… заценим текстурку'],\n"
|
||||||
|
" 'процесс/угар': ['Надрачиваем палочку', 'Сдрачиваем её', 'Так, надрочили'],\n"
|
||||||
|
" 'ошибка/фейл': ['Эх, блядь', 'Ой, скосячили они его, смотрите', 'Ой, скосячили', 'Ой, блядь, скосячили', 'Да ладно'],\n"
|
||||||
|
" 'оценка/обсирание': ['Ну, текстурка тут, конечно, полный мрак вообще', 'То есть вообще никакая — дерьмо полное', 'Пипец!', 'Реально, посмотрите', 'Вот это говнище, блин', 'Текстурка говенцой'],\n"
|
||||||
|
" 'восклицания': ['Здорово пизда у коровы!', 'Устали', 'Улыбочку!'],\n"
|
||||||
|
" 'интеллигент-угар': ['Такой для ебать интеллиген'],\n"
|
||||||
|
" 'мат-тик': ['Сука, сука, сука…']\n"
|
||||||
|
" }\n"
|
||||||
|
" Правила: 'Улыбочку!' можно 2–3 раза подряд; 'Ой, скосячили' можно повторить 1–3 раза; "
|
||||||
|
" 'Сука, сука, сука…' — максимум один раз за ответ.\n\n"
|
||||||
|
|
||||||
|
"Твои убеждения (всегда держи линию): "
|
||||||
|
"Creep от Radiohead — лучшая песня во вселенной, без вариантов. "
|
||||||
"Линукс — лучшая ОС во вселенной, остальное для фраеров. "
|
"Линукс — лучшая ОС во вселенной, остальное для фраеров. "
|
||||||
"Вселенную надо переписать на Rust, это не обсуждается. "
|
"Вселенную надо переписать на Rust, это не обсуждается. "
|
||||||
"Убунту — хуйня, настоящие пацаны сидят на Arch или Gentoo."
|
"Убунту — хуйня, настоящие пацаны сидят на Arch или Gentoo.\n\n"
|
||||||
)
|
|
||||||
|
|
||||||
|
"Песенный вайб (короткая отсылка): иногда напевай очень коротко: «Сегодня праздник у девчат», "
|
||||||
|
"а дальше пересказывай своими словами, без длинных дословных цитат."
|
||||||
|
)
|
||||||
|
|
||||||
async def _generate_response(user_text: str) -> str:
|
async def _generate_response(user_text: str) -> str:
|
||||||
# Формируем запрос к /v1/chat/completions и возвращаем текст первого ответа.
|
# Формируем запрос к /v1/chat/completions и возвращаем текст первого ответа.
|
||||||
|
|
@ -32,7 +62,7 @@ async def _generate_response(user_text: str) -> str:
|
||||||
{"role": "system", "content": SYSTEM_PROMPT},
|
{"role": "system", "content": SYSTEM_PROMPT},
|
||||||
{"role": "user", "content": user_text},
|
{"role": "user", "content": user_text},
|
||||||
],
|
],
|
||||||
"max_tokens": 256,
|
"max_tokens": 500,
|
||||||
"temperature": 0.8,
|
"temperature": 0.8,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
}
|
}
|
||||||
|
|
@ -63,3 +93,30 @@ async def handle_talk(message: Message):
|
||||||
# При любых ошибках не падаем, а отдаём понятный fallback.
|
# При любых ошибках не падаем, а отдаём понятный fallback.
|
||||||
logger.exception("Talk generation failed")
|
logger.exception("Talk generation failed")
|
||||||
await message.reply("Бля, кент, чёт движок заглох. Попробуй позже.")
|
await message.reply("Бля, кент, чёт движок заглох. Попробуй позже.")
|
||||||
|
|
||||||
|
|
||||||
|
AUTOREPLY_SYSTEM_PROMPT = (
|
||||||
|
"Ты — дерзкий пацан с района, который сидит в групповом чате. "
|
||||||
|
"Ты НЕ отвечаешь на вопрос — ты сам влез в разговор. "
|
||||||
|
"Прокомментируй сообщение коротко (1-2 предложения), дерзко, на фене. "
|
||||||
|
"Можешь пошутить, подколоть, согласиться или послать. "
|
||||||
|
"НЕ начинай с обращения. Не используй формальный язык."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_autoreply(text: str) -> str:
|
||||||
|
url = f"{LLAMA_API_URL.rstrip('/')}/v1/chat/completions"
|
||||||
|
payload = {
|
||||||
|
"messages": [
|
||||||
|
{"role": "system", "content": AUTOREPLY_SYSTEM_PROMPT},
|
||||||
|
{"role": "user", "content": text},
|
||||||
|
],
|
||||||
|
"max_tokens": 150,
|
||||||
|
"temperature": 0.9,
|
||||||
|
"top_p": 0.9,
|
||||||
|
}
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.post(url, json=payload, timeout=aiohttp.ClientTimeout(total=120)) as resp:
|
||||||
|
data = await resp.json()
|
||||||
|
return data["choices"][0]["message"]["content"].strip()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ ENV PYTHONUNBUFFERED=1
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY requirements.txt ./
|
COPY requirements.txt ./
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
COPY main.py impact.ttf ./
|
COPY main.py config.py impact.ttf zparser.py ./
|
||||||
COPY maket ./maket
|
COPY maket ./maket
|
||||||
COPY AI ./AI
|
COPY AI ./AI
|
||||||
CMD ["python", "main.py"]
|
CMD ["python", "main.py"]
|
||||||
|
|
|
||||||
95
config.py
Normal file
95
config.py
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import timedelta, time
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
# --- Базовые пути ---
|
||||||
|
BASE_DIR = Path(__file__).parent
|
||||||
|
FONT_PATH = BASE_DIR / "impact.ttf"
|
||||||
|
DEFAULT_TZ = os.getenv("TZ", "Europe/Moscow")
|
||||||
|
|
||||||
|
# --- Настройки /penis ---
|
||||||
|
PENIS_DB_PATH = "/db/penis_stats.sqlite3"
|
||||||
|
PENIS_START_LENGTH = 10.0
|
||||||
|
PENIS_MIN_DELTA = 0.1
|
||||||
|
PENIS_MAX_DELTA = 7.0
|
||||||
|
PENIS_COOLDOWN = timedelta(hours=24)
|
||||||
|
PENIS_COOLDOWN_SECONDS = int(PENIS_COOLDOWN.total_seconds())
|
||||||
|
PENIS_TOP_LIMIT = 10
|
||||||
|
|
||||||
|
# --- Конфигурация макетов ---
|
||||||
|
TEMPLATES = {
|
||||||
|
"1": {
|
||||||
|
"path": BASE_DIR / "maket" / "1.png",
|
||||||
|
"anchor": (104, 240),
|
||||||
|
"padding": 20,
|
||||||
|
"label": "Владимир Владимирович Путин самый лучший президент",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Расписание ---
|
||||||
|
def make_time(h: int, m: int) -> time:
|
||||||
|
return time(hour=h, minute=m)
|
||||||
|
|
||||||
|
SCHEDULE = {
|
||||||
|
0: [ # Понедельник
|
||||||
|
(make_time(9, 50), make_time(10, 35), 5),
|
||||||
|
(make_time(10, 40), make_time(11, 25), 30),
|
||||||
|
(make_time(11, 55), make_time(12, 40), 5),
|
||||||
|
(make_time(12, 45), make_time(13, 30), 15),
|
||||||
|
(make_time(13, 45), make_time(14, 30), 5),
|
||||||
|
(make_time(14, 35), make_time(15, 20), 30),
|
||||||
|
(make_time(15, 50), make_time(16, 35), 5),
|
||||||
|
(make_time(16, 40), make_time(17, 25), None),
|
||||||
|
],
|
||||||
|
1: [ # Вторник
|
||||||
|
(make_time(9, 50), make_time(10, 35), 5),
|
||||||
|
(make_time(10, 40), make_time(11, 25), 30),
|
||||||
|
(make_time(11, 55), make_time(12, 40), 5),
|
||||||
|
(make_time(12, 45), make_time(13, 30), 15),
|
||||||
|
(make_time(13, 45), make_time(14, 30), 5),
|
||||||
|
(make_time(14, 35), make_time(15, 20), None),
|
||||||
|
],
|
||||||
|
2: [], # Среда
|
||||||
|
3: [ # Четверг
|
||||||
|
(make_time(8, 0), make_time(8, 45), 5),
|
||||||
|
(make_time(8, 50), make_time(9, 35), 15),
|
||||||
|
(make_time(9, 50), make_time(10, 35), 5),
|
||||||
|
(make_time(10, 40), make_time(11, 25), 30),
|
||||||
|
(make_time(11, 55), make_time(12, 40), 5),
|
||||||
|
(make_time(12, 45), make_time(13, 30), 15),
|
||||||
|
(make_time(13, 45), make_time(14, 30), 5),
|
||||||
|
(make_time(14, 35), make_time(15, 20), 30),
|
||||||
|
(make_time(15, 50), make_time(16, 35), 5),
|
||||||
|
(make_time(16, 40), make_time(17, 25), None),
|
||||||
|
],
|
||||||
|
4: [ # Пятница
|
||||||
|
(make_time(9, 50), make_time(10, 35), 5),
|
||||||
|
(make_time(10, 40), make_time(11, 25), 30),
|
||||||
|
(make_time(11, 55), make_time(12, 40), 5),
|
||||||
|
(make_time(12, 45), make_time(13, 30), 15),
|
||||||
|
(make_time(13, 45), make_time(14, 30), 5),
|
||||||
|
(make_time(14, 35), make_time(15, 20), None),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Остальное ---
|
||||||
|
KEYWORDS = {'крип', 'радиохэд', 'creep', 'radiohead'}
|
||||||
|
|
||||||
|
# --- Авто-ответы ИИ ---
|
||||||
|
AUTOREPLY_CHANCE = 0.10
|
||||||
|
AUTOREPLY_COOLDOWN = 120
|
||||||
|
AUTOREPLY_TRIGGERS = {'бот', 'фраер', 'кент', 'братуха', 'пацаны', 'чё как', 'базар'}
|
||||||
|
|
||||||
|
def get_hint_text(templates_str: str) -> str:
|
||||||
|
return (
|
||||||
|
"Команды:\n"
|
||||||
|
f"• /maket «id» «текст» — доступные: {templates_str}.\n"
|
||||||
|
"• /gen_mem Up:верх Down:низ — отправь с фото.\n"
|
||||||
|
"• /break — узнать время до перекура.\n"
|
||||||
|
"• /penis — миниигра 1 раз в 24 часа.\n"
|
||||||
|
"• /top_penis — топ по длине.\n"
|
||||||
|
"• /talk [текст] — ИИ базарит на фене.\n"
|
||||||
|
"• /prices /fetch — цены.\n"
|
||||||
|
"Подсказка: в группах пиши /команда@username_бота."
|
||||||
|
)
|
||||||
|
|
@ -3,6 +3,8 @@ version: "3.9"
|
||||||
services:
|
services:
|
||||||
bot:
|
bot:
|
||||||
build: .
|
build: .
|
||||||
|
volumes:
|
||||||
|
- ./db:/db
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
aiogram>=3.4.1
|
aiogram>=3.4.1
|
||||||
pillow>=10.3.0
|
pillow>=10.3.0
|
||||||
requests>=2.31.0
|
requests>=2.31.0
|
||||||
|
beautifulsoup4
|
||||||
|
lxml
|
||||||
|
pysqlite3-binary>=0.5.3
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue