From d0cf0762c803b68650cd48898117c7ec04abeea7 Mon Sep 17 00:00:00 2001 From: Rykov7 Date: Wed, 22 Feb 2023 18:53:12 +0300 Subject: [PATCH] format Black --- app/bot.py | 202 +++++++++++++++++++++++++-------------- app/commands/donation.py | 27 ++++-- app/commands/get.py | 8 +- app/commands/service.py | 45 +++++---- app/config.py | 95 ++++++++++++------ app/filters.py | 19 ++-- app/helpers.py | 21 ++-- app/reminder.py | 20 ++-- app/report.py | 45 +++++---- app/rules.py | 6 +- app/stan.py | 69 ++++++++----- holidays.csv | 2 +- wsgi.py | 2 +- 13 files changed, 356 insertions(+), 205 deletions(-) diff --git a/app/bot.py b/app/bot.py index 46a676e..3783304 100644 --- a/app/bot.py +++ b/app/bot.py @@ -14,181 +14,222 @@ from .config import * @bot.edited_message_handler(func=in_spam_list) @bot.message_handler(func=in_spam_list) def moderate_messages(message: types.Message): - """ Ban user and delete their message. """ - logging.warning(f'[BAN] {message.from_user.id} {message.from_user.username} - {message.text}') + """Ban user and delete their message.""" + logging.warning( + f"[BAN] {message.from_user.id} {message.from_user.username} - {message.text}" + ) bot.delete_message(message.chat.id, message.id) bot.ban_chat_member(message.chat.id, message.from_user.id) - with shelve.open(f'{DATA}{message.chat.id}') as s: - s['Banned'] += 1 + with shelve.open(f"{DATA}{message.chat.id}") as s: + s["Banned"] += 1 -@bot.message_handler(func=in_caption_spam_list, content_types=['video']) +@bot.message_handler(func=in_caption_spam_list, content_types=["video"]) def catch_videos(message: types.Message): """Catch offensive videos""" - logging.warning(f'[BAN] {message.from_user.id} {message.from_user.first_name} - {message.video.file_name}') + logging.warning( + f"[BAN] {message.from_user.id} {message.from_user.first_name} - {message.video.file_name}" + ) bot.delete_message(message.chat.id, message.id) bot.ban_chat_member(message.chat.id, message.from_user.id) - with shelve.open(f'{DATA}{message.chat.id}') as s: - s['Banned'] += 1 + with shelve.open(f"{DATA}{message.chat.id}") as s: + s["Banned"] += 1 @bot.edited_message_handler(func=in_delete_list) @bot.message_handler(func=in_delete_list) def delete_message(message: types.Message): - """ Delete unwanted message. """ + """Delete unwanted message.""" bot.delete_message(message.chat.id, message.id) - with shelve.open(f'{DATA}{message.chat.id}') as s: - s['Deleted'] += 1 + with shelve.open(f"{DATA}{message.chat.id}") as s: + s["Deleted"] += 1 """ [ COMMANDS ] """ -@bot.message_handler(commands=['start', 'links', 'ссылки']) +@bot.message_handler(commands=["start", "links", "ссылки"]) def start(message: types.Message): - """ What to begin with. """ - log_msg = f'[START] {message.from_user.id} {message.from_user.first_name}' + """What to begin with.""" + log_msg = f"[START] {message.from_user.id} {message.from_user.first_name}" logging.warning(log_msg) markup = types.InlineKeyboardMarkup([[RULES], [FAQ], [LIB]], 1) send_or_reply(message, "Начни с прочтения", reply_markup=markup) -@bot.message_handler(commands=['rules', 'rule', 'r', 'правила', 'правило', 'п']) +@bot.message_handler(commands=["rules", "rule", "r", "правила", "правило", "п"]) def send_rules(message): markup = types.InlineKeyboardMarkup([[RULES]], 1) args = message.text.split() if len(args) > 1 and args[-1].isdigit() and 0 < int(args[-1]): - send_or_reply(message, f'Правило {args[-1]}\n{rules.fetch_rule(args[-1])}', reply_markup=markup) + send_or_reply( + message, + f"Правило {args[-1]}\n{rules.fetch_rule(args[-1])}", + reply_markup=markup, + ) else: - send_or_reply(message, '...', reply_markup=markup) + send_or_reply(message, "...", reply_markup=markup) -@bot.message_handler(commands=['faq', 'чзв']) +@bot.message_handler(commands=["faq", "чзв"]) def send_faq(message): markup = types.InlineKeyboardMarkup([[FAQ]], 1) - send_or_reply(message, '...', reply_markup=markup) + send_or_reply(message, "...", reply_markup=markup) -@bot.message_handler(commands=['lib', 'library', 'books', 'книги', 'библиотека']) +@bot.message_handler(commands=["lib", "library", "books", "книги", "библиотека"]) def send_lib(message): markup = types.InlineKeyboardMarkup([[LIB]], 1) - send_or_reply(message, '...', reply_markup=markup) + send_or_reply(message, "...", reply_markup=markup) -@bot.message_handler(commands=['lutz', 'лутц']) +@bot.message_handler(commands=["lutz", "лутц"]) def send_lutz(message): - bot.send_document(message.chat.id, - document='BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA', - caption="вот, не позорься") + bot.send_document( + message.chat.id, + document="BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA", + caption="вот, не позорься", + ) -@bot.message_handler(commands=['bdmtss', 'бдмтсс']) +@bot.message_handler(commands=["bdmtss", "бдмтсс"]) def send_bdmtss_audio(message): - bot.send_voice(message.chat.id, 'AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ') + bot.send_voice( + message.chat.id, + "AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ", + ) -@bot.message_handler(commands=['tr', 'тр']) +@bot.message_handler(commands=["tr", "тр"]) def translate_layout(message): if message.reply_to_message and message.reply_to_message.text: if message.reply_to_message.text[0] in RUS: - bot.send_message(message.chat.id, message.reply_to_message.text.translate(RUS_ENG_TABLE)) + bot.send_message( + message.chat.id, message.reply_to_message.text.translate(RUS_ENG_TABLE) + ) else: - bot.send_message(message.chat.id, message.reply_to_message.text.translate(ENG_RUS_TABLE)) + bot.send_message( + message.chat.id, message.reply_to_message.text.translate(ENG_RUS_TABLE) + ) -@bot.message_handler(commands=['quote', 'цитата']) +@bot.message_handler(commands=["quote", "цитата"]) def stan_speak(message): bot.send_message(message.chat.id, stan.speak(0)) -@bot.message_handler(commands=['tsya', 'тся', 'ться']) +@bot.message_handler(commands=["tsya", "тся", "ться"]) def send_tsya(message: types.Message): markup = types.InlineKeyboardMarkup() - markup.add(types.InlineKeyboardButton('🧑🏼‍🎓 Читать правило', url='https://tsya.ru/'), row_width=1) - send_or_reply(message, '-тся и -ться в глаголах', reply_markup=markup) + markup.add( + types.InlineKeyboardButton("🧑🏼‍🎓 Читать правило", url="https://tsya.ru/"), + row_width=1, + ) + send_or_reply(message, "-тся и -ться в глаголах", reply_markup=markup) -@bot.message_handler(commands=['nometa', 'номета']) +@bot.message_handler(commands=["nometa", "номета"]) def send_nometa(message: types.Message): markup = types.InlineKeyboardMarkup() - markup.add(types.InlineKeyboardButton('❓ nometa.xyz', url='https://nometa.xyz/ru.html'), row_width=1) - send_or_reply(message, """Не задавай мета-вопросов вроде: + markup.add( + types.InlineKeyboardButton("❓ nometa.xyz", url="https://nometa.xyz/ru.html"), + row_width=1, + ) + send_or_reply( + message, + """Не задавай мета-вопросов вроде: «Можно задать вопрос?» «Кто-нибудь пользовался .. ?» «Привет, мне нужна помощь по .. !» -Просто спроси сразу! И чем лучше объяснишь проблему, тем вероятнее получишь помощь.""", reply_markup=markup) +Просто спроси сразу! И чем лучше объяснишь проблему, тем вероятнее получишь помощь.""", + reply_markup=markup, + ) -@bot.message_handler(commands=['neprivet', 'непривет']) +@bot.message_handler(commands=["neprivet", "непривет"]) def send_neprivet(message: types.Message): markup = types.InlineKeyboardMarkup() - markup.add(types.InlineKeyboardButton('👋 Непривет', url='https://neprivet.com/'), row_width=1) - send_or_reply(message, 'Пожалуйста, не пишите просто «Привет» в чате.', reply_markup=markup) + markup.add( + types.InlineKeyboardButton("👋 Непривет", url="https://neprivet.com/"), + row_width=1, + ) + send_or_reply( + message, "Пожалуйста, не пишите просто «Привет» в чате.", reply_markup=markup + ) -@bot.message_handler(commands=['nojob', 'ноджоб']) +@bot.message_handler(commands=["nojob", "ноджоб"]) def send_nojob(message): - logging.warning('Sent no job') + logging.warning("Sent no job") answer = """Мы здесь не для того, чтобы за тебя решать задачи. -Здесь помогают по конкретным вопросам в ТВОЁМ коде, поэтому тебе нужно показать код, который ты написал сам и объяснить где и почему застрял... всё просто. 🤷🏼️""" +Здесь помогают по конкретным вопросам в ТВОЁМ коде, поэтому тебе нужно показать код, который ты написал сам и \ +объяснить где и почему застрял... всё просто. 🤷🏼️""" send_or_reply(message, answer) -@bot.message_handler(commands=['nobot', 'нобот']) +@bot.message_handler(commands=["nobot", "нобот"]) def nobot(message: types.Message): answer = """Внимание: -Телеграм бот не должен быть твоим первым проектом на Python. Пожалуйста, изучи основы Python, работу с модулями, основы веб-технологий, асинхронное программирование и отладку до начала работы с Телеграм ботами. Существует много ресурсов для этого в интернете.""" +Телеграм бот не должен быть твоим первым проектом на Python. Пожалуйста, изучи основы Python, \ +работу с модулями, основы веб-технологий, асинхронное программирование и \ +отладку до начала работы с Телеграм ботами. Существует много ресурсов для этого в интернете.""" send_or_reply(message, answer) -@bot.message_handler(commands=['nogui', 'ногуи']) +@bot.message_handler(commands=["nogui", "ногуи"]) def nogui(message: types.Message): answer = """Внимание: -GUI приложение не должно быть твоим первым проектом на Python. Пожалуйста, изучи основы Python, работу с модулями, циклы событий и отладку до начала работы с какими-либо GUI-фреймворками. Существует много ресурсов для этого в интернете.""" +GUI приложение не должно быть твоим первым проектом на Python. Пожалуйста, изучи основы Python, \ +работу с модулями, циклы событий и отладку до начала работы с какими-либо \ +GUI-фреймворками. Существует много ресурсов для этого в интернете.""" send_or_reply(message, answer) -@bot.message_handler(commands=['g', 'г']) +@bot.message_handler(commands=["g", "г"]) def google_it(message: types.Message): - """ Google it! """ - query = f'{detect_args(message)}' - get_query = 'https://www.google.com/search?q=' + represent_as_get(message) + """Google it!""" + query = f"{detect_args(message)}" + get_query = "https://www.google.com/search?q=" + represent_as_get(message) markup = types.InlineKeyboardMarkup() - markup.add(types.InlineKeyboardButton('🔍 Google Поиск', url=get_query), row_width=1) - send_or_reply(message, f'Ищем «{query}»...', reply_markup=markup) + markup.add(types.InlineKeyboardButton("🔍 Google Поиск", url=get_query), row_width=1) + send_or_reply(message, f"Ищем «{query}»...", reply_markup=markup) """ [ ADMIN PANEL ] """ -@bot.message_handler(func=is_admin, commands=['ddel']) +@bot.message_handler(func=is_admin, commands=["ddel"]) def delete_user(message: types.Message): if message.reply_to_message: bot.delete_message(message.chat.id, message.id) bot.delete_message(message.chat.id, message.reply_to_message.id) logging.warning( - f'[DEL (M)] {message.reply_to_message.from_user.id} {message.reply_to_message.from_user.first_name} - {message.reply_to_message.text}') + f"[DEL (M)] {message.reply_to_message.from_user.id} {message.reply_to_message.from_user.first_name} - \ + {message.reply_to_message.text}" + ) -@bot.message_handler(func=is_admin, commands=['bban']) +@bot.message_handler(func=is_admin, commands=["bban"]) def ban_user(message: types.Message): if message.reply_to_message: bot.delete_message(message.chat.id, message.id) bot.delete_message(message.chat.id, message.reply_to_message.id) bot.ban_chat_member(message.chat.id, message.reply_to_message.from_user.id) logging.warning( - f'[BAN (M)] {message.reply_to_message.from_user.id} {message.reply_to_message.from_user.first_name} - {message.reply_to_message.text}') + f"[BAN (M)] {message.reply_to_message.from_user.id} {message.reply_to_message.from_user.first_name} - \ + {message.reply_to_message.text}" + ) -@bot.message_handler(func=is_admin, commands=['unban_id']) +@bot.message_handler(func=is_admin, commands=["unban_id"]) def unban_user(message: types.Message): if message.text.split()[-1].isdigit(): user_id = int(message.text.split()[-1]) bot.unban_chat_member(PYTHONCHATRU, user_id) - logging.warning(f'[UNBAN (M)] {user_id}') + logging.warning(f"[UNBAN (M)] {user_id}") """ [ INLINE ] """ @@ -196,14 +237,19 @@ def unban_user(message: types.Message): @bot.inline_handler(lambda query: True) def default_query(inline_query): - """ Inline the Zen of Python. """ + """Inline the Zen of Python.""" zen = [] for id_p, phrase in enumerate(ZEN): q = inline_query.query.casefold() - if phrase.casefold().startswith(q) or ' ' + q in phrase.casefold(): - zen.append(types.InlineQueryResultArticle( - f"{id_p}", f'The Zen of Python #{id_p + 1}', types.InputTextMessageContent( - f"{phrase}"), description=phrase)) + if phrase.casefold().startswith(q) or " " + q in phrase.casefold(): + zen.append( + types.InlineQueryResultArticle( + f"{id_p}", + f"The Zen of Python #{id_p + 1}", + types.InputTextMessageContent(f"{phrase}"), + description=phrase, + ) + ) bot.answer_inline_query(inline_query.id, zen, cache_time=1200) @@ -211,10 +257,20 @@ def default_query(inline_query): """ [ COUNTER ] """ -@bot.message_handler(content_types=['text', 'sticker', 'photo', 'animation', 'video', 'audio', 'document'], - chat_types=['supergroup', 'group']) +@bot.message_handler( + content_types=[ + "text", + "sticker", + "photo", + "animation", + "video", + "audio", + "document", + ], + chat_types=["supergroup", "group"], +) def handle_msg(message: types.Message): - """ Count messages, Stan. """ + """Count messages, Stan.""" update_stats(message) stan.act(message) @@ -222,13 +278,13 @@ def handle_msg(message: types.Message): """ [ WEBHOOK ] """ -@app.route(f"/bot{TOKEN}/", methods=['POST']) +@app.route(f"/bot{TOKEN}/", methods=["POST"]) def webhook(): - """ Parse POST requests from Telegram. """ - if request.headers.get('content-type') == 'application/json': - json_string = request.get_data().decode('utf-8') + """Parse POST requests from Telegram.""" + if request.headers.get("content-type") == "application/json": + json_string = request.get_data().decode("utf-8") update = types.Update.de_json(json_string) bot.process_new_updates([update]) - return '' + return "" else: abort(403) diff --git a/app/commands/donation.py b/app/commands/donation.py index f90181f..d25a2f8 100644 --- a/app/commands/donation.py +++ b/app/commands/donation.py @@ -1,19 +1,28 @@ from telebot.types import LabeledPrice, Message, PreCheckoutQuery from ..config import YOOPAY, bot -prices = [LabeledPrice('Сумма', 100_00)] +prices = [LabeledPrice("Сумма", 100_00)] -@bot.message_handler(commands=['donate']) +@bot.message_handler(commands=["donate"]) def request_invoice(message: Message): - bot.send_invoice(message.chat.id, 'Поддержать проект', 'Stan', 'donate_stan', provider_token=YOOPAY, - currency='RUB', prices=prices, - provider_data='{"capture": true}', - max_tip_amount=500_000_00, - suggested_tip_amounts=[150_00, 300_00, 500_00, 1_000_00], capture=True, - ) + bot.send_invoice( + message.chat.id, + "Поддержать проект", + "Stan", + "donate_stan", + provider_token=YOOPAY, + currency="RUB", + prices=prices, + provider_data='{"capture": true}', + max_tip_amount=500_000_00, + suggested_tip_amounts=[150_00, 300_00, 500_00, 1_000_00], + capture=True, + ) @bot.pre_checkout_query_handler(func=lambda a: True) def process_pre_checkout(q: PreCheckoutQuery): - bot.answer_pre_checkout_query(q.id, True, 'Извините, пожертвования больше не принимаем!') + bot.answer_pre_checkout_query( + q.id, True, "Извините, пожертвования больше не принимаем!" + ) diff --git a/app/commands/get.py b/app/commands/get.py index cf5c8f7..415fa1c 100644 --- a/app/commands/get.py +++ b/app/commands/get.py @@ -2,9 +2,11 @@ from urllib.request import urlopen def my_ip(): - ip_service = 'https://icanhazip.com' - ip = urlopen(ip_service, ) - return ip.read().decode('utf-8') + ip_service = "https://icanhazip.com" + ip = urlopen( + ip_service, + ) + return ip.read().decode("utf-8") def me(message): diff --git a/app/commands/service.py b/app/commands/service.py index 7f817c9..03b3806 100644 --- a/app/commands/service.py +++ b/app/commands/service.py @@ -10,20 +10,20 @@ from ..filters import is_admin from .get import me, my_ip -@bot.message_handler(commands=['me']) +@bot.message_handler(commands=["me"]) def command_me(message): - """ Send info about user and chat id [Service]. """ + """Send info about user and chat id [Service].""" bot.send_message(message.chat.id, me(message)) -@bot.message_handler(func=is_admin, commands=['ip']) +@bot.message_handler(func=is_admin, commands=["ip"]) def get_ip(message): bot.send_message(message.chat.id, my_ip()) -@bot.message_handler(commands=['remind']) +@bot.message_handler(commands=["remind"]) def remind_manually(message): - """ Remind holidays manually. """ + """Remind holidays manually.""" args = message.text.split() if len(args) > 1: try: @@ -33,38 +33,45 @@ def remind_manually(message): else: reminder.remind(message.chat.id, today) else: - bot.send_message(message.chat.id, f"Формат даты: MM-DD-YYYY\n\n" - f"Примеры:\n" - f"/remind 09-12-2024\n" - f"/remind 09-13-2022") + bot.send_message( + message.chat.id, + f"Формат даты: MM-DD-YYYY\n\n" + f"Примеры:\n" + f"/remind 09-12-2024\n" + f"/remind 09-13-2022", + ) -@bot.message_handler(func=is_admin, commands=['jobs']) +@bot.message_handler(func=is_admin, commands=["jobs"]) def list_jobs(message): - """ List all the jobs in schedule. """ + """List all the jobs in schedule.""" bot.send_message(ADMIN_ID, reminder.print_get_jobs()) -@bot.message_handler(func=is_admin, commands=['stats']) +@bot.message_handler(func=is_admin, commands=["stats"]) def send_stats(message: types.Message): if len(message.text.split()) == 1: rep = report.create_report_text(message.chat.id) if rep: bot.send_message(message.chat.id, rep) else: - bot.send_message(message.chat.id, report.create_report_text(message.text.split()[-1])) + bot.send_message( + message.chat.id, report.create_report_text(message.text.split()[-1]) + ) -@bot.message_handler(func=is_admin, commands=['reset_stats'], chat_types=['supergroup', 'group']) +@bot.message_handler( + func=is_admin, commands=["reset_stats"], chat_types=["supergroup", "group"] +) def send_stats(message: types.Message): - logging.warning('reset_stats') + logging.warning("reset_stats") report.reset_report_stats(message.chat.id) bot.send_message(message.chat.id, report.reset_report_stats(message.chat.id)) -@bot.message_handler(func=is_admin, commands=['reload']) +@bot.message_handler(func=is_admin, commands=["reload"]) def send_stats(message): - logging.warning('Reloading...') + logging.warning("Reloading...") reloader.reload_modules() - logging.warning('Reloaded!!!') - bot.send_message(message.chat.id, 'Reloaded successfully') + logging.warning("Reloaded!!!") + bot.send_message(message.chat.id, "Reloaded successfully") diff --git a/app/config.py b/app/config.py index f0a8c2d..9dcecd9 100644 --- a/app/config.py +++ b/app/config.py @@ -5,54 +5,89 @@ from flask import Flask from telebot import TeleBot, logger, types from dotenv import load_dotenv -logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%Y.%m.%d %H:%M:%S') +logging.basicConfig( + level=logging.INFO, format="%(asctime)s %(message)s", datefmt="%Y.%m.%d %H:%M:%S" +) logger.setLevel(logging.INFO) -logging.critical('STAN STARTED!') +logging.critical("STAN STARTED!") load_dotenv() -TOKEN = os.environ.get('LUTZPYBOT', 'Token not in ENVIRON') -YOOPAY = os.environ.get('YOOKASSA') -bot = TeleBot(TOKEN, 'HTML', disable_web_page_preview=True, allow_sending_without_reply=True, - colorful_logs=True) +TOKEN = os.environ.get("LUTZPYBOT", "Token not in ENVIRON") +YOOPAY = os.environ.get("YOOKASSA") +bot = TeleBot( + TOKEN, + "HTML", + disable_web_page_preview=True, + allow_sending_without_reply=True, + colorful_logs=True, +) app = Flask(__name__) -DATA = 'data/chat' +DATA = "data/chat" ADMIN_ID = 280887861 # Rykov7 PYTHONCHATRU = -1001338616632 # pythonchatru -URL_RX = re.compile(r'\w+\.\w+/\w+') -ALLOWED_WORDS = ['paste', 'nekobin', 'github', 'google', 'nometa', 'python', 'django', 'flask', 'fastapi', 'wiki', - 'stackoverflow', 'habr', 'medium', 'youtu', 'stepik', 'telegra', '#rtfm', 'support', - 'jetbrains', ] +URL_RX = re.compile(r"\w+\.\w+/\w+") +ALLOWED_WORDS = [ + "paste", + "nekobin", + "github", + "google", + "nometa", + "python", + "django", + "flask", + "fastapi", + "wiki", + "stackoverflow", + "habr", + "medium", + "youtu", + "stepik", + "telegra", + "#rtfm", + "support", + "jetbrains", +] -WHITEIDS = {int(i) for i in os.environ.get('whiteids').split(',')} -ROLLBACK = {int(i) for i in os.environ.get('rollback').split(',')} +WHITEIDS = {int(i) for i in os.environ.get("whiteids").split(",")} +ROLLBACK = {int(i) for i in os.environ.get("rollback").split(",")} RUS = """ёйцукенгшщзхъфывапролджэячсмитьбю.Ё!"№;%:?ЙЦУКЕНГШЩЗХЪ/ФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,""" ENG = """`qwertyuiop[]asdfghjkl;'zxcvbnm,./~!@#$%^&QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?""" RUS_ENG_TABLE = str.maketrans(RUS, ENG) ENG_RUS_TABLE = str.maketrans(ENG, RUS) -RULES = types.InlineKeyboardButton('🟡 Правила чата', url='https://telegra.ph/pythonchatru-07-07') -FAQ = types.InlineKeyboardButton('🔵 Частые вопросы', url='https://telegra.ph/faq-10-07-4') -LIB = types.InlineKeyboardButton('📚 Книги', url='https://telegra.ph/what-to-read-10-06') +RULES = types.InlineKeyboardButton( + "🟡 Правила чата", url="https://telegra.ph/pythonchatru-07-07" +) +FAQ = types.InlineKeyboardButton( + "🔵 Частые вопросы", url="https://telegra.ph/faq-10-07-4" +) +LIB = types.InlineKeyboardButton("📚 Книги", url="https://telegra.ph/what-to-read-10-06") -SPAM = ['me.sv/', 'tg.sv/', 'goo.by/', 'go.sv/', 'intim.video/', 'uclck.ru/'] -NON_GRATA = ['дудар', 'хауди', 'dudar'] -BAN_WORDS = ['GREEN'] +SPAM = ["me.sv/", "tg.sv/", "goo.by/", "go.sv/", "intim.video/", "uclck.ru/"] +NON_GRATA = ["дудар", "хауди", "dudar"] +BAN_WORDS = ["GREEN"] -ZEN = ['Beautiful is better than ugly.', 'Explicit is better than implicit.', 'Simple is better than complex.', - 'Complex is better than complicated.', 'Flat is better than nested.', 'Sparse is better than dense.', - 'Readability counts.', - "Special cases aren't special enough to break the rules. Although practicality beats purity.", - 'Errors should never pass silently. Unless explicitly silenced.', - 'In the face of ambiguity, refuse the temptation to guess.', - 'There should be one — and preferably only one — obvious way to do it.', - 'Now is better than never. Although never is often better than *right* now.', - "If the implementation is hard to explain, it's a bad idea.", - '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!"] +ZEN = [ + "Beautiful is better than ugly.", + "Explicit is better than implicit.", + "Simple is better than complex.", + "Complex is better than complicated.", + "Flat is better than nested.", + "Sparse is better than dense.", + "Readability counts.", + "Special cases aren't special enough to break the rules. Although practicality beats purity.", + "Errors should never pass silently. Unless explicitly silenced.", + "In the face of ambiguity, refuse the temptation to guess.", + "There should be one — and preferably only one — obvious way to do it.", + "Now is better than never. Although never is often better than *right* now.", + "If the implementation is hard to explain, it's a bad idea.", + "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!", +] diff --git a/app/filters.py b/app/filters.py index bb8d738..7343d50 100644 --- a/app/filters.py +++ b/app/filters.py @@ -2,7 +2,7 @@ from .config import * def in_spam_list(message: types.Message) -> bool: - """ Check for mentioning unwanted persons in text. """ + """Check for mentioning unwanted persons in text.""" if message.from_user.id not in WHITEIDS: for url in SPAM: if url in message.text.casefold(): @@ -10,7 +10,7 @@ def in_spam_list(message: types.Message) -> bool: def in_caption_spam_list(type_message: types.Message) -> bool: - """ Check for mentioning unwanted words in caption. """ + """Check for mentioning unwanted words in caption.""" for phrase in BAN_WORDS: if type_message.caption and phrase in type_message.caption: return True @@ -24,21 +24,26 @@ def in_not_allowed(word_list, msg): def in_delete_list(type_message: types.Message) -> bool: - """ Check for URLs in message and delete. """ + """Check for URLs in message and delete.""" if type_message.from_user.id not in WHITEIDS: - if URL_RX.search(type_message.text) and in_not_allowed(ALLOWED_WORDS, type_message.text): - logging.info(f'[DEL] {type_message.from_user.id} {type_message.from_user.first_name} - {type_message.text}') + if URL_RX.search(type_message.text) and in_not_allowed( + ALLOWED_WORDS, type_message.text + ): + logging.info( + f"[DEL] {type_message.from_user.id} {type_message.from_user.first_name} - {type_message.text}" + ) return True if type_message.entities: for entity in type_message.entities: if entity.url and in_not_allowed(ALLOWED_WORDS, entity.url): logging.info( - f'[DEL] {type_message.from_user.id} {type_message.from_user.first_name} - Entity ({entity.url})') + f"[DEL] {type_message.from_user.id} {type_message.from_user.first_name} - Entity ({entity.url})" + ) return True def is_nongrata(type_message: types.Message) -> bool: - """ Check for non grata persons. """ + """Check for non grata persons.""" for phrase in NON_GRATA: if phrase in type_message.text.casefold(): return True diff --git a/app/helpers.py b/app/helpers.py index bad9008..a00d136 100644 --- a/app/helpers.py +++ b/app/helpers.py @@ -16,19 +16,24 @@ def detect_args(message: types.Message): if len(message.text.split()) == 1: return message.reply_to_message.text else: - return ' '.join(message.text.split()[1:]) + return " ".join(message.text.split()[1:]) else: if len(message.text.split()) > 1: - return ' '.join(message.text.split()[1:]) + return " ".join(message.text.split()[1:]) def update_stats(message: types.Message): - with shelve.open(f'{DATA}{message.chat.id}', writeback=True) as s: - if 'Messages' not in s: + with shelve.open(f"{DATA}{message.chat.id}", writeback=True) as s: + if "Messages" not in s: report.reset_report_stats(message.chat.id) - if message.from_user.id not in s['Messages']: - s['Messages'][message.from_user.id] = {'User': message.from_user, 'Count': 1} - logging.warning(f'CNTR {message.chat.id}: {message.from_user.first_name} ({message.from_user.id})') + if message.from_user.id not in s["Messages"]: + s["Messages"][message.from_user.id] = { + "User": message.from_user, + "Count": 1, + } + logging.warning( + f"CNTR {message.chat.id}: {message.from_user.first_name} ({message.from_user.id})" + ) else: - s['Messages'][message.from_user.id]['Count'] += 1 + s["Messages"][message.from_user.id]["Count"] += 1 diff --git a/app/reminder.py b/app/reminder.py index 9f03c5d..e6c4851 100644 --- a/app/reminder.py +++ b/app/reminder.py @@ -15,28 +15,28 @@ def scheduler(): time.sleep(300) -@repeat(every().day.at('07:00'), PYTHONCHATRU, None) +@repeat(every().day.at("07:00"), PYTHONCHATRU, None) def remind(chat_to_repeat, today): - """ Remind holiday. """ + """Remind holiday.""" if not today: today = dt.today() - with open('holidays.csv', newline='', encoding='utf-8') as holidays_file: + with open("holidays.csv", newline="", encoding="utf-8") as holidays_file: holidays = tuple(csv.reader(holidays_file))[1:] for entry in holidays: date, holiday, description = entry - if today.year % 4 == 0 and holiday == 'День программиста': - date = '09-12-1000' # instead of 09-13-1000 in non-leap-year + if today.year % 4 == 0 and holiday == "День программиста": + date = "09-12-1000" # instead of 09-13-1000 in non-leap-year date = dt.strptime(date, "%m-%d-%Y") if today.month == date.month and today.day == date.day: - notification = f'🎉 Сегодня {holiday.upper()}!\ - \n\n{description}.' + notification = f"🎉 Сегодня {holiday.upper()}!\ + \n\n{description}." if date.year != 1000: age = today.year - date.year - notification += f'\n\n🥳 {age}-ая годовщина' + notification += f"\n\n🥳 {age}-ая годовщина" bot.send_message(chat_to_repeat, notification) -@repeat(every().day.at('06:00'), PYTHONCHATRU) +@repeat(every().day.at("06:00"), PYTHONCHATRU) def stat_report(chat_to_repeat): rep = report.create_report_text(PYTHONCHATRU) if rep: @@ -48,7 +48,7 @@ def print_get_jobs(): all_jobs = get_jobs() text = f"├ Jobs: {str(len(all_jobs))}\ \n├ {dt.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n" - text += '' + str(all_jobs) + '' + text += "" + str(all_jobs) + "" return text diff --git a/app/report.py b/app/report.py index ac93c5d..9b9ccbb 100644 --- a/app/report.py +++ b/app/report.py @@ -4,31 +4,40 @@ from .config import DATA, ROLLBACK def create_report_text(chat_id): - report = '' - top_users = '' + report = "" + top_users = "" flooders = [] - if os.path.exists(f'{DATA}{chat_id}.db'): - with shelve.open(f'{DATA}{chat_id}', writeback=True) as s: + if os.path.exists(f"{DATA}{chat_id}.db"): + with shelve.open(f"{DATA}{chat_id}", writeback=True) as s: for user_id in ROLLBACK: - if user_id in s['Messages'] and s['Messages'][user_id]['Count'] > 10: - s['Messages'][user_id]['Count'] //= 3 + if user_id in s["Messages"] and s["Messages"][user_id]["Count"] > 10: + s["Messages"][user_id]["Count"] //= 3 - for n in range(min(3, len(s['Messages']))): - top_user = s['Messages'][ - sorted(s['Messages'], key=lambda a: s['Messages'][a]['Count'], reverse=True)[n]] - if top_user['Count'] >= 5: + for n in range(min(3, len(s["Messages"]))): + top_user = s["Messages"][ + sorted( + s["Messages"], + key=lambda a: s["Messages"][a]["Count"], + reverse=True, + )[n] + ] + if top_user["Count"] >= 5: flooders.append(top_user) for i, flooder in enumerate(flooders): user = flooder["User"] - name = f"{user.first_name} {user.last_name}" if user.last_name else user.first_name + name = ( + f"{user.first_name} {user.last_name}" + if user.last_name + else user.first_name + ) top_users += f'\n {i + 1}. {name} [{flooder["Count"]}]' - if len(flooders) >= 3 or s['Banned'] or s['Deleted']: + if len(flooders) >= 3 or s["Banned"] or s["Deleted"]: report = f"Hello, World!\n" if len(flooders) >= 3: report += f"\nТоп 🐍{top_users}\n" - if s['Banned'] or s['Deleted']: + if s["Banned"] or s["Deleted"]: report += f""" Заблокировано ├ Пользователей: {s['Banned']} @@ -36,14 +45,14 @@ def create_report_text(chat_id): """ return report else: - return f'Невозможно получить статистику.\n{DATA}{chat_id}.db не существует, возможно запрос в приватном чате. ' + return f"Невозможно получить статистику.\n{DATA}{chat_id}.db не существует, возможно запрос в приватном чате. " def reset_report_stats(chat_id): - with shelve.open(f'{DATA}{chat_id}') as s: - s['Messages'] = {} - s['Banned'] = 0 - s['Deleted'] = 0 + with shelve.open(f"{DATA}{chat_id}") as s: + s["Messages"] = {} + s["Banned"] = 0 + s["Deleted"] = 0 return f"""Chat ID: {chat_id} {s['Messages']=} diff --git a/app/rules.py b/app/rules.py index 0055a4c..6a34b94 100644 --- a/app/rules.py +++ b/app/rules.py @@ -1,13 +1,13 @@ from bs4 import BeautifulSoup from urllib.request import urlopen -html = BeautifulSoup(urlopen('https://telegra.ph/pythonchatru-07-07'), 'lxml') +html = BeautifulSoup(urlopen("https://telegra.ph/pythonchatru-07-07"), "lxml") def fetch_rule(li): li = int(li) - lis = html.find_all('li') + lis = html.find_all("li") if li <= len(lis): return lis[li - 1].text else: - return f'Пока не придумали.' + return f"Пока не придумали." diff --git a/app/stan.py b/app/stan.py index 6640008..223da9c 100644 --- a/app/stan.py +++ b/app/stan.py @@ -9,14 +9,18 @@ from .filters import is_white, is_nongrata def speak(chance_of): number = random.randint(0, chance_of) if number == 0: - return random.choice([i.rstrip() for i in open('Stan.txt', 'r', encoding='utf8') if i]) + return random.choice( + [i.rstrip() for i in open("Stan.txt", "r", encoding="utf8") if i] + ) def send_quote(after_sec, message, quote): - """ Pretend Reading, pretend Typing, send. """ + """Pretend Reading, pretend Typing, send.""" if message.text: - sleep(len(message.text) * 0.13 / 4) # Reading time is quarter of the same text writing time - bot.send_chat_action(message.chat.id, action='typing') + sleep( + len(message.text) * 0.13 / 4 + ) # Reading time is quarter of the same text writing time + bot.send_chat_action(message.chat.id, action="typing") sleep(after_sec) # Typing time bot.send_message(message.chat.id, quote) @@ -24,37 +28,56 @@ def send_quote(after_sec, message, quote): def act(message): quote = speak(50) if quote: - threading.Thread(target=send_quote, args=(len(quote) * 0.13, message, quote)).start() + threading.Thread( + target=send_quote, args=(len(quote) * 0.13, message, quote) + ).start() -@bot.message_handler(func=is_white, commands=['add']) +@bot.message_handler(func=is_white, commands=["add"]) def add_stan_quote(message): if message.reply_to_message and message.reply_to_message.text: - with open('Stan.txt', 'a', encoding='utf8') as stan_quotes: - if message.reply_to_message.text not in (i.rstrip() for i in open('Stan.txt', 'r', encoding='utf8')): - stan_quotes.write(message.reply_to_message.text.replace('\n', ' ') + '\n') - bot.send_message(message.chat.id, - '✅ Добавил\n └ ' + message.reply_to_message.text.replace("\n", - " ") + '') + with open("Stan.txt", "a", encoding="utf8") as stan_quotes: + if message.reply_to_message.text not in ( + i.rstrip() for i in open("Stan.txt", "r", encoding="utf8") + ): + stan_quotes.write( + message.reply_to_message.text.replace("\n", " ") + "\n" + ) + bot.send_message( + message.chat.id, + "✅ Добавил\n └ " + + message.reply_to_message.text.replace("\n", " ") + + "", + ) else: - bot.send_message(message.chat.id, - f'⛔️ Не добавил, есть токое\n └ {message.reply_to_message.text}') + bot.send_message( + message.chat.id, + f"⛔️ Не добавил, есть токое\n └ {message.reply_to_message.text}", + ) -@bot.message_handler(func=is_white, commands=['remove']) +@bot.message_handler(func=is_white, commands=["remove"]) def remove_stan_quote(message): if message.reply_to_message and message.reply_to_message.text: - if message.reply_to_message.text in (i.rstrip() for i in open('Stan.txt', 'r', encoding='utf8')): - quotes = list(open('Stan.txt', 'r', encoding='utf8')) - with open('Stan.txt', 'w', encoding='utf8') as stan_quotes: - quotes.remove(message.reply_to_message.text + '\n') + if message.reply_to_message.text in ( + i.rstrip() for i in open("Stan.txt", "r", encoding="utf8") + ): + quotes = list(open("Stan.txt", "r", encoding="utf8")) + with open("Stan.txt", "w", encoding="utf8") as stan_quotes: + quotes.remove(message.reply_to_message.text + "\n") stan_quotes.writelines(quotes) - bot.send_message(message.chat.id, f'✅ Удалил\n └ {message.reply_to_message.text}') + bot.send_message( + message.chat.id, + f"✅ Удалил\n └ {message.reply_to_message.text}", + ) else: - bot.send_message(message.chat.id, f'⛔️ Нет такого\n └ {message.reply_to_message.text}') + bot.send_message( + message.chat.id, + f"⛔️ Нет такого\n └ {message.reply_to_message.text}", + ) @bot.message_handler(func=is_nongrata) def tease_nongrata(message: types.Message): - """ Reply to non grata mentions. """ - bot.reply_to(message, f'у нас тут таких не любят') + """Reply to non grata mentions.""" + bot.reply_to(message, f"у нас тут таких не любят") diff --git a/holidays.csv b/holidays.csv index 83178cb..a35e29b 100644 --- a/holidays.csv +++ b/holidays.csv @@ -1,7 +1,7 @@ "Date (mm-dd-yyyy)","Name","Description" "02-20-1991","День рождения Python","Задумка по реализации языка появилась в конце 1980-х годов, а разработка его реализации началась в 1989 году сотрудником голландского института CWI Гвидо ван Россумом" "04-01-2010","День рождения Flask","Flask — фреймворк для создания веб-приложений на языке программирования Python. Создатель и основной автор — австрийский программист Армин Ронахер" -"04-04-1000","День веб-мастера","4 апреля — «404» — отмечают свой профессиональный праздник неутомимые веб-мастера и интернет-разработчики" +"04-04-1000","День веб-разработчика","4 апреля — «404» — отмечают свой профессиональный праздник веб-разработчики" "04-07-1994","День рождения Рунета","7 апреля 1994 года для России был зарегистрирован домен — .Ru — и внесен в международную базу данных национальных доменов верхнего уровня" "07-21-2005","День рождения Django","Джанго — свободный фреймворк для веб-приложений на языке Python. Авторы: американский веб-разработчик Адриан Головатый и британский программист Саймон Уиллисон" "08-25-1991","День рождения Linux","Именно 25 августа 1991 года после нескольких месяцев разработки 21-летний студент Линус Торвальдс на конференции comp. os. minix заявил о создании рабочего прототипа новой ОС под названием Linux" diff --git a/wsgi.py b/wsgi.py index b83fe0a..3c95a08 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,4 +1,4 @@ from app.bot import app -if __name__ == '__main__': +if __name__ == "__main__": app.run(debug=False)