It's version 0.6.2 I clear code
This commit is contained in:
@@ -18,3 +18,6 @@ storage/message.txt
|
||||
/addons/todo/todo.db
|
||||
/addons/rule34/urls.db
|
||||
/addons/x_days_to/days_to_new_year.db
|
||||
/addons/hello/photo_2025-11-17_20-57-54.jpg
|
||||
/addons/poll/img.png
|
||||
/addons/hello/мемы/
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
def register(dp, state, bot):
|
||||
from . import handlers
|
||||
|
||||
handlers.register_handlers(dp, state, bot)
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from mutagen.id3 import ID3, APIC, error
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def get_video_info(url: str) -> dict:
|
||||
async def get_video_info(url: str) -> Optional[dict]:
|
||||
"""Получает информацию о видео через yt-dlp"""
|
||||
try:
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
@@ -63,8 +63,8 @@ def apply_metadata(mp3_path: str, metadata: dict):
|
||||
# Сначала удаляем старые теги ID3 если есть
|
||||
try:
|
||||
ID3(mp3_path).delete()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось удалить старые ID3 теги: {e}")
|
||||
|
||||
# Добавляем текстовые теги
|
||||
try:
|
||||
|
||||
+15
-10
@@ -3,7 +3,7 @@ import base64
|
||||
from io import BytesIO
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
from PIL import Image
|
||||
from aiogram import Dispatcher, Bot
|
||||
from aiogram.types import Message, BufferedInputFile
|
||||
from aiogram.filters import Command
|
||||
@@ -43,6 +43,11 @@ async def generate_img2img(prompt: str, init_image: BytesIO) -> BytesIO | None:
|
||||
:return: BytesIO с результатом или None при ошибке
|
||||
"""
|
||||
try:
|
||||
# Определяем размеры оригинала
|
||||
init_image.seek(0)
|
||||
with Image.open(init_image) as img:
|
||||
width, height = img.size
|
||||
|
||||
# кодируем входное изображение в base64
|
||||
init_image_base64 = base64.b64encode(init_image.getvalue()).decode("utf-8")
|
||||
|
||||
@@ -50,15 +55,15 @@ async def generate_img2img(prompt: str, init_image: BytesIO) -> BytesIO | None:
|
||||
"init_images": [init_image_base64],
|
||||
"prompt": prompt,
|
||||
"negative_prompt": "blurry, low quality, bad anatomy, watermark, text, cropped",
|
||||
"steps": 20, # можно 15–20
|
||||
"width": 1024, # лучше подставлять размеры исходного фото
|
||||
"height": 1024,
|
||||
"sampler_name": "Euler a", # мягкий и стабильный для img2img
|
||||
"Schedule_type": "Karras",
|
||||
"cfg_scale": 6, # чуть ниже, чем для txt2img
|
||||
"steps": 25,
|
||||
"width": width, # берём ширину оригинала
|
||||
"height": height, # берём высоту оригинала
|
||||
"sampler_name": "Euler a",
|
||||
"scheduler": "Karras", # исправлен ключ
|
||||
"cfg_scale": 10,
|
||||
"seed": -1,
|
||||
"denoising_strength": 0.8, # 0.3–0.5 для «сохранить стиль», 0.6–0.8 для «перерисовать»
|
||||
"restore_faces": True, # если работаешь с людьми
|
||||
"denoising_strength": 0.45,
|
||||
"restore_faces": True,
|
||||
"override_settings": {
|
||||
"sd_model_checkpoint": "waiNSFWIllustrious_v150.safetensors"
|
||||
},
|
||||
@@ -101,7 +106,7 @@ async def generate_image(prompt: str) -> BytesIO | None:
|
||||
"hr_scale": 2, # во сколько раз увеличить при highres fix
|
||||
"hr_upscaler": "Latent", # апскейлер для highres fix
|
||||
"override_settings": {
|
||||
"sd_model_checkpoint": "waiNSFWIllustrious_v150.safetensors" # выбор модели
|
||||
"sd_model_checkpoint": "sd_xl_base_1.safetensors" # выбор модели
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,66 @@
|
||||
from aiogram import Dispatcher, Bot
|
||||
from aiogram.types import Message
|
||||
from aiogram.types import Message, FSInputFile
|
||||
from aiogram.filters import Command
|
||||
from models.state import BotState
|
||||
from config import Config
|
||||
import logging
|
||||
from utils.antispam import admin_required
|
||||
from storage.message_storage import save_message # импортируем функцию
|
||||
import os
|
||||
import asyncio
|
||||
from random import choice, seed
|
||||
from time import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
async def list_files():
|
||||
# Запускаем синхронный os.listdir в отдельном потоке
|
||||
return await asyncio.to_thread(os.listdir, "/Users/mac/myfirstprogramm/addons/hello/мемы")
|
||||
|
||||
def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
|
||||
i = 0
|
||||
@dp.message(Command("hello"))
|
||||
@admin_required(1)
|
||||
async def hello(message: Message):
|
||||
# сохраняем саму команду пользователя
|
||||
nonlocal i
|
||||
save_message(message.chat.id, message.message_id)
|
||||
|
||||
for admin_id in Config.ADMINS:
|
||||
try:
|
||||
name = Config.Names.get(admin_id, "Админ")
|
||||
msg = await bot.send_message(
|
||||
chat_id=admin_id, text=f"🤖 Я готов к работе, господин {name}!"
|
||||
)
|
||||
# сохраняем сообщение, отправленное админу
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
if 1345058877 == admin_id:
|
||||
name = Config.Names.get(admin_id, "Админ")
|
||||
photo = FSInputFile("/Users/mac/myfirstprogramm/addons/hello/photo_2025-11-17_20-57-54.jpg")
|
||||
msg = await bot.send_photo(
|
||||
chat_id=admin_id, photo=photo, caption=f"🤖 Я готов к работе, господин {name}!"
|
||||
)
|
||||
|
||||
logger.info(f"Сообщение отправлено админу {admin_id} ({name})")
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
logger.info(f"Фото отправлено админу {admin_id} ({name})")
|
||||
elif 6394047531 == admin_id:
|
||||
png = choice(await list_files())
|
||||
i += 1
|
||||
seed(time() + i)
|
||||
name = Config.Names.get(admin_id, "Админ")
|
||||
photo = FSInputFile(f"/Users/mac/myfirstprogramm/addons/hello/мемы/{png}")
|
||||
msg = await bot.send_photo(
|
||||
chat_id=admin_id, photo=photo, caption=f"🤖 Я готов к работе, господин {name}!"
|
||||
)
|
||||
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
logger.info(f"Фото {f"/Users/mac/myfirstprogramm/addons/hello/мемы/{png}"} отправлено админу {admin_id} ({name})")
|
||||
|
||||
else:
|
||||
name = Config.Names.get(admin_id, "Админ")
|
||||
msg = await bot.send_message(
|
||||
chat_id=admin_id, text=f"🤖 Я готов к работе, господин {name}!"
|
||||
)
|
||||
# сохраняем сообщение, отправленное админу
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
|
||||
logger.info(f"Сообщение отправлено админу {admin_id} ({name})")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при отправке админу {admin_id}: {e}")
|
||||
|
||||
|
||||
+24
-5
@@ -3,7 +3,6 @@ from aiogram import Dispatcher, Bot
|
||||
from aiogram.types import Message
|
||||
from aiogram.filters import Command
|
||||
from models.state import BotState
|
||||
from utils.antispam import saving
|
||||
|
||||
API_URL = "http://127.0.0.1:7700/speak"
|
||||
|
||||
@@ -12,7 +11,27 @@ logger = getLogger(__name__)
|
||||
|
||||
def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
|
||||
@dp.message(Command("id"))
|
||||
@saving
|
||||
async def id(message: Message):
|
||||
id = message.from_user.id
|
||||
msg = await message.reply(str(id))
|
||||
async def id_handler(message: Message):
|
||||
# Разбираем аргументы команды
|
||||
args = message.text.split()
|
||||
if len(args) > 1:
|
||||
try:
|
||||
user_id = int(args[1]) # берём ID из аргумента
|
||||
except ValueError:
|
||||
await message.reply("ID должен быть числом")
|
||||
return
|
||||
else:
|
||||
# если аргумента нет — берём ID самого пользователя
|
||||
user_id = message.from_user.id
|
||||
|
||||
# Получаем фото профиля
|
||||
photos = await bot.get_user_profile_photos(user_id=user_id)
|
||||
|
||||
if photos.total_count > 0:
|
||||
for i, photo_sizes in enumerate(photos.photos):
|
||||
file_id = photo_sizes[-1].file_id # самое большое разрешение
|
||||
await message.answer_photo(file_id, caption=f"Аватар #{i + 1}")
|
||||
await message.reply(f"ID пользователя: {user_id}")
|
||||
else:
|
||||
await message.reply(f"У пользователя {user_id} нет аватара")
|
||||
|
||||
|
||||
+22
-12
@@ -1,7 +1,7 @@
|
||||
from config import Config
|
||||
from utils.antispam import admin_required
|
||||
from aiogram import Dispatcher, Bot
|
||||
from aiogram.types import Message
|
||||
from aiogram.types import Message, FSInputFile
|
||||
from models.state import BotState
|
||||
from aiogram.filters import Command
|
||||
from logging import getLogger
|
||||
@@ -20,7 +20,7 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
|
||||
poll_msg = await bot.send_poll(
|
||||
chat_id=chat_id,
|
||||
question="Кто опоздает?",
|
||||
options=["Я", "Я очень сильно опоздаю", "Я пиздец как опоздаю", "Наверное", "Не опоздаю"],
|
||||
options=["Я", "Я очень сильно опоздаю", "Я пиздец как опоздаю", "Наверное", "я ДОЛБОЯЩЕР и я к 2 паре", "Не опоздаю"],
|
||||
is_anonymous=False,
|
||||
allows_multiple_answers=False,
|
||||
)
|
||||
@@ -44,39 +44,49 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
|
||||
|
||||
# всегда пишем в первый чат из Config.CHAT_IDS
|
||||
# 6394047531
|
||||
#850906163
|
||||
STARAST = 6394047531
|
||||
|
||||
if option_ids and option_ids[0] == 0:
|
||||
if not option_ids:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} опоздает"
|
||||
chat_id=STARAST, text=f"{username} Отменил свой голос"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
elif option_ids and option_ids[0] == 0:
|
||||
msg = await bot.send_message(
|
||||
chat_id=STARAST, text=f"{username} опоздает"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
elif option_ids and option_ids[0] == 1:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} сильно опоздает"
|
||||
chat_id=STARAST, text=f"{username} сильно опоздает"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
elif option_ids and option_ids[0] == 2:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} Пиздец опоздает"
|
||||
chat_id=STARAST, text=f"{username} Пиздец опоздает"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
elif option_ids[0] == 3:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} возможно опоздает"
|
||||
chat_id=STARAST, text=f"{username} возможно опоздает"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
|
||||
elif option_ids[0] == 4:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} возможно опоздает"
|
||||
photo = FSInputFile("/Users/mac/myfirstprogramm/addons/poll/img.png")
|
||||
msg = await bot.send_photo(
|
||||
chat_id=STARAST, photo=photo, caption=f"{username} ДОЛБОЯЩЕР"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
elif not option_ids:
|
||||
|
||||
elif option_ids[0] == 5:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} Отменил свой голос"
|
||||
chat_id=STARAST, text=f"{username} не опоздает"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
else:
|
||||
msg = await bot.send_message(
|
||||
chat_id=6394047531, text=f"{username} выбрал вариант {option_ids}"
|
||||
chat_id=STARAST, text=f"{username} выбрал вариант {option_ids}"
|
||||
)
|
||||
save_message(msg.chat.id, msg.message_id)
|
||||
|
||||
+61
-45
@@ -1,11 +1,8 @@
|
||||
import requests
|
||||
import asyncio
|
||||
from random import randint, choice
|
||||
from bs4 import BeautifulSoup
|
||||
from playwright.async_api import async_playwright
|
||||
|
||||
BASE_URL = "https://rule34.xxx"
|
||||
HEADERS = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
|
||||
}
|
||||
URL = f"{BASE_URL}/index.php?page=post&s=list"
|
||||
MAXIMUM = 999
|
||||
|
||||
@@ -25,49 +22,68 @@ def get_tags_str() -> str:
|
||||
def get_tags() -> str:
|
||||
return "+".join(TAGS) if TAGS else ""
|
||||
|
||||
def get_url():
|
||||
while True:
|
||||
try:
|
||||
tags = get_tags()
|
||||
pid = randint(1, MAXIMUM)
|
||||
|
||||
# Формируем корректный URL с query‑параметрами
|
||||
if tags:
|
||||
url_page = f"{URL}&tags={tags}&pid={pid}"
|
||||
else:
|
||||
url_page = f"{URL}&pid={pid}"
|
||||
async def get_url():
|
||||
async with async_playwright() as p:
|
||||
browser = await p.firefox.launch(headless=True)
|
||||
page = await browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
|
||||
|
||||
r = requests.get(url_page, headers=HEADERS, timeout=5)
|
||||
soup = BeautifulSoup(r.text, 'lxml')
|
||||
block = soup.find(class_="image-list")
|
||||
if not block:
|
||||
continue
|
||||
block = block.find_all("span")
|
||||
if not block:
|
||||
while True:
|
||||
try:
|
||||
tags = get_tags()
|
||||
pid = randint(1, MAXIMUM)
|
||||
|
||||
# Формируем корректный URL
|
||||
if tags:
|
||||
url_page = f"{URL}&tags={tags}&pid={pid}"
|
||||
else:
|
||||
url_page = f"{URL}&pid={pid}"
|
||||
|
||||
await page.goto(url_page, timeout=5000)
|
||||
|
||||
# Ищем блок с картинками
|
||||
block = await page.query_selector(".image-list")
|
||||
if not block:
|
||||
continue
|
||||
|
||||
spans = await block.query_selector_all("span")
|
||||
if not spans:
|
||||
continue
|
||||
|
||||
link_el = await choice(spans).query_selector("a")
|
||||
if not link_el:
|
||||
continue
|
||||
|
||||
href = await link_el.get_attribute("href")
|
||||
if not href:
|
||||
continue
|
||||
|
||||
await page.goto(f"{BASE_URL}{href}", timeout=30000)
|
||||
|
||||
flexi = await page.query_selector(".flexi")
|
||||
if not flexi:
|
||||
continue
|
||||
|
||||
img_el = await flexi.query_selector("img")
|
||||
if not img_el:
|
||||
continue
|
||||
|
||||
url = await img_el.get_attribute("src")
|
||||
if not url:
|
||||
continue
|
||||
|
||||
await browser.close()
|
||||
return url
|
||||
|
||||
except Exception as e:
|
||||
print(f"[get_url ERROR] {e}")
|
||||
continue
|
||||
|
||||
link = choice(block).find("a")
|
||||
if not link:
|
||||
continue
|
||||
|
||||
r2 = requests.get(f"{BASE_URL}{link.get('href')}", headers=HEADERS, timeout=10)
|
||||
soup_two = BeautifulSoup(r2.text, 'lxml')
|
||||
|
||||
flexi = soup_two.find(class_="flexi")
|
||||
if not flexi:
|
||||
continue
|
||||
|
||||
img = flexi.find("img")
|
||||
if not img:
|
||||
continue
|
||||
|
||||
url = img.get("src")
|
||||
if not url:
|
||||
continue
|
||||
|
||||
return url
|
||||
|
||||
except Exception as e:
|
||||
print(f"[get_url ERROR] {e}")
|
||||
continue
|
||||
# Пример использования
|
||||
async def main():
|
||||
result = await get_url()
|
||||
print("Result URL:", result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -26,7 +26,7 @@ def register_handlers(dp: Dispatcher, state, bot: Bot):
|
||||
@dp.message(Command("rule34"))
|
||||
async def rule34(message: Message):
|
||||
msg = await message.answer_photo(
|
||||
photo=get_url(),
|
||||
photo= await get_url(),
|
||||
caption="Вот фото 📷",
|
||||
reply_markup=get_keyboard()
|
||||
)
|
||||
@@ -39,7 +39,7 @@ def register_handlers(dp: Dispatcher, state, bot: Bot):
|
||||
for attempt in range(3): # максимум 3 попытки
|
||||
try:
|
||||
media = InputMediaPhoto(
|
||||
media=get_url(),
|
||||
media=await get_url(),
|
||||
caption=f"Новое фото 🌄 (попытка {attempt + 1})"
|
||||
)
|
||||
await callback.message.edit_media(
|
||||
|
||||
@@ -8,6 +8,7 @@ from aiogram.types import Message
|
||||
from models.state import BotState
|
||||
from aiogram.filters import Command
|
||||
from logging import getLogger
|
||||
import aiohttp
|
||||
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class TelegramBot:
|
||||
self.addons.load("poll")
|
||||
self.addons.load("hello")
|
||||
# self.addons.load("draw")
|
||||
# self.addons.load("gpt")
|
||||
self.addons.load("gpt")
|
||||
# self.addons.load("rule34")
|
||||
# self.addons.load("todo")
|
||||
self.addons.load("miniapps")
|
||||
|
||||
@@ -22,7 +22,7 @@ class Config:
|
||||
# Admins (user_id: уровень)
|
||||
ADMINS: Dict[int, int] = {850906163: 0, 6394047531: 4, 1345058877: 3}
|
||||
|
||||
Names: Dict[int, str] = {850906163: "Ляпич", 6394047531: "Прокопович"}
|
||||
Names: Dict[int, str] = {850906163: "Ляпич", 6394047531: "Прокопович", 1345058877: "Сом"}
|
||||
|
||||
# Chats
|
||||
CHAT_IDS = [-1003038389942]
|
||||
@@ -32,7 +32,7 @@ class Config:
|
||||
}
|
||||
|
||||
# Settings
|
||||
ANTISPAM_DELAY = 600
|
||||
ANTISPAM_DELAY = 20
|
||||
WATCHER_BASE_DELAY = 600
|
||||
|
||||
# Пути
|
||||
|
||||
@@ -41,7 +41,7 @@ def register_handlers(dp: Dispatcher, state: BotState):
|
||||
|
||||
@dp.message(Command("prasp"))
|
||||
@saving
|
||||
async def send_schedule(message: types.Message):
|
||||
async def send_pschedule(message: types.Message):
|
||||
"""Отправка расписания"""
|
||||
if is_chat_spam(message.chat.id, state):
|
||||
await message.answer("НЕ СПАМЬТЕ!!!")
|
||||
|
||||
@@ -92,8 +92,8 @@ class ScheduleService:
|
||||
return result, url, day, month
|
||||
|
||||
|
||||
|
||||
def exact_group_regex(self, group: str) -> re.Pattern:
|
||||
@staticmethod
|
||||
def exact_group_regex(group: str) -> re.Pattern:
|
||||
# ищем как отдельный токен: граница слева/справа или начало/конец
|
||||
pattern = rf"(^|{BOUNDARY}){re.escape(group)}({BOUNDARY}|$)"
|
||||
return re.compile(pattern)
|
||||
|
||||
+4
-5
@@ -157,16 +157,15 @@ def analyze_bot_logs(log_file_path="bot.log"):
|
||||
return stats
|
||||
|
||||
|
||||
def calculate_duration_hours(start_str, end_str):
|
||||
def calculate_duration_hours(start_str: str, end_str: str) -> float:
|
||||
"""Вычисляет продолжительность в часах"""
|
||||
fmt = "%Y-%m-%d %H:%M:%S"
|
||||
try:
|
||||
fmt = "%Y-%m-%d %H:%M:%S"
|
||||
start = datetime.strptime(start_str, fmt)
|
||||
end = datetime.strptime(end_str, fmt)
|
||||
return round((end - start).total_seconds() / 3600, 2)
|
||||
except:
|
||||
return 0
|
||||
|
||||
except (ValueError, TypeError):
|
||||
return 0.0
|
||||
|
||||
def calculate_success_rate(stats):
|
||||
"""Рассчитывает процент успешных операций"""
|
||||
|
||||
Reference in New Issue
Block a user