Refactoring: step3
- вся работа с shelve унесена в report - вся работа с БД унесена в моделс (крме команд админа) - ид книги лутца и звука вынесены в константы - исправлен баг в проверке на смешанный алфавит при определении спама, добавлены константы для более точного выявления - написаны новые тесты в том числе на цитаты и действия админов
This commit is contained in:
+10
-20
@@ -1,16 +1,16 @@
|
||||
import logging
|
||||
import logging.handlers
|
||||
import shelve
|
||||
|
||||
from telebot import types
|
||||
|
||||
from .constants import DATA, LOG_COMM, FAQ, LIB, RULES, RUS, RUS_ENG_TABLE, ENG_RUS_TABLE, PYTHONCHATRU, ZEN
|
||||
from .admin_commands import bot
|
||||
from .constants import (LOG_COMM, FAQ, LIB, RULES, RUS, RUS_ENG_TABLE, ENG_RUS_TABLE, PYTHONCHATRU, ZEN, LUTZ_ID,
|
||||
BDMTSS_ID)
|
||||
from .filters import in_spam_list, in_caption_spam_list, in_delete_list
|
||||
from .helpers import represent_as_get, detect_args, is_admin
|
||||
from .admin_commands import bot
|
||||
from .report import update_stats, increment
|
||||
from .rules import fetch_rule
|
||||
from .stan import act, speak
|
||||
from .report import update_stats
|
||||
|
||||
|
||||
async def send_or_reply(message: types.Message, answer, **kwargs):
|
||||
@@ -29,8 +29,7 @@ async def moderate_messages(message: types.Message):
|
||||
"""Ban user and delete their message."""
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
await bot.ban_chat_member(message.chat.id, message.from_user.id)
|
||||
with shelve.open(f"{DATA}{message.chat.id}") as shelve_db:
|
||||
shelve_db["Banned"] += 1
|
||||
increment(message.chat.id, banned=True)
|
||||
|
||||
|
||||
@bot.message_handler(func=in_caption_spam_list, content_types=["video"], chat_types=["supergroup", "group"])
|
||||
@@ -38,8 +37,7 @@ async def catch_videos(message: types.Message):
|
||||
"""Catch offensive videos"""
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
await bot.ban_chat_member(message.chat.id, message.from_user.id)
|
||||
with shelve.open(f"{DATA}{message.chat.id}") as shelve_db:
|
||||
shelve_db["Banned"] += 1
|
||||
increment(message.chat.id, banned=True)
|
||||
|
||||
|
||||
@bot.edited_message_handler(func=in_delete_list, chat_types=["supergroup", "group"])
|
||||
@@ -47,8 +45,7 @@ async def catch_videos(message: types.Message):
|
||||
async def delete_message(message: types.Message):
|
||||
"""Delete unwanted message."""
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
with shelve.open(f"{DATA}{message.chat.id}") as shelve_db:
|
||||
shelve_db["Deleted"] += 1
|
||||
increment(message.chat.id, banned=False)
|
||||
|
||||
|
||||
""" [ COMMANDS ] """
|
||||
@@ -122,11 +119,7 @@ async def send_lutz(message: types.Message):
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
await bot.send_document(
|
||||
message.chat.id,
|
||||
document="BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA",
|
||||
caption="вот, не позорься",
|
||||
)
|
||||
await bot.send_document(message.chat.id, document=LUTZ_ID, caption="вот, не позорься")
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@@ -141,10 +134,7 @@ async def send_bdmtss_audio(message: types.Message):
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
await bot.send_voice(
|
||||
message.chat.id,
|
||||
"AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ",
|
||||
)
|
||||
await bot.send_voice(message.chat.id, BDMTSS_ID)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@@ -210,7 +200,7 @@ async def send_nometa(message: types.Message):
|
||||
)
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
markup.add(types.InlineKeyboardButton("❓ nometa.xyz", url="https://nometa.xyz/ru.html"), row_width=1)
|
||||
markup.add(types.InlineKeyboardButton("❓ nometa.xyz", url="https://nometa.xyz/ru.html"), row_width=1)
|
||||
await send_or_reply(
|
||||
message,
|
||||
"""Не задавай мета-вопросов вроде:
|
||||
|
||||
+3
-1
@@ -1,9 +1,11 @@
|
||||
import logging
|
||||
import os
|
||||
from .helpers import is_url_reachable
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from telebot import logger
|
||||
|
||||
from .helpers import is_url_reachable
|
||||
|
||||
load_dotenv()
|
||||
|
||||
TOKEN = os.environ.get("LUTZPYBOT")
|
||||
|
||||
+5
-2
@@ -1,8 +1,8 @@
|
||||
import re
|
||||
import string
|
||||
|
||||
from telebot import types
|
||||
|
||||
|
||||
LOG_TEXT = "[%s] %s: %s"
|
||||
LOG_COMM = "[%s] [%s] %s: %s"
|
||||
LOGGING_LEVEL_DEBUG = 10
|
||||
@@ -37,6 +37,8 @@ ALLOWED_WORDS = [
|
||||
]
|
||||
|
||||
RUS = """ёйцукенгшщзхъфывапролджэячсмитьбю.Ё!"№;%:?ЙЦУКЕНГШЩЗХЪ/ФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,"""
|
||||
ONLY_RUS_LETTERS = "ёйцукенгшщзхъфывапролджэячсмитьбю"
|
||||
RUS_LETTERS_AND_PUNCTUATION = ONLY_RUS_LETTERS + string.punctuation
|
||||
ENG = """`qwertyuiop[]asdfghjkl;'zxcvbnm,./~!@#$%^&QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?"""
|
||||
RUS_ENG_TABLE = str.maketrans(RUS, ENG)
|
||||
ENG_RUS_TABLE = str.maketrans(ENG, RUS)
|
||||
@@ -78,4 +80,5 @@ ZEN = [
|
||||
"If the implementation is easy to explain, it may be a good idea.",
|
||||
"Namespaces are one honking great idea — let's do more of those!",
|
||||
]
|
||||
|
||||
LUTZ_ID = "BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA"
|
||||
BDMTSS_ID = "AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ"
|
||||
|
||||
+3
-4
@@ -5,12 +5,11 @@ from telebot import types
|
||||
from .config import WHITEIDS
|
||||
from .constants import LOG_COMM, ALLOWED_WORDS, URL_RX
|
||||
from .helpers import is_spam, is_in_not_allowed, is_ban_words_in_caption
|
||||
from .models import Chat, session
|
||||
from .models import is_antispam_enabled
|
||||
|
||||
|
||||
def in_spam_list(message: types.Message) -> bool:
|
||||
"""Check for mentioning unwanted persons in text."""
|
||||
antispam_is_enabled = session.query(Chat.antispam).filter_by(chat_id=message.chat.id).first()[0]
|
||||
antispam_is_enabled = is_antispam_enabled(message.chat.id)
|
||||
from_user_id, title, from_user_name = message.from_user.id, message.chat.title, message.from_user.first_name
|
||||
if from_user_id not in WHITEIDS and antispam_is_enabled:
|
||||
if is_spam(message.text):
|
||||
@@ -30,7 +29,7 @@ def in_caption_spam_list(message: types.Message) -> bool:
|
||||
|
||||
def in_delete_list(message: types.Message) -> bool:
|
||||
"""Check for URLs in message and delete."""
|
||||
antispam_is_enabled = session.query(Chat.antispam).filter_by(chat_id=message.chat.id).first()[0]
|
||||
antispam_is_enabled = is_antispam_enabled(message.chat.id)
|
||||
from_user_id, title, from_user_name = message.from_user.id, message.chat.title, message.from_user.first_name
|
||||
if from_user_id not in WHITEIDS and antispam_is_enabled:
|
||||
if URL_RX.search(message.text) and is_in_not_allowed(ALLOWED_WORDS, message.text):
|
||||
|
||||
+10
-2
@@ -6,7 +6,7 @@ from urllib.request import urlopen
|
||||
|
||||
from telebot import types
|
||||
|
||||
from .constants import SPAM, RUS, BAN_WORDS, NON_GRATA, ADMIN_ID
|
||||
from .constants import SPAM, BAN_WORDS, NON_GRATA, ADMIN_ID, ONLY_RUS_LETTERS, RUS_LETTERS_AND_PUNCTUATION
|
||||
|
||||
|
||||
def is_url_reachable(url: str) -> bool:
|
||||
@@ -17,14 +17,22 @@ def is_url_reachable(url: str) -> bool:
|
||||
|
||||
|
||||
def is_spam(message_text: str) -> bool:
|
||||
"""
|
||||
Проверяет текст на спам - сначала проверка смешанного алфавита, потом на константный набор спам-слов
|
||||
"""
|
||||
if is_mixed(message_text):
|
||||
return True
|
||||
return any(text.casefold() in message_text.casefold() for text in SPAM)
|
||||
|
||||
|
||||
def is_mixed(text: str) -> bool:
|
||||
"""
|
||||
Разбивает текст на слова и проверяет на смешанный алфавит, спамеры используют его. Слово допускается только
|
||||
полностью на русском или русский + знаки пунктуации
|
||||
"""
|
||||
for word in text.split():
|
||||
if not all(e in RUS for e in word.strip().lower()):
|
||||
word = word.strip().lower()
|
||||
if any(e in ONLY_RUS_LETTERS for e in word) and not all(e in RUS_LETTERS_AND_PUNCTUATION for e in word):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from pathlib import Path
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import delete
|
||||
from sqlalchemy.orm import relationship, declarative_base, sessionmaker
|
||||
|
||||
Base = declarative_base()
|
||||
@@ -49,3 +50,29 @@ class Chat(Base):
|
||||
|
||||
def __repr__(self):
|
||||
return f'Chat({self.chat_id=}, {self.title=})'
|
||||
|
||||
|
||||
def is_antispam_enabled(chat_id: int) -> bool:
|
||||
try:
|
||||
return session.query(Chat.antispam).filter_by(chat_id=chat_id).first()[0]
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
|
||||
def is_quote_in_chat(text: str, chat_id: int) -> bool:
|
||||
result = session.query(Quote.text).filter_by(text=text, chat_id=chat_id).first()
|
||||
return bool(result)
|
||||
|
||||
|
||||
def delete_quote_in_chat(text: str, chat_id: int):
|
||||
session.execute(delete(Quote).filter_by(text=text, chat_id=chat_id))
|
||||
session.commit()
|
||||
|
||||
|
||||
def all_chat_quotes(chat_id: int) -> list:
|
||||
return session.query(Quote.text).filter(Quote.chat_id == chat_id).all()
|
||||
|
||||
|
||||
def add_quote(chat_id: int, text: str):
|
||||
session.add(Quote(chat_id=chat_id, text=text))
|
||||
session.commit()
|
||||
|
||||
+10
-3
@@ -5,10 +5,17 @@ import random
|
||||
import shelve
|
||||
from pathlib import Path
|
||||
|
||||
from telebot import types
|
||||
|
||||
from .config import ROLLBACK
|
||||
from .constants import DATA
|
||||
from .constants import DATA, types
|
||||
|
||||
|
||||
def increment(chat_id: int, banned: bool = True):
|
||||
"""
|
||||
Увеличивает счетчик банов или удаленных
|
||||
"""
|
||||
category = "Banned" if banned else "Deleted"
|
||||
with shelve.open(f"{DATA}{chat_id}") as shelve_db:
|
||||
shelve_db[category] += 1
|
||||
|
||||
|
||||
def create_report_text(chat_id):
|
||||
|
||||
+8
-11
@@ -3,21 +3,21 @@ import asyncio
|
||||
import html
|
||||
import random
|
||||
|
||||
from sqlalchemy import delete
|
||||
from telebot import types
|
||||
|
||||
from .filters import is_white_id
|
||||
from .helpers import is_nongrata
|
||||
from .models import Quote, session
|
||||
from .models import all_chat_quotes, add_quote, is_quote_in_chat, delete_quote_in_chat
|
||||
from .robot import bot
|
||||
|
||||
TYPING_TIMEOUT = 0.13 / 4 # Reading time is quarter of the same text writing time
|
||||
|
||||
|
||||
def speak(chance_of, group_id):
|
||||
def speak(chance_of: int, chat_id: int) -> None | str:
|
||||
number = random.randint(0, chance_of)
|
||||
if number == 0:
|
||||
return random.choice([i[0] for i in session.query(Quote.text).filter(Quote.chat_id == group_id).all()])
|
||||
return random.choice([i[0] for i in all_chat_quotes(chat_id)])
|
||||
return None
|
||||
|
||||
|
||||
async def send_quote(after_sec, message, quote):
|
||||
@@ -39,9 +39,8 @@ async def act(message: types.Message):
|
||||
async def add_stan_quote(message: types.Message):
|
||||
if message.reply_to_message and message.reply_to_message.text:
|
||||
quote = message.reply_to_message.text
|
||||
if quote not in [i[0] for i in session.query(Quote.text).filter(Quote.chat_id == message.chat.id).all()]:
|
||||
session.add(Quote(chat_id=message.chat.id, text=quote.replace("\n", " ")))
|
||||
session.commit()
|
||||
if quote not in {i[0] for i in all_chat_quotes(message.chat.id)}:
|
||||
add_quote(message.chat.id, quote.replace("\n", " "))
|
||||
await bot.send_message(message.chat.id, "➕\n └ " + quote.replace("\n", " "), parse_mode='Markdown')
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
else:
|
||||
@@ -52,10 +51,8 @@ async def add_stan_quote(message: types.Message):
|
||||
async def remove_stan_quote(message: types.Message):
|
||||
if message.reply_to_message and message.reply_to_message.text:
|
||||
quote = message.reply_to_message.text
|
||||
already_exist = session.query(Quote.text).filter_by(text=quote, chat_id=message.chat.id).first()
|
||||
if already_exist:
|
||||
session.execute(delete(Quote).filter_by(text=quote, chat_id=message.chat.id))
|
||||
session.commit()
|
||||
if is_quote_in_chat(quote, message.chat.id):
|
||||
delete_quote_in_chat(quote, message.chat.id)
|
||||
await bot.send_message(message.chat.id, f"➖ \n └ {quote}", parse_mode='Markdown')
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user