initial commit
This commit is contained in:
commit
0bb0cece15
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
config.yaml
|
||||||
|
.vscode
|
||||||
|
.venv
|
||||||
|
__pycache__
|
7
TODO.md
Normal file
7
TODO.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
- Делать разделение по юзерам во время использования. Т.е. под каждую сессию для раасыки - свой класс.
|
||||||
|
- Организовать корректную проверку введенных данных.
|
||||||
|
- Написать функцию по составлению SQL-запроса для БД
|
||||||
|
- Сформировать БД из данной exel-таблицы
|
||||||
|
- Написать функцию для рассылки WatsApp и Email
|
||||||
|
- Вынести кнопки в отдельные класс.
|
||||||
|
- Переписать обработчики сообщений, вынести отдельными функциями из __init__
|
7
main.py
Normal file
7
main.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""SenderBot - Telegram bot for mailing to email and Watsapp-messanger."""
|
||||||
|
|
||||||
|
from modules.telegram import TGSenderBot
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bot = TGSenderBot()
|
||||||
|
bot.bot.infinity_polling()
|
0
modules/__init__.py
Normal file
0
modules/__init__.py
Normal file
20
modules/configuration.py
Normal file
20
modules/configuration.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
"""Module for work with config-file."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
class Configuration:
|
||||||
|
"""Class for parsing config-file."""
|
||||||
|
|
||||||
|
def __init__(self, path: str) -> None:
|
||||||
|
"""Init class."""
|
||||||
|
self.path = path
|
||||||
|
self.config = self.get()
|
||||||
|
self.token = self.config["telegram_token"]
|
||||||
|
|
||||||
|
def get(self) -> dict:
|
||||||
|
"""Open file and get all value."""
|
||||||
|
with Path(self.path).open() as file:
|
||||||
|
return yaml.safe_load(file)
|
177
modules/telegram.py
Normal file
177
modules/telegram.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
"""..."""
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import telebot
|
||||||
|
from telebot.types import BotCommand, KeyboardButton, ReplyKeyboardMarkup
|
||||||
|
|
||||||
|
from modules.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
class TGSenderBot:
|
||||||
|
"""..."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
"""..."""
|
||||||
|
self.config = Configuration("config.yaml")
|
||||||
|
self.bot = telebot.TeleBot(self.config.token)
|
||||||
|
self.start_cmd = BotCommand(command="start", description="Start bot")
|
||||||
|
self.start_mailing = BotCommand(command="mailing", description="Prepare to mailing")
|
||||||
|
self.company = None
|
||||||
|
self.template_msg_path = Path()
|
||||||
|
self.mailing_method = None
|
||||||
|
self.waiting_template = bool
|
||||||
|
self.template_type = None
|
||||||
|
|
||||||
|
self.bot.set_my_commands([self.start_cmd, self.start_mailing])
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
@self.bot.message_handler(commands=["start"])
|
||||||
|
def __start_bot(message) -> None: ...
|
||||||
|
|
||||||
|
@self.bot.message_handler(commands=["mailing"])
|
||||||
|
def __start_mailing(message) -> None:
|
||||||
|
self.__clear_old_data()
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"Привет! Давай начнем подготовку к рассылке.\n\n"
|
||||||
|
"Для начала - нужно выбрать компанию, от имени которой ты будешь делать рассылку.",
|
||||||
|
reply_markup=self.__company_buttons(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Messages
|
||||||
|
@self.bot.message_handler(func=lambda message: True, content_types=["document","text","contact"]) # noqa: ARG005
|
||||||
|
def __send_message(message) -> None:
|
||||||
|
if self.waiting_template and message.document:
|
||||||
|
if message.document.mime_type.split("/")[1] == self.template_type:
|
||||||
|
template_info = self.bot.get_file(message.document.file_id)
|
||||||
|
download_file = self.bot.download_file(template_info.file_path)
|
||||||
|
|
||||||
|
self.template_msg_path = Path(f"./templates/{message.document.file_name}")
|
||||||
|
|
||||||
|
with self.template_msg_path.open("w+b") as file:
|
||||||
|
file.write(download_file)
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"Отлично! Шаблон сохранен. Осталось лишь проверить все данные, для рассылки.",
|
||||||
|
reply_markup= self.__enter_check(),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"Неверный формат файла. Пожалуйста, отправь файл в формате "
|
||||||
|
f"{'.txt' if self.template_type == 'plain' else '.html'}",
|
||||||
|
)
|
||||||
|
|
||||||
|
match message.text:
|
||||||
|
case "COZY COTTON" | "MixFix" | "chic chick" | "Ky Ky" | "WOLF&OWL" | "NOW":
|
||||||
|
self.company = message.text
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f'Выбрана компания "{self.company}"\n\nТеперь необходимо выбрать метод,'
|
||||||
|
"которым будут рассылаться сообщения.\n"
|
||||||
|
"Пожалуйста, выбери формат шаблона.",
|
||||||
|
reply_markup=self.__mailing_methods(),
|
||||||
|
)
|
||||||
|
case "E-Mail" | "WatsApp":
|
||||||
|
self.mailing_method = "mail" if message.text == "E-Mail" else "whatsapp"
|
||||||
|
msg = "по E-Mail" if self.mailing_method == "mail" else "сообщениями в WatsApp"
|
||||||
|
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f"Рассылка будет произведена методом {msg}.\n\n"
|
||||||
|
"Далее мы с тобой напишем шаблон сообщения для рассылки.",
|
||||||
|
reply_markup=self.__types_template_message(),
|
||||||
|
)
|
||||||
|
case "Текст" | "HTML":
|
||||||
|
self.template_type = "plain" if message.text == "Текст" else "html"
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"Отлично. Теперь отправь мне шаблон сообщения файлом.",
|
||||||
|
)
|
||||||
|
self.waiting_template = True
|
||||||
|
case "Проверить данные":
|
||||||
|
with self.template_msg_path.open() as file: # type: ignore # noqa: PGH003
|
||||||
|
txt = file.read()
|
||||||
|
msg = str(f'Отлично! Мы на финишной прямой. Проверь все данные. '
|
||||||
|
f'если все верно - нажми на кнопку "Начать", '
|
||||||
|
f"если где-то ошибка, пожалуйста, нажми на кнопку, что ты хочешь изменить.\n\n"
|
||||||
|
f"Компания: {self.company}\n"
|
||||||
|
f"Метод: {self.mailing_method}\n"
|
||||||
|
f"Текст:\n\n{txt}",
|
||||||
|
)
|
||||||
|
self.bot.send_message(message.chat.id, msg,reply_markup=self.__finish_menu())
|
||||||
|
case "Изменить компанию":
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"Выбери компанию, от имени которой ты будешь делать рассылку.",
|
||||||
|
reply_markup=self.__company_buttons()
|
||||||
|
)
|
||||||
|
case "Начать":
|
||||||
|
self.bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"Рассылка начата. По ее окончанию - я сообщу Вам.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __clear_old_data(self) -> None:
|
||||||
|
self.company = None
|
||||||
|
self.template_msg_path = None
|
||||||
|
self.mailing_method = None
|
||||||
|
self.waiting_template = bool
|
||||||
|
self.template_type = None
|
||||||
|
|
||||||
|
def __enter_check(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 3
|
||||||
|
markup.add(KeyboardButton("Проверить данные"))
|
||||||
|
return markup
|
||||||
|
|
||||||
|
def __enter_company(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 3
|
||||||
|
markup.add(KeyboardButton("Выбрать компанию"))
|
||||||
|
return markup
|
||||||
|
|
||||||
|
def __types_template_message(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 2
|
||||||
|
|
||||||
|
for method in ("Текст", "HTML"):
|
||||||
|
markup.add(KeyboardButton(method))
|
||||||
|
|
||||||
|
return markup
|
||||||
|
|
||||||
|
def __genetare_message_button(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 3
|
||||||
|
markup.add(
|
||||||
|
KeyboardButton("Send Number", request_contact=True),
|
||||||
|
)
|
||||||
|
return markup
|
||||||
|
|
||||||
|
def __company_buttons(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 3
|
||||||
|
|
||||||
|
for company in ("COZY COTTON", "MixFix", "chic chick", "Ky Ky", "WOLF&OWL", "NOW"):
|
||||||
|
markup.add(KeyboardButton(company))
|
||||||
|
|
||||||
|
return markup
|
||||||
|
|
||||||
|
def __mailing_methods(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 2
|
||||||
|
|
||||||
|
for method in ("E-Mail", "WatsApp"):
|
||||||
|
markup.add(KeyboardButton(method))
|
||||||
|
|
||||||
|
return markup
|
||||||
|
|
||||||
|
def __finish_menu(self) -> ReplyKeyboardMarkup:
|
||||||
|
markup = ReplyKeyboardMarkup()
|
||||||
|
markup.row_width = 3
|
||||||
|
|
||||||
|
for state in ("Изменить компанию", "Изменить метод", "Изменить шаблон", "Начать"):
|
||||||
|
markup.add(KeyboardButton(state))
|
||||||
|
return markup
|
6
pyproject.toml
Normal file
6
pyproject.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[tool.ruff]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
ignore = ["ANN001", "ANN101", "RUF001"]
|
1
templates/test.html
Normal file
1
templates/test.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h3>Hello World</h3>
|
1
templates/test.txt
Normal file
1
templates/test.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello World!
|
Loading…
Reference in New Issue
Block a user