Refactoring: step 2

- независимые функции вынесены в хелперы
- добавлены тесты на хелперы и простые команды бота
- проверка урла Правил вынесена в хелпер
- уровень логирования повышен для бота
- добавлено пара кейсов и слов в спам
- при проверке на спам идет сработка если кроме русского и препинания есть еще какие-то символы
-
This commit is contained in:
kotolex
2023-12-22 22:17:07 +05:00
parent 9103669cac
commit 52347c19f7
11 changed files with 297 additions and 81 deletions
+7 -7
View File
@@ -4,8 +4,8 @@ from datetime import datetime as dt
from telebot import types, logger
from .constants import ADMIN_ID, LOGGING_LEVEL_DEBUG, LOGGING_LEVEL_INFO
from .filters import is_white, is_admin
from .helpers import me, my_ip
from .filters import is_white_id
from .helpers import me, my_ip, is_admin
from .models import Chat, Quote, session
from .reminder import remind, print_get_jobs, create_report_text
from .report import reset_report_stats
@@ -67,7 +67,7 @@ async def send_stats(message: types.Message):
await bot.send_message(message.chat.id, reset_report_stats(message.chat.id))
@bot.message_handler(func=is_white, commands=["enable_stan"], chat_types=["supergroup", "group"])
@bot.message_handler(func=is_white_id, commands=["enable_stan"], chat_types=["supergroup", "group"])
async def enable_stan(message: types.Message):
"""Add group to database."""
logging.info(f"[{message.chat.title}] [{message.from_user.id}] {message.from_user.username}: {message.text}")
@@ -96,7 +96,7 @@ async def disable_stan(message: types.Message):
@bot.message_handler(
func=is_white,
func=is_white_id,
commands=["set_antispam_report_reminder", "set_rules"],
chat_types=["supergroup", "group"],
)
@@ -117,7 +117,7 @@ async def set_antispam_report_reminder(message: types.Message):
await bot.send_message(message.chat.id, f"""Настройки обновлены. Проверить: /get_group_info""")
@bot.message_handler(func=is_white, commands=["get_quotes"], chat_types=["supergroup", "group"])
@bot.message_handler(func=is_white_id, commands=["get_quotes"], chat_types=["supergroup", "group"])
async def get_quotes(message: types.Message):
logging.info(f"[{message.chat.id}] {message.from_user.first_name} {message.text}.")
quotes = session.query(Quote.text).filter(Quote.chat_id == message.chat.id).all()
@@ -130,7 +130,7 @@ async def get_quotes(message: types.Message):
await bot.send_message(message.chat.id, f"Цитаты отсутствуют. Подробнее: /get_group_info")
@bot.message_handler(func=is_white, commands=["get_group_info"], chat_types=["supergroup", "group"])
@bot.message_handler(func=is_white_id, commands=["get_group_info"], chat_types=["supergroup", "group"])
async def get_group_info(message: types.Message):
group = session.query(Chat).filter(Chat.chat_id == message.chat.id).first()
if group:
@@ -151,7 +151,7 @@ ID группы: {group.chat_id}
await bot.send_message(message.chat.id, f"Группа не включена. Включить: /enable_stan")
@bot.message_handler(func=is_white, commands=["set_logging_level"], chat_types=["supergroup", "group"])
@bot.message_handler(func=is_white_id, commands=["set_logging_level"], chat_types=["supergroup", "group"])
async def set_logging_level(message: types.Message):
args = message.text.split()
if args[-1] == '10':
+3 -2
View File
@@ -5,11 +5,12 @@ 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 .filters import in_spam_list, in_caption_spam_list, in_delete_list, is_admin
from .helpers import represent_as_get, detect_args, update_stats
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 .rules import fetch_rule
from .stan import act, speak
from .report import update_stats
async def send_or_reply(message: types.Message, answer, **kwargs):
+4 -8
View File
@@ -1,8 +1,6 @@
import logging
import os
from urllib.error import URLError
from urllib.request import urlopen
from .helpers import is_url_reachable
from dotenv import load_dotenv
from telebot import logger
@@ -17,10 +15,8 @@ ROLLBACK = {int(i) for i in os.environ.get("rollback").split(",")}
USE_REMINDER = os.environ.get("use_reminder", "TRUE") == "TRUE"
RULES_URL = os.environ.get("rules_url", "https://telegra.ph/pythonchatru-07-07")
try:
assert urlopen(RULES_URL).status == 200
except (URLError, AssertionError):
if not is_url_reachable(RULES_URL):
raise LookupError(f"LUTZPYBOT rules url({RULES_URL}) is not reachable")
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logger.setLevel(logging.DEBUG)
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logger.setLevel(logging.INFO)
+2 -1
View File
@@ -55,7 +55,8 @@ SPAM = {"me.sv/", "tg.sv/", "goo.by/", "go.sv/", "intim.video/", "uclck.ru/", '
'заработка в крипте', 'Веду набор', 'Идёт набор', 'мне в ЛС', 'Доход от', 'Trading',
'P2P', 'Идет набор', 'в лс', 'нaбop', 'комaндy', 'kpuпт', 'бupж', '💰', 'пишитe', '💸',
'$ в неделю', 'обучаю с нуля', 'доходы для всех', 'по трейдингу', 'фальшивые рубли', '‼️',
'зароботку', 'Набuраю', 'цuфр', 'Обучу вас', 'прuб', 'остались курсы', 'Crypt', 'kр', 'рu'}
'зароботку', 'Набuраю', 'цuфр', 'Обучу вас', 'прuб', 'остались курсы', 'Crypt', 'kр', 'рu',
'в лc'}
NON_GRATA = {"дудар", "хауди", "dudar"}
BAN_WORDS = {"GREEN"}
+13 -34
View File
@@ -3,9 +3,9 @@ import logging.handlers
from telebot import types
from .config import WHITEIDS
from .constants import BAN_WORDS, LOG_COMM, SPAM, ALLOWED_WORDS, URL_RX, NON_GRATA, ADMIN_ID
from .models import Chat
from .models import session
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
def in_spam_list(message: types.Message) -> bool:
@@ -13,57 +13,36 @@ def in_spam_list(message: types.Message) -> bool:
antispam_is_enabled = session.query(Chat.antispam).filter_by(chat_id=message.chat.id).first()[0]
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:
for text in SPAM:
if text.casefold() in message.text.casefold():
logging.info("!BAN!" + LOG_COMM % (title, from_user_id, from_user_name, message.text))
return True
if is_spam(message.text):
logging.info("!BAN!" + LOG_COMM % (title, from_user_id, from_user_name, message.text))
return True
return False
def in_caption_spam_list(message: types.Message) -> bool:
"""Check for mentioning unwanted words in caption."""
for phrase in BAN_WORDS:
if message.caption and phrase in message.caption:
logging.info("!BAN!" + LOG_COMM % (
message.chat.title, message.from_user.id, message.from_user.first_name, message.video.file_name))
return True
if message.caption and is_ban_words_in_caption(message.caption):
from_user_id, title, from_user_name = message.from_user.id, message.chat.title, message.from_user.first_name
logging.info("!BAN!" + LOG_COMM % (title, from_user_id, from_user_name, message.video.file_name))
return True
return False
def in_not_allowed(word_list, msg):
for word in word_list:
if word in msg.casefold():
return False
return True
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]
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 in_not_allowed(ALLOWED_WORDS, message.text):
if URL_RX.search(message.text) and is_in_not_allowed(ALLOWED_WORDS, message.text):
logging.info(f"[DELETE] [{title}] [{from_user_id}] {from_user_name}: {message.text}")
return True
if message.entities:
for entity in message.entities:
if entity.url and in_not_allowed(ALLOWED_WORDS, entity.url):
if entity.url and is_in_not_allowed(ALLOWED_WORDS, entity.url):
logging.info(f"[DELETE] [{title}] [{from_user_id}] {from_user_name}: [entity] {message.text}")
return True
return False
def is_nongrata(type_message: types.Message) -> bool:
"""Check for non grata persons."""
for phrase in NON_GRATA:
if phrase in type_message.text.casefold():
return True
return False
def is_admin(message: types.Message) -> bool:
return message.from_user.id == ADMIN_ID
def is_white(message: types.Message) -> bool:
def is_white_id(message: types.Message) -> bool:
return message.from_user.id in WHITEIDS
+45 -18
View File
@@ -1,14 +1,54 @@
""" Send User's info. """
import logging
import shelve
from pathlib import Path
from urllib import parse
from urllib.error import URLError
from urllib.request import urlopen
from telebot import types
from .constants import DATA
from .report import reset_report_stats
from .constants import SPAM, RUS, BAN_WORDS, NON_GRATA, ADMIN_ID
def is_url_reachable(url: str) -> bool:
try:
return urlopen(url).status == 200
except URLError:
return False
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()):
return True
return False
def is_in_not_allowed(word_list: list, msg: str) -> bool:
for word in word_list:
if word in msg.casefold():
return False
return True
def is_ban_words_in_caption(caption: str) -> bool:
return any(ban_word in caption for ban_word in BAN_WORDS)
def is_nongrata(type_message: types.Message) -> bool:
for phrase in NON_GRATA:
if phrase in type_message.text.casefold():
return True
return False
def is_admin(message: types.Message) -> bool:
return message.from_user.id == ADMIN_ID
def my_ip():
@@ -47,16 +87,3 @@ def detect_args(message: types.Message):
else:
if len(message.text.split()) > 1:
return " ".join(message.text.split()[1:])
def update_stats(message: types.Message):
if not Path(f"{DATA}{message.chat.id}").exists():
reset_report_stats(message.chat.id)
with shelve.open(f"{DATA}{message.chat.id}", writeback=True) as shelve_db:
if "Messages" not in shelve_db:
reset_report_stats(message.chat.id)
if message.from_user.id not in shelve_db["Messages"]:
shelve_db["Messages"][message.from_user.id] = {"User": message.from_user, "Count": 1}
logging.info(f"[{message.chat.title[:10]}] [{message.from_user.id}] {message.from_user.first_name}")
else:
shelve_db["Messages"][message.from_user.id]["Count"] += 1
+17
View File
@@ -1,7 +1,11 @@
import html
import logging
import os
import random
import shelve
from pathlib import Path
from telebot import types
from .config import ROLLBACK
from .constants import DATA
@@ -63,3 +67,16 @@ def reset_report_stats(chat_id):
{shelve_db['Messages']=}
{shelve_db['Banned']=}
{shelve_db['Deleted']=}"""
def update_stats(message: types.Message):
if not Path(f"{DATA}{message.chat.id}").exists():
reset_report_stats(message.chat.id)
with shelve.open(f"{DATA}{message.chat.id}", writeback=True) as shelve_db:
if "Messages" not in shelve_db:
reset_report_stats(message.chat.id)
if message.from_user.id not in shelve_db["Messages"]:
shelve_db["Messages"][message.from_user.id] = {"User": message.from_user, "Count": 1}
logging.info(f"[{message.chat.title[:10]}] [{message.from_user.id}] {message.from_user.first_name}")
else:
shelve_db["Messages"][message.from_user.id]["Count"] += 1
+5 -5
View File
@@ -6,9 +6,9 @@ import random
from sqlalchemy import delete
from telebot import types
from .filters import is_white, is_nongrata
from .models import Quote
from .models import session
from .filters import is_white_id
from .helpers import is_nongrata
from .models import Quote, session
from .robot import bot
TYPING_TIMEOUT = 0.13 / 4 # Reading time is quarter of the same text writing time
@@ -35,7 +35,7 @@ async def act(message: types.Message):
await send_quote(len(quote) * 0.13, message, quote)
@bot.message_handler(func=is_white, commands=["add"])
@bot.message_handler(func=is_white_id, commands=["add"])
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
@@ -48,7 +48,7 @@ async def add_stan_quote(message: types.Message):
await bot.send_message(message.chat.id, f"⛔️ Не добавил, есть токое\n └ {quote}", parse_mode='Markdown')
@bot.message_handler(func=is_white, commands=["remove"])
@bot.message_handler(func=is_white_id, commands=["remove"])
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