Refactoring: step 1
- пакет app переименован в src - файл БД теперь должен лежать в data - удалена папка коммандс, все команды вынесены в модуль коммандс или админ_коммандс - нет импортов в ините - убраны все импорты * - теперь в .env можно указать use_reminder="FALSE", тогда не будет стартовать ремайндер - можно указать урл для Правил - в конфиге теперь только конфиг -то, что из енва получаем - константы теперь лежат отдельно - добавлены явные return там, где не было - бот и вебхук разнесены отдельно - при старте проверяем, что Правила доступны - добавлено еще логирование
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import logging
|
||||
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 .models import Chat, Quote, session
|
||||
from .reminder import remind, print_get_jobs, create_report_text
|
||||
from .report import reset_report_stats
|
||||
from .robot import bot
|
||||
|
||||
|
||||
@bot.message_handler(commands=["me"])
|
||||
async def send_me(message):
|
||||
"""Send info about user and chat id [Service]."""
|
||||
await bot.send_message(message.chat.id, me(message))
|
||||
|
||||
|
||||
@bot.message_handler(func=is_admin, commands=["ip"])
|
||||
async def get_ip(message):
|
||||
await bot.send_message(message.chat.id, my_ip())
|
||||
|
||||
|
||||
@bot.message_handler(commands=["remind"])
|
||||
async def remind_manually(message):
|
||||
"""Remind holidays manually."""
|
||||
args = message.text.split()
|
||||
if len(args) > 1:
|
||||
try:
|
||||
today = dt.strptime(args[1], "%m-%d-%Y")
|
||||
except ValueError as ve:
|
||||
await bot.send_message(message.chat.id, f"Не удалось разобрать дату!\n{ve}")
|
||||
else:
|
||||
await remind(message.chat.id, today)
|
||||
else:
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
f"<b>Формат даты: MM-DD-YYYY</b>\n\n"
|
||||
f"Примеры:\n"
|
||||
f"/remind 09-12-2024\n"
|
||||
f"/remind 09-13-2022",
|
||||
)
|
||||
|
||||
|
||||
@bot.message_handler(func=is_admin, commands=["jobs"])
|
||||
async def list_jobs(_message):
|
||||
"""List all the jobs in schedule."""
|
||||
await bot.send_message(ADMIN_ID, print_get_jobs())
|
||||
|
||||
|
||||
@bot.message_handler(func=is_admin, commands=["stats"])
|
||||
async def send_stats(message: types.Message):
|
||||
if len(message.text.split()) == 1:
|
||||
rep = create_report_text(message.chat.id)
|
||||
if rep:
|
||||
await bot.send_message(message.chat.id, rep)
|
||||
else:
|
||||
await bot.send_message(message.chat.id, create_report_text(message.text.split()[-1]))
|
||||
|
||||
|
||||
@bot.message_handler(func=is_admin, commands=["reset_stats"], chat_types=["supergroup", "group"])
|
||||
async def send_stats(message: types.Message):
|
||||
logging.warning("reset_stats")
|
||||
reset_report_stats(message.chat.id)
|
||||
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"])
|
||||
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}")
|
||||
if not session.query(Chat.id).filter(Chat.chat_id == message.chat.id).first():
|
||||
session.add(Chat(chat_id=message.chat.id, title=message.chat.title, antispam=1, report=0, reminder=1))
|
||||
session.commit()
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
f"""Группа "{message.chat.title} добавлена в БД.
|
||||
/get_group_info - узнать текущие настройки""",
|
||||
)
|
||||
else:
|
||||
await bot.send_message(message.chat.id, "Отказ. Группа уже включена")
|
||||
|
||||
|
||||
@bot.message_handler(func=is_admin, commands=["disable_stan"], chat_types=["supergroup", "group"])
|
||||
async def disable_stan(message: types.Message):
|
||||
logging.info(f"[{message.chat.title}] [{message.from_user.id}] {message.from_user.username}: {message.text}")
|
||||
if session.query(Chat.id).filter(Chat.chat_id == message.chat.id).first():
|
||||
chat = session.query(Chat).filter_by(chat_id=message.chat.id).first()
|
||||
session.delete(chat)
|
||||
session.commit()
|
||||
await bot.send_message(message.chat.id, f"Группа {message.chat.title} и все связанные с ней цитаты удалёны!")
|
||||
else:
|
||||
await bot.send_message(message.chat.id, "Отказ. Этой группы нет в БД.")
|
||||
|
||||
|
||||
@bot.message_handler(
|
||||
func=is_white,
|
||||
commands=["set_antispam_report_reminder", "set_rules"],
|
||||
chat_types=["supergroup", "group"],
|
||||
)
|
||||
async def set_antispam_report_reminder(message: types.Message):
|
||||
args = message.text.split()
|
||||
if len(args) == 4:
|
||||
try:
|
||||
antispam = int(args[1])
|
||||
rep = int(args[2])
|
||||
rem = int(args[3])
|
||||
except ValueError:
|
||||
logging.info(f"[ERROR] Неверные аргументы {message.text}")
|
||||
else:
|
||||
session.query(Chat).filter_by(chat_id=message.chat.id).update(
|
||||
{"antispam": antispam, "report": rep, "reminder": rem}
|
||||
)
|
||||
session.commit()
|
||||
await bot.send_message(message.chat.id, f"""Настройки обновлены. Проверить: /get_group_info""")
|
||||
|
||||
|
||||
@bot.message_handler(func=is_white, 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()
|
||||
if quotes:
|
||||
length = len(session.query(Quote).filter(Quote.chat_id == message.chat.id).all())
|
||||
text = f"Количество цитат: {length}\n\Последние добавленные\n\n"
|
||||
text += "\n".join(f"· {quote[0]}" for quote in quotes[-10:])
|
||||
await bot.send_message(message.chat.id, f"{text}")
|
||||
else:
|
||||
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"])
|
||||
async def get_group_info(message: types.Message):
|
||||
group = session.query(Chat).filter(Chat.chat_id == message.chat.id).first()
|
||||
if group:
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
f"""Группа: {group.title}
|
||||
ID группы: {group.chat_id}
|
||||
|
||||
Количество цитат: {len(session.query(Quote).filter(Quote.chat_id == message.chat.id).all())}
|
||||
Последние добавленные: /get_quotes
|
||||
|
||||
Текущие настройки:
|
||||
Антиспам: {group.antispam}
|
||||
Ежедневные отчёты: {group.report}
|
||||
Праздники: {group.reminder}""",
|
||||
)
|
||||
else:
|
||||
await bot.send_message(message.chat.id, f"Группа не включена. Включить: /enable_stan")
|
||||
|
||||
|
||||
@bot.message_handler(func=is_white, commands=["set_logging_level"], chat_types=["supergroup", "group"])
|
||||
async def set_logging_level(message: types.Message):
|
||||
args = message.text.split()
|
||||
if args[-1] == '10':
|
||||
logger.setLevel(LOGGING_LEVEL_DEBUG)
|
||||
logging.info("[LEVEL] Установлен уровень DEBUG")
|
||||
else:
|
||||
logger.setLevel(LOGGING_LEVEL_INFO)
|
||||
logging.info("[LEVEL] Установлен уровень INFO")
|
||||
+368
@@ -0,0 +1,368 @@
|
||||
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 .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 .admin_commands import bot
|
||||
from .rules import fetch_rule
|
||||
from .stan import act, speak
|
||||
|
||||
|
||||
async def send_or_reply(message: types.Message, answer, **kwargs):
|
||||
if message.reply_to_message:
|
||||
await bot.reply_to(message.reply_to_message, answer, **kwargs)
|
||||
else:
|
||||
await bot.send_message(message.chat.id, answer, **kwargs)
|
||||
|
||||
|
||||
""" [ ANTISPAM ] """
|
||||
|
||||
|
||||
@bot.edited_message_handler(func=in_spam_list, chat_types=["supergroup", "group"])
|
||||
@bot.message_handler(func=in_spam_list, chat_types=["supergroup", "group"])
|
||||
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
|
||||
|
||||
|
||||
@bot.message_handler(func=in_caption_spam_list, content_types=["video"], chat_types=["supergroup", "group"])
|
||||
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
|
||||
|
||||
|
||||
@bot.edited_message_handler(func=in_delete_list, chat_types=["supergroup", "group"])
|
||||
@bot.message_handler(func=in_delete_list, chat_types=["supergroup", "group"])
|
||||
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
|
||||
|
||||
|
||||
""" [ COMMANDS ] """
|
||||
|
||||
|
||||
@bot.message_handler(commands=["start", "links", "ссылки"])
|
||||
async def start(message: types.Message):
|
||||
"""What to begin with."""
|
||||
logging.info(LOG_COMM % (message.chat.title, message.from_user.id, message.from_user.first_name, message.text))
|
||||
markup = types.InlineKeyboardMarkup([[RULES], [FAQ], [LIB]], 1)
|
||||
await send_or_reply(message, "Начни с прочтения", reply_markup=markup)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["rules", "rule", "r", "правила", "правило", "п"])
|
||||
async def send_rules(message: types.Message):
|
||||
markup = types.InlineKeyboardMarkup([[RULES]], 1)
|
||||
args = message.text.split()
|
||||
logging.info(LOG_COMM % (message.chat.title, message.from_user.id, message.from_user.first_name, message.text))
|
||||
if len(args) > 1 and args[-1].isdigit() and 0 < int(args[-1]):
|
||||
await send_or_reply(
|
||||
message,
|
||||
f"<b>Правило {args[-1]}</b>\n<i>{fetch_rule(args[-1])}</i>",
|
||||
reply_markup=markup,
|
||||
)
|
||||
else:
|
||||
await send_or_reply(message, "Читай...", reply_markup=markup)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["faq", "чзв"])
|
||||
async def send_faq(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup([[FAQ]], 1)
|
||||
await send_or_reply(message, "Читай...", reply_markup=markup)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["lib", "library", "books", "книги", "библиотека"])
|
||||
async def send_lib(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup([[LIB]], 1)
|
||||
await send_or_reply(message, "Читай...", reply_markup=markup)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["lutz", "лутц"])
|
||||
async def send_lutz(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
await bot.send_document(
|
||||
message.chat.id,
|
||||
document="BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA",
|
||||
caption="вот, не позорься",
|
||||
)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["bdmtss", "бдмтсс"])
|
||||
async def send_bdmtss_audio(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
await bot.send_voice(
|
||||
message.chat.id,
|
||||
"AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ",
|
||||
)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["tr", "тр"])
|
||||
async def translate_layout(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
if message.reply_to_message and message.reply_to_message.text:
|
||||
if message.reply_to_message.text[0] in RUS:
|
||||
await bot.send_message(message.chat.id, message.reply_to_message.text.translate(RUS_ENG_TABLE))
|
||||
else:
|
||||
await bot.send_message(message.chat.id, message.reply_to_message.text.translate(ENG_RUS_TABLE))
|
||||
|
||||
|
||||
@bot.message_handler(commands=["quote", "цитата"])
|
||||
async def stan_speak(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
await bot.send_message(message.chat.id, speak(0, message.chat.id), parse_mode='Markdown')
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["tsya", "тся", "ться"])
|
||||
async def send_tsya(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
markup.add(types.InlineKeyboardButton("🧑🏼🎓 Читать правило", url="https://tsya.ru/"), row_width=1)
|
||||
await send_or_reply(message, "<i>-тся</i> и <i>-ться</i> в глаголах", reply_markup=markup)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["nometa", "номета"])
|
||||
async def send_nometa(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
markup.add(types.InlineKeyboardButton("❓ nometa.xyz", url="https://nometa.xyz/ru.html"), row_width=1)
|
||||
await send_or_reply(
|
||||
message,
|
||||
"""Не задавай мета-вопросов вроде:
|
||||
<i> «Можно задать вопрос?»
|
||||
«Кто-нибудь пользовался .. ?»
|
||||
«Привет, мне нужна помощь по .. !»</i>
|
||||
|
||||
Просто спроси сразу! И чем лучше объяснишь проблему, тем вероятнее получишь помощь.""",
|
||||
reply_markup=markup,
|
||||
)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["neprivet", "непривет"])
|
||||
async def send_neprivet(message: types.Message):
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
markup.add(types.InlineKeyboardButton("👋 Непривет", url="https://neprivet.com/"), row_width=1)
|
||||
await send_or_reply(message, "Пожалуйста, не пишите просто «Привет» в чате.", reply_markup=markup)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["nojob", "ноджоб"])
|
||||
async def send_nojob(message):
|
||||
answer = """Мы здесь не для того, чтобы за тебя решать задачи.
|
||||
|
||||
Здесь помогают по конкретным вопросам в <u>ТВОЁМ</u> коде, поэтому тебе нужно показать код, который ты написал сам и \
|
||||
объяснить где и почему застрял... всё просто. 🤷🏼️"""
|
||||
await send_or_reply(message, answer)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["nobot", "нобот"])
|
||||
async def nobot(message: types.Message):
|
||||
answer = """<b>Внимание</b>:
|
||||
Телеграм бот <i>не должен</i> быть твоим первым проектом на Python. Пожалуйста, изучи <code>основы Python</code>, \
|
||||
<code>работу с модулями</code>, <code>основы веб-технологий</code>, <code>асинхронное программирование</code> и \
|
||||
<code>отладку</code> до начала работы с Телеграм ботами. Существует много ресурсов для этого в интернете."""
|
||||
await send_or_reply(message, answer)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["nogui", "ногуи"])
|
||||
async def nogui(message: types.Message):
|
||||
answer = """<b>Внимание</b>:
|
||||
GUI приложение <i>не должно</i> быть твоим первым проектом на Python. Пожалуйста, изучи <code>основы Python</code>, \
|
||||
<code>работу с модулями</code>, <code>циклы событий</code> и <code>отладку</code> до начала работы с какими-либо \
|
||||
GUI-фреймворками. Существует много ресурсов для этого в интернете."""
|
||||
await send_or_reply(message, answer)
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["g", "г"])
|
||||
async def google_it(message: types.Message):
|
||||
"""Google it!"""
|
||||
logging.info(
|
||||
LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
message.from_user.id,
|
||||
message.from_user.first_name,
|
||||
message.text,
|
||||
)
|
||||
)
|
||||
query = f"<i>{detect_args(message)}</i>"
|
||||
get_query = f"https://www.google.com/search?q={represent_as_get(message)}"
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
markup.add(types.InlineKeyboardButton("🔍 Google Поиск", url=get_query), row_width=1)
|
||||
await send_or_reply(message, f"<i>Ищем «{query}»...</i>", reply_markup=markup)
|
||||
|
||||
|
||||
""" [ ADMIN PANEL ] """
|
||||
|
||||
|
||||
@bot.message_handler(func=is_admin, commands=["ddel"])
|
||||
async def delete_user(message: types.Message):
|
||||
if message.reply_to_message:
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
await bot.delete_message(message.chat.id, message.reply_to_message.id)
|
||||
logging.info(
|
||||
"!DEL!M "
|
||||
+ LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
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"])
|
||||
async def ban_user(message: types.Message):
|
||||
if message.reply_to_message:
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
await bot.delete_message(message.chat.id, message.reply_to_message.id)
|
||||
await bot.ban_chat_member(message.chat.id, message.reply_to_message.from_user.id)
|
||||
logging.info(
|
||||
f"!BAN!M "
|
||||
+ LOG_COMM
|
||||
% (
|
||||
message.chat.title,
|
||||
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"])
|
||||
async def unban_user(message: types.Message):
|
||||
if message.text.split()[-1].isdigit():
|
||||
user_id = int(message.text.split()[-1])
|
||||
await bot.unban_chat_member(PYTHONCHATRU, user_id)
|
||||
logging.info(f"!UNBAN (M)! {user_id}")
|
||||
|
||||
|
||||
""" [ INLINE ] """
|
||||
|
||||
|
||||
@bot.inline_handler(lambda query: True)
|
||||
async def default_query(inline_query):
|
||||
"""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,
|
||||
)
|
||||
)
|
||||
|
||||
await bot.answer_inline_query(inline_query.id, zen, cache_time=1200)
|
||||
|
||||
|
||||
""" [ COUNTER ] """
|
||||
|
||||
|
||||
@bot.message_handler(content_types=["text", "sticker", "photo", "animation", "video", "audio", "document"],
|
||||
chat_types=["supergroup", "group"])
|
||||
async def handle_msg(message: types.Message):
|
||||
"""Count messages, Stan."""
|
||||
update_stats(message)
|
||||
await act(message)
|
||||
@@ -0,0 +1,26 @@
|
||||
import logging
|
||||
import os
|
||||
from urllib.error import URLError
|
||||
from urllib.request import urlopen
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from telebot import logger
|
||||
|
||||
load_dotenv()
|
||||
|
||||
TOKEN = os.environ.get("LUTZPYBOT")
|
||||
if not TOKEN:
|
||||
raise LookupError("LUTZPYBOT (token) has not been found in .env")
|
||||
|
||||
WHITEIDS = {int(i) for i in os.environ.get("whiteids").split(",")}
|
||||
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):
|
||||
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)
|
||||
@@ -0,0 +1,80 @@
|
||||
import re
|
||||
|
||||
from telebot import types
|
||||
|
||||
|
||||
LOG_TEXT = "[%s] %s: %s"
|
||||
LOG_COMM = "[%s] [%s] %s: %s"
|
||||
LOGGING_LEVEL_DEBUG = 10
|
||||
LOGGING_LEVEL_INFO = 20
|
||||
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",
|
||||
"rykov7",
|
||||
"habr",
|
||||
"medium",
|
||||
"youtu",
|
||||
"rutube",
|
||||
"stepik",
|
||||
"digitalocean",
|
||||
"gra.ph",
|
||||
"#rtfm",
|
||||
"support",
|
||||
"jetbrains",
|
||||
]
|
||||
|
||||
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")
|
||||
|
||||
SPAM = {"me.sv/", "tg.sv/", "goo.by/", "go.sv/", "intim.video/", "uclck.ru/", 'раб0т',
|
||||
'0плат', 'Жду в ЛС', 'новый способ заработка', 'криптовалют', 'цифровых валют',
|
||||
'Binance', 'ByBit', 'Помогу заработать', 'подробнее в лс', 'арбитраж', 'напиши в личку',
|
||||
'DEX бирж', 'пишите в ЛС', 'Писать в ЛИЧКУ!', 'любую девушку', 'Пишите в личку',
|
||||
'прибыль у вaс', 'обучaю быстро', 'в л.с.', 'вопросам в ЛС', 'Предлагаю новый вид заработка',
|
||||
'пишите мне в ЛС', 'Писать в ЛС', 'межбиржев', 'КУПЮРЫ', '💎', 'kрипт', 'биpж', 'apбитpaж',
|
||||
'в неделю выходит до', 'предложить заработок', 'голые фот', '🔞', 'интимные фот', '➡️',
|
||||
'заработка в крипте', 'Веду набор', 'Идёт набор', 'мне в ЛС', 'Доход от', 'Trading',
|
||||
'P2P', 'Идет набор', 'в лс', 'нaбop', 'комaндy', 'kpuпт', 'бupж', '💰', 'пишитe', '💸',
|
||||
'$ в неделю', 'обучаю с нуля', 'доходы для всех', 'по трейдингу', 'фальшивые рубли', '‼️',
|
||||
'зароботку', 'Набuраю', 'цuфр', 'Обучу вас', 'прuб', 'остались курсы', 'Crypt', 'kр', 'рu'}
|
||||
|
||||
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!",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
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
|
||||
|
||||
|
||||
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]
|
||||
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
|
||||
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
|
||||
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):
|
||||
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):
|
||||
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:
|
||||
return message.from_user.id in WHITEIDS
|
||||
@@ -0,0 +1,62 @@
|
||||
""" Send User's info. """
|
||||
import logging
|
||||
import shelve
|
||||
from pathlib import Path
|
||||
from urllib import parse
|
||||
from urllib.request import urlopen
|
||||
|
||||
from telebot import types
|
||||
|
||||
from .constants import DATA
|
||||
from .report import reset_report_stats
|
||||
|
||||
|
||||
def my_ip():
|
||||
ip_service = "https://icanhazip.com"
|
||||
ip = urlopen(ip_service)
|
||||
return ip.read().decode("utf-8")
|
||||
|
||||
|
||||
def me(message: types.Message):
|
||||
msg = f"<b>Telegram ID:</b> <code>{message.from_user.id}</code>\n\
|
||||
├ <b>Is bot:</b> {message.from_user.is_bot}\n\
|
||||
├ <b>First name:</b> {message.from_user.first_name}\n"
|
||||
if message.from_user.last_name:
|
||||
msg += f" ├ <b>Last name:</b> {message.from_user.last_name}\n"
|
||||
if message.from_user.username:
|
||||
msg += f" ├ <b>Username:</b> {message.from_user.username}\n"
|
||||
msg += f" ├ <b>Language code:</b> {message.from_user.language_code}\n"
|
||||
if message.from_user.is_premium is True:
|
||||
msg += f" ├ <b>Is Premium</b>: ⭐️\n"
|
||||
else:
|
||||
msg += f" ├ <b>Is Premium</b>: No\n"
|
||||
msg += f" ├ <b>Chat ID:</b> {message.chat.id}"
|
||||
return msg
|
||||
|
||||
|
||||
def represent_as_get(message: types.Message):
|
||||
return parse.quote_plus(detect_args(message))
|
||||
|
||||
|
||||
def detect_args(message: types.Message):
|
||||
if message.reply_to_message and message.reply_to_message.text:
|
||||
if len(message.text.split()) == 1:
|
||||
return message.reply_to_message.text
|
||||
else:
|
||||
return " ".join(message.text.split()[1:])
|
||||
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
|
||||
@@ -0,0 +1,51 @@
|
||||
from pathlib import Path
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import relationship, declarative_base, sessionmaker
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
root = Path(__file__).parent.parent
|
||||
data_folder = root / "data"
|
||||
db_path = data_folder / "db.sqlite"
|
||||
engine = create_engine(f'sqlite:///{db_path}')
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
|
||||
|
||||
class Permission:
|
||||
USE_COMMANDS = 1 # Пользоваться обычными командами.
|
||||
SEND_LINKS = 2 # Может отправлять ссылки без удаления.
|
||||
MODIFY_QUOTES = 4 # Может добавлять и удалять цитаты.
|
||||
MODERATE = 8
|
||||
ADMIN = 16 # Может банить юзеров и удалять сообщения.
|
||||
|
||||
|
||||
class Quote(Base):
|
||||
__tablename__ = "quotes"
|
||||
id = Column(Integer, primary_key=True)
|
||||
chat_id = Column(Integer, ForeignKey('chats.chat_id'))
|
||||
text = Column(String)
|
||||
|
||||
def __repr__(self):
|
||||
return f"Quote({self.text=}, {self.chat_id=})"
|
||||
|
||||
|
||||
class Chat(Base):
|
||||
__tablename__ = "chats"
|
||||
id = Column(Integer, primary_key=True)
|
||||
chat_id = Column(Integer, unique=True)
|
||||
title = Column(String)
|
||||
|
||||
# Settings
|
||||
quotes = relationship('Quote', backref='chat', cascade='all, delete')
|
||||
antispam = Column(Boolean)
|
||||
report = Column(Boolean)
|
||||
reminder = Column(Boolean)
|
||||
hidden = Column(Boolean)
|
||||
|
||||
def __repr__(self):
|
||||
return f'Chat({self.chat_id=}, {self.title=})'
|
||||
@@ -0,0 +1,70 @@
|
||||
""" Schedule holidays. """
|
||||
import csv
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime as dt
|
||||
from threading import Thread
|
||||
|
||||
from schedule import repeat, every, get_jobs, run_pending
|
||||
from telebot import TeleBot
|
||||
|
||||
from .config import TOKEN, USE_REMINDER
|
||||
from .constants import PYTHONCHATRU
|
||||
from .report import create_report_text, reset_report_stats
|
||||
|
||||
if USE_REMINDER:
|
||||
logging.debug("Starts reminder!!!")
|
||||
# We need synchronous instance of bot here as we use synchronous library 'schedule' in a separate thread.
|
||||
bot = TeleBot(TOKEN, "HTML", disable_web_page_preview=True, allow_sending_without_reply=True)
|
||||
else:
|
||||
bot = None
|
||||
|
||||
|
||||
def scheduler():
|
||||
"""Main loop of schedule library."""
|
||||
while True:
|
||||
run_pending()
|
||||
time.sleep(60)
|
||||
|
||||
|
||||
@repeat(every().day.at("07:00"), PYTHONCHATRU, None)
|
||||
def remind(chat_to_repeat, today):
|
||||
"""Remind holiday."""
|
||||
if not today:
|
||||
today = dt.today()
|
||||
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
|
||||
date = dt.strptime(date, "%m-%d-%Y")
|
||||
if today.month == date.month and today.day == date.day:
|
||||
notification = f"🎉 Сегодня <b>{holiday.upper()}</b>!\n\n{description}"
|
||||
if date.year != 1000:
|
||||
age = today.year - date.year
|
||||
notification += f"\n\n🥳 <i>{age}-ая годовщина</i>"
|
||||
bot.send_message(chat_to_repeat, notification)
|
||||
|
||||
|
||||
@repeat(every().day.at("06:00"), PYTHONCHATRU)
|
||||
def stat_report(chat_to_repeat):
|
||||
"""Everyday group statistic info."""
|
||||
rep = create_report_text(PYTHONCHATRU)
|
||||
if rep:
|
||||
bot.send_message(chat_to_repeat, rep)
|
||||
reset_report_stats(PYTHONCHATRU)
|
||||
|
||||
|
||||
def print_get_jobs():
|
||||
"""Get jobs from schedule and prepare a formatted info text."""
|
||||
all_jobs = get_jobs()
|
||||
text = f"<b>{len(all_jobs)} jobs</b>\
|
||||
\n..:: {dt.now().strftime('%d-%m-%Y %H:%M:%S')} ::..\n"
|
||||
for i in all_jobs:
|
||||
text += f"\n · {i!r}"
|
||||
return text
|
||||
|
||||
|
||||
if USE_REMINDER:
|
||||
Thread(target=scheduler).start()
|
||||
@@ -0,0 +1,65 @@
|
||||
import html
|
||||
import os
|
||||
import random
|
||||
import shelve
|
||||
|
||||
from .config import ROLLBACK
|
||||
from .constants import DATA
|
||||
|
||||
|
||||
def create_report_text(chat_id):
|
||||
report = ""
|
||||
top_users = ""
|
||||
flooders = []
|
||||
spammer_icons = ('🐷', '🐒', '🐔')
|
||||
current_spammer_face = random.choice(spammer_icons)
|
||||
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
|
||||
|
||||
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
|
||||
)
|
||||
top_users += f'\n{i + 1}. {html.escape(name)} [{flooder["Count"]}]'
|
||||
|
||||
if len(flooders) >= 3 or s["Banned"] or s["Deleted"]:
|
||||
report = f"<b>H</b>ello, <b>W</b>orld!\n"
|
||||
if len(flooders) >= 3:
|
||||
report += f"{top_users}\n"
|
||||
if s["Banned"]:
|
||||
report += f"""
|
||||
<b> Криптоидов поймано:</b> {s['Banned']}
|
||||
└ [ {s['Banned'] * current_spammer_face} ]
|
||||
"""
|
||||
return report
|
||||
else:
|
||||
return f"Невозможно получить статистику.\n{DATA}{chat_id}.db не существует, возможно запрос в приватном чате. "
|
||||
|
||||
|
||||
def reset_report_stats(chat_id):
|
||||
with shelve.open(f"{DATA}{chat_id}") as shelve_db:
|
||||
shelve_db["Messages"] = {}
|
||||
shelve_db["Banned"] = 0
|
||||
shelve_db["Deleted"] = 0
|
||||
return f"""Chat ID: {chat_id}
|
||||
|
||||
{shelve_db['Messages']=}
|
||||
{shelve_db['Banned']=}
|
||||
{shelve_db['Deleted']=}"""
|
||||
@@ -0,0 +1,14 @@
|
||||
import logging
|
||||
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
|
||||
from .config import TOKEN
|
||||
|
||||
logging.warning("[START] Stan")
|
||||
bot = AsyncTeleBot(
|
||||
TOKEN,
|
||||
"HTML",
|
||||
disable_web_page_preview=True,
|
||||
allow_sending_without_reply=True,
|
||||
colorful_logs=True,
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
from urllib.request import urlopen
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from .config import RULES_URL
|
||||
|
||||
html = BeautifulSoup(urlopen(RULES_URL), "lxml")
|
||||
|
||||
|
||||
def fetch_rule(li):
|
||||
li = int(li)
|
||||
lis = html.find_all("li")
|
||||
if li <= len(lis):
|
||||
return lis[li - 1].text
|
||||
else:
|
||||
return f"Пока не придумали."
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
""" Stan's commands and reactions. """
|
||||
import asyncio
|
||||
import html
|
||||
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 .robot import bot
|
||||
|
||||
TYPING_TIMEOUT = 0.13 / 4 # Reading time is quarter of the same text writing time
|
||||
|
||||
|
||||
def speak(chance_of, group_id):
|
||||
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()])
|
||||
|
||||
|
||||
async def send_quote(after_sec, message, quote):
|
||||
"""Pretend Reading, pretend Typing, send."""
|
||||
if message.text:
|
||||
await asyncio.sleep(len(message.text) * TYPING_TIMEOUT)
|
||||
await bot.send_chat_action(message.chat.id, action="typing")
|
||||
await asyncio.sleep(after_sec) # Typing time
|
||||
await bot.send_message(message.chat.id, html.escape(quote))
|
||||
|
||||
|
||||
async def act(message: types.Message):
|
||||
quote = speak(50, message.chat.id)
|
||||
if quote:
|
||||
await send_quote(len(quote) * 0.13, message, quote)
|
||||
|
||||
|
||||
@bot.message_handler(func=is_white, 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
|
||||
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()
|
||||
await bot.send_message(message.chat.id, "➕\n └ " + quote.replace("\n", " "), parse_mode='Markdown')
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
else:
|
||||
await bot.send_message(message.chat.id, f"⛔️ Не добавил, есть токое\n └ {quote}", parse_mode='Markdown')
|
||||
|
||||
|
||||
@bot.message_handler(func=is_white, 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
|
||||
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()
|
||||
await bot.send_message(message.chat.id, f"➖ \n └ {quote}", parse_mode='Markdown')
|
||||
await bot.delete_message(message.chat.id, message.id)
|
||||
else:
|
||||
await bot.send_message(message.chat.id, f"⛔️ Нет такого\n └ {quote}", parse_mode='Markdown')
|
||||
|
||||
|
||||
@bot.message_handler(func=is_nongrata)
|
||||
async def tease_nongrata(message: types.Message):
|
||||
"""Reply to non grata mentions."""
|
||||
await bot.reply_to(message, "у нас тут таких не любят")
|
||||
@@ -0,0 +1,20 @@
|
||||
import logging
|
||||
|
||||
import telebot
|
||||
from fastapi import FastAPI
|
||||
|
||||
from .commands import bot
|
||||
from .config import TOKEN
|
||||
|
||||
logging.warning("[START] Webhook server")
|
||||
app = FastAPI(docs=None, redoc_url=None)
|
||||
|
||||
|
||||
@app.post(f"/bot{TOKEN}/")
|
||||
async def webhook(update: dict):
|
||||
"""Parse POST requests from Telegram."""
|
||||
if update:
|
||||
update = telebot.types.Update.de_json(update)
|
||||
await bot.process_new_updates([update])
|
||||
else:
|
||||
return None
|
||||
Reference in New Issue
Block a user