Skip to content

Commit

Permalink
fix: moar helpdesk refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
vas3k committed Jun 15, 2024
1 parent 9d2cb5f commit 062de44
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 129 deletions.
7 changes: 0 additions & 7 deletions club/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,6 @@
TELEGRAM_BOT_WEBHOOK_HOST = "0.0.0.0"
TELEGRAM_BOT_WEBHOOK_PORT = 8816

TELEGRAM_HELP_DESK_BOT_TOKEN = os.getenv("TELEGRAM_HELP_DESK_BOT_TOKEN")
TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID = os.getenv("TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID")
TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_DISCUSSION_ID = os.getenv("TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_DISCUSSION_ID")
TELEGRAM_HELP_DESK_BOT_WEBHOOK_URL = "https://vas3k.club/telegram/helpdeskbot/webhook/"
TELEGRAM_HELP_DESK_BOT_WEBHOOK_HOST = "0.0.0.0"
TELEGRAM_HELP_DESK_BOT_WEBHOOK_PORT = 8817

STRIPE_API_KEY = os.getenv("STRIPE_API_KEY") or ""
STRIPE_PUBLIC_KEY = os.getenv("STRIPE_PUBLIC_KEY") or ""
STRIPE_WEBHOOK_SECRET = os.getenv("STRIPE_WEBHOOK_SECRET") or ""
Expand Down
11 changes: 10 additions & 1 deletion helpdeskbot/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
DAILY_QUESTION_LIMIT = 3
import os

DAILY_QUESTION_LIMIT = 2
QUESTION_TITLE_MAX_LEN = 150
QUESTION_BODY_MAX_LEN = 2500

TELEGRAM_HELP_DESK_BOT_TOKEN = os.getenv("TELEGRAM_HELP_DESK_BOT_TOKEN")
TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID = os.getenv("TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID")
TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_DISCUSSION_ID = os.getenv("TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_DISCUSSION_ID")
TELEGRAM_HELP_DESK_BOT_WEBHOOK_URL = "https://vas3k.club/telegram/helpdeskbot/webhook/"
TELEGRAM_HELP_DESK_BOT_WEBHOOK_HOST = "0.0.0.0"
TELEGRAM_HELP_DESK_BOT_WEBHOOK_PORT = 8817
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from telegram import Update
from telegram.ext import CallbackContext

from helpdeskbot.help_desk_common import channel_msg_link, send_msg
from helpdeskbot import config
from helpdeskbot.help_desk_common import get_channel_message_link, send_message
from helpdeskbot.room import get_rooms
from helpdeskbot.models import Question
from club import settings

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -62,8 +62,8 @@ def handle_reply_from_room_chat(update: Update) -> None:
message_text = f"💬 {reply_chat_link} от {from_user_link} из чата {room_invite_link}:\n\n" \
f"{update.message.text}"

chat_id = settings.TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_DISCUSSION_ID
send_msg(chat_id=chat_id, text=message_text, reply_to_message_id=question.discussion_msg_id)
chat_id = config.TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_DISCUSSION_ID
send_message(chat_id=chat_id, text=message_text, reply_to_message_id=question.discussion_msg_id)


def notify_user_about_reply(update: Update, question: Question, from_room_chat: bool) -> None:
Expand All @@ -86,7 +86,7 @@ def notify_user_about_reply(update: Update, question: Question, from_room_chat:
from_user_link = f"<a href=\"tg://user?id={from_user.id}\">{from_user.first_name}</a>"
reply_text = message.text

question_link = f"<a href=\"{channel_msg_link(question.channel_msg_id)}\">❓ Ссылка на твой вопрос</a>"
question_link = f"<a href=\"{get_channel_message_link(question.channel_msg_id)}\">❓ Ссылка на твой вопрос</a>"

if from_room_chat:
room = question.room
Expand All @@ -101,7 +101,7 @@ def notify_user_about_reply(update: Update, question: Question, from_room_chat:
f"{reply_text}\n\n" \
f"{question_link}"

send_msg(chat_id=int(user_id), text=message_text)
send_message(chat_id=int(user_id), text=message_text)


def on_reply_message(update: Update, context: CallbackContext) -> None:
Expand All @@ -113,7 +113,7 @@ def on_reply_message(update: Update, context: CallbackContext) -> None:
reply_to = update.message.reply_to_message

if reply_to.forward_from_chat:
if reply_to.forward_from_chat.id == int(settings.TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID):
if reply_to.forward_from_chat.id == int(config.TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID):
handle_reply_from_channel(update)
return None
else:
Expand Down
126 changes: 52 additions & 74 deletions helpdeskbot/handlers/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
from telegram.ext import CallbackContext, ConversationHandler, CommandHandler, MessageHandler, Filters

from helpdeskbot import config
from helpdeskbot.help_desk_common import channel_msg_link, send_msg, edit_msg, chat_msg_link, msg_reply
from helpdeskbot.help_desk_common import get_channel_message_link, send_message, edit_message, get_chat_message_link, send_reply
from helpdeskbot.models import Question, HelpDeskUser
from helpdeskbot.room import get_rooms
from bot.handlers.common import get_club_user
from club import settings
from notifications.telegram.common import render_html_message

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -61,7 +60,6 @@ class QuestionKeyboard(Enum):
def get_rooms_markup() -> list:
room_names = list(rooms.keys())
room_names.append(DO_NOT_SEND_ROOM)

num_columns = 2
return [room_names[i:i + num_columns] for i in range(0, len(room_names), num_columns)]

Expand All @@ -83,6 +81,8 @@ def from_user_data(cls, user_data: Dict[str, str]) -> "QuestionDto":
title=user_data.get(QuestionKeyboard.TITLE.value, ""),
body=user_data.get(QuestionKeyboard.BODY.value, ""),
room=user_data.get(QuestionKeyboard.ROOM.value, "")
if user_data.get(QuestionKeyboard.ROOM.value, "") != DO_NOT_SEND_ROOM
else None
)

def to_json(self):
Expand All @@ -100,21 +100,20 @@ def start(update: Update, context: CallbackContext) -> State:

help_desk_user_ban = HelpDeskUser.objects.filter(user=user).first()
if help_desk_user_ban and help_desk_user_ban.is_banned:
msg_reply(update, "🙈 Вас забанили от пользования Вастрик Справочной")
send_reply(update, "🙈 Вас забанили от пользования Вастрик Справочной")
return ConversationHandler.END

yesterday = datetime.utcnow() - timedelta(hours=24)
question_number = Question.objects.filter(user=user) \
.filter(created_at__gte=yesterday) \
question_count_24h = Question.objects.filter(user=user) \
.filter(created_at__gte=datetime.utcnow() - timedelta(hours=24)) \
.count()

if question_number >= config.DAILY_QUESTION_LIMIT:
msg_reply(update, "🙅‍♂️ Вы достигли своего дневного лимита вопросов. Приходите завтра!")
if question_count_24h >= config.DAILY_QUESTION_LIMIT:
send_reply(update, "🙅‍♂️ Вы достигли своего дневного лимита вопросов. Приходите завтра!")
return ConversationHandler.END

context.user_data.clear()

msg_reply(
send_reply(
update,
render_html_message("helpdeskbot_welcome.html", user=user),
reply_markup=question_markup,
Expand All @@ -130,7 +129,7 @@ def input_response(update: Update, context: CallbackContext) -> State:
user_data[field] = text
del user_data[CUR_FIELD_KEY]

msg_reply(
send_reply(
update,
"Принято 👌 Что дальше?",
reply_markup=question_markup,
Expand All @@ -141,9 +140,9 @@ def input_response(update: Update, context: CallbackContext) -> State:

def request_title_value(update: Update, context: CallbackContext) -> State:
context.user_data[CUR_FIELD_KEY] = QuestionKeyboard.TITLE.value
msg_reply(
send_reply(
update,
f"Введите заголовок вопроса. Он должен кратко и понятно описывать ваш запрос. "
f"Введите заголовок вашего вопроса. Постарайтесь быть краткими и понятными. "
f"Максимум {config.QUESTION_TITLE_MAX_LEN} символов.",
reply_markup=ReplyKeyboardRemove()
)
Expand All @@ -153,10 +152,10 @@ def request_title_value(update: Update, context: CallbackContext) -> State:

def request_body_value(update: Update, context: CallbackContext) -> State:
context.user_data[CUR_FIELD_KEY] = QuestionKeyboard.BODY.value
msg_reply(
send_reply(
update,
f"Введите текст вопроса. Опишите побольше деталей и контекста. "
f"Например, ваш город/страну или уже опробованные варианты решений.",
f"Например, ваш город/страну и уже опробованные варианты решений.",
reply_markup=ReplyKeyboardRemove()
)

Expand All @@ -165,10 +164,10 @@ def request_body_value(update: Update, context: CallbackContext) -> State:

def request_room_choose(update: Update, context: CallbackContext) -> State:
context.user_data[CUR_FIELD_KEY] = QuestionKeyboard.ROOM.value
msg_reply(
send_reply(
update,
"Выберите один из чатов, в который бот перепостит ваш вопрос. "
"Это не обязательно, но увеличивает возможность того, что вам кто-то ответит.",
"Это не обязательно, но может увеличить вероятность того, что там найдётся кто-то, кто знает ответ.",
reply_markup=room_choose_markup,
)
return State.INPUT_RESPONSE
Expand All @@ -180,24 +179,24 @@ def review_question(update: Update, context: CallbackContext) -> State:
title = user_data.get(QuestionKeyboard.TITLE.value, None)
body = user_data.get(QuestionKeyboard.BODY.value, None)
if not title or not body:
msg_reply(update, "☝️ Заголовок и текст вопроса обязательны для заполнения")
send_reply(update, "☝️ Заголовок и текст вопроса обязательны для заполнения")
return edit_question(update, context)

if len(title) > config.QUESTION_TITLE_MAX_LEN:
msg_reply(
send_reply(
update,
f"😬 Заголовок не должен быть длиннее {config.QUESTION_TITLE_MAX_LEN} символов (у вас {len(title)})"
)
return edit_question(update, context)

if len(body) > config.QUESTION_BODY_MAX_LEN:
msg_reply(
send_reply(
update,
f"😬 Текст вопроса не может быть длиннее {config.QUESTION_BODY_MAX_LEN} символов (у вас {len(body)})"
)
return edit_question(update, context)

msg_reply(
send_reply(
update,
render_html_message(
"helpdeskbot_review_question.html",
Expand All @@ -215,66 +214,45 @@ def publish_question(update: Update, user_data: Dict[str, str]) -> str:
if not user:
return ConversationHandler.END

title = user_data[QuestionKeyboard.TITLE.value]
body = user_data[QuestionKeyboard.BODY.value]
json_text = {
"title": title,
"body": body
}

room_title = user_data.get(QuestionKeyboard.ROOM.value, None)
if room_title and room_title != DO_NOT_SEND_ROOM:
json_text["room"] = room_title
data = QuestionDto.from_user_data(user_data)
room = rooms[data.room] if data.room else None

question = Question(
user=user,
json_text=json_text
json_text=data.to_json()
)
question.save()

room_chat_msg_text = render_html_message(
"helpdeskbot_question.html",
question=QuestionDto.from_user_data(user_data),
user=user,
telegram_user=update.effective_user,
)

room = rooms[room_title] if room_title and room_title != DO_NOT_SEND_ROOM else None
room_chat_msg = None
if room and room.chat_id:
room_chat_msg = send_msg(room.chat_id, room_chat_msg_text)

channel_msg_text = room_chat_msg_text

if room_chat_msg:
question.room = room
question.room_chat_msg_id = room_chat_msg.message_id

group_msg_link = chat_msg_link(
chat_id=room.chat_id.replace("-100", ""),
message_id=room_chat_msg.message_id
channel_message = send_message(
chat_id=config.TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID,
text=render_html_message(
"helpdeskbot_channel_question.html",
question=data,
room=room,
user=user,
telegram_user=update.effective_user,
)
channel_msg_text = (f"{channel_msg_text}\n\n" +
hyperlink_format(href=group_msg_link, text="🔗 Ссылка на вопрос в чате"))

channel_msg = send_msg(
chat_id=settings.TELEGRAM_HELP_DESK_BOT_QUESTION_CHANNEL_ID,
text=channel_msg_text
)

question.channel_msg_id = channel_msg.message_id
question.channel_msg_id = channel_message.message_id
question.save()

msg_link = channel_msg_link(channel_msg.message_id)
if room_chat_msg:
room_chat_msg_text = (f"{room_chat_msg_text}\n\n" +
hyperlink_format(href=msg_link, text="🔗 Ответы на вопрос в канале"))
edit_msg(chat_id=room.chat_id, message_id=room_chat_msg.message_id, new_text=room_chat_msg_text)
return msg_link
if room and room.chat_id:
send_message(
chat_id=room.chat_id,
text=render_html_message(
"helpdeskbot_room_question.html",
question=data,
room=room,
user=user,
telegram_user=update.effective_user,
channel_message_link=get_channel_message_link(channel_message.message_id),
)
)


def edit_question(update: Update, context: CallbackContext) -> State:
msg_reply(
send_reply(
update,
"Окей, что редактируем?",
reply_markup=question_markup,
Expand All @@ -288,9 +266,9 @@ def finish_review(update: Update, context: CallbackContext) -> State:

if text == ReviewKeyboard.CREATE.value:
link = publish_question(update, user_data)
msg_reply(
send_reply(
update,
f"🎉 Вопрос опубликован: <a href=\"{link}\">ссылка и ответы</a>",
f"🎉 Вопрос опубликован: <a href=\"{link}\">ссылка и ответы в канале</a>",
reply_markup=ReplyKeyboardRemove(),
)
return ConversationHandler.END
Expand All @@ -299,9 +277,9 @@ def finish_review(update: Update, context: CallbackContext) -> State:
return edit_question(update, context)

elif text == ReviewKeyboard.CANCEL.value:
msg_reply(
send_reply(
update,
"🫡 Создание вопроса отменено. Можно начать заново",
"🫡 Создание вопроса отменено. Можно начать заново — /start",
reply_markup=ReplyKeyboardRemove(),
)
return ConversationHandler.END
Expand All @@ -311,7 +289,7 @@ def finish_review(update: Update, context: CallbackContext) -> State:


def fallback(update: Update, context: CallbackContext) -> State:
msg_reply(
send_reply(
update,
"Вы не выбрали действие. Пожалуйста, кликните на один из пунктов меню 👇",
reply_markup=question_markup,
Expand All @@ -320,9 +298,9 @@ def fallback(update: Update, context: CallbackContext) -> State:


def error_fallback(update: Update, context: CallbackContext) -> int:
msg_reply(
send_reply(
update,
"Что-то пошло не так. Придётся начать всё заново :("
"Что-то пошло не так. Придётся начать всё заново — /start"
)
return ConversationHandler.END

Expand Down
Loading

0 comments on commit 062de44

Please sign in to comment.