1
0
mirror of https://github.com/civsocit/olgram.git synced 2025-12-17 05:26:18 +00:00

Chinese language support (suddenly!)

This commit is contained in:
mihalin
2022-03-22 05:43:10 +03:00
parent db54473e0f
commit 1a9646d607
18 changed files with 740 additions and 126 deletions

View File

@@ -5,6 +5,7 @@ from aiogram import types
from aiogram.utils.exceptions import TelegramAPIError, Unauthorized
from olgram.models.models import Bot
from server.server import unregister_token
from locales.locale import _
async def delete_bot(bot: Bot, call: types.CallbackQuery):
@@ -17,7 +18,7 @@ async def delete_bot(bot: Bot, call: types.CallbackQuery):
# Вероятно пользователь сбросил токен или удалил бот, это уже не наши проблемы
pass
await bot.delete()
await call.answer("Бот удалён")
await call.answer(_("Бот удалён"))
try:
await call.message.delete()
except TelegramAPIError:
@@ -33,7 +34,7 @@ async def reset_bot_text(bot: Bot, call: types.CallbackQuery):
"""
bot.start_text = bot._meta.fields_map['start_text'].default
await bot.save()
await call.answer("Текст сброшен")
await call.answer(_("Текст сброшен"))
async def reset_bot_second_text(bot: Bot, call: types.CallbackQuery):
@@ -45,7 +46,7 @@ async def reset_bot_second_text(bot: Bot, call: types.CallbackQuery):
"""
bot.second_text = bot._meta.fields_map['second_text'].default
await bot.save()
await call.answer("Текст сброшен")
await call.answer(_("Текст сброшен"))
async def select_chat(bot: Bot, call: types.CallbackQuery, chat: str):
@@ -59,16 +60,16 @@ async def select_chat(bot: Bot, call: types.CallbackQuery, chat: str):
if chat == "personal":
bot.group_chat = None
await bot.save()
await call.answer("Выбран личный чат")
await call.answer(_("Выбран личный чат"))
return
chat_obj = await bot.group_chats.filter(id=chat).first()
if not chat_obj:
await call.answer("Нельзя привязать бота к этому чату")
await call.answer(_("Нельзя привязать бота к этому чату"))
return
bot.group_chat = chat_obj
await bot.save()
await call.answer(f"Выбран чат {chat_obj.name}")
await call.answer(_("Выбран чат {0}").format(chat_obj.name))
async def threads(bot: Bot, call: types.CallbackQuery):

View File

@@ -12,6 +12,7 @@ from olgram.models.models import Bot, User
from olgram.settings import OlgramSettings
from olgram.commands.menu import send_bots_menu
from server.server import register_token
from locales.locale import _
from olgram.router import dp
@@ -38,10 +39,10 @@ async def add_bot(message: types.Message, state: FSMContext):
"""
bot_count = await Bot.filter(owner__telegram_id=message.from_user.id).count()
if bot_count >= OlgramSettings.max_bots_per_user():
await message.answer("У вас уже слишком много ботов.")
await message.answer(_("У вас уже слишком много ботов."))
return
await message.answer(dedent("""
await message.answer(dedent(_("""
Чтобы подключить бот, вам нужно выполнить три действия:
1. Перейдите в бот @BotFather, нажмите START и отправьте команду /newbot
@@ -49,7 +50,7 @@ async def add_bot(message: types.Message, state: FSMContext):
3. После создания бота перешлите ответное сообщение в этот бот или скопируйте и пришлите token бота.
Важно: не подключайте боты, которые используются в других сервисах (Manybot, Chatfuel, Livegram и других).
"""))
""")))
await state.set_state("add_bot")
@@ -61,26 +62,26 @@ async def bot_added(message: types.Message, state: FSMContext):
token = re.findall(token_pattern, message.text)
async def on_invalid_token():
await message.answer(dedent("""
await message.answer(dedent(_("""
Это не токен бота.
Токен выглядит вот так: 123456789:AAAA-abc123_AbcdEFghijKLMnopqrstu12
"""))
""")))
async def on_dummy_token():
await message.answer(dedent("""
await message.answer(dedent(_("""
Не удалось запустить этого бота: неверный токен
"""))
""")))
async def on_unknown_error():
await message.answer(dedent("""
await message.answer(dedent(_("""
Не удалось запустить этого бота: непредвиденная ошибка
"""))
""")))
async def on_duplication_bot():
await message.answer(dedent("""
await message.answer(dedent(_("""
Такой бот уже есть в базе данных
"""))
""")))
if not token:
return await on_invalid_token()
@@ -98,7 +99,7 @@ async def bot_added(message: types.Message, state: FSMContext):
except TelegramAPIError:
return await on_unknown_error()
user, _ = await User.get_or_create(telegram_id=message.from_user.id)
user, created = await User.get_or_create(telegram_id=message.from_user.id)
bot = Bot(token=Bot.encrypted_token(token), owner=user, name=test_bot_info.username,
super_chat_id=message.from_user.id)
try:
@@ -110,5 +111,5 @@ async def bot_added(message: types.Message, state: FSMContext):
await bot.delete()
return await on_unknown_error()
await message.answer("Бот добавлен! Список ваших ботов: /mybots")
await message.answer(_("Бот добавлен! Список ваших ботов: /mybots"))
await state.reset_state()

View File

@@ -8,6 +8,7 @@ from olgram.models import models
from olgram.router import dp
from olgram.settings import OlgramSettings
from locales.locale import _
@dp.message_handler(commands=["info"], state="*")
@@ -17,7 +18,7 @@ async def info(message: types.Message, state: FSMContext):
"""
if message.chat.id != OlgramSettings.supervisor_id():
await message.answer("Недостаточно прав")
await message.answer(_("Недостаточно прав"))
return
bots = await models.Bot.all()
@@ -28,8 +29,8 @@ async def info(message: types.Message, state: FSMContext):
income_messages = sum([bot.incoming_messages_count for bot in bots])
outgoing_messages = sum([bot.outgoing_messages_count for bot in bots])
await message.answer(f"Количество ботов: {bots_count}\n"
f"Количество пользователей (у конструктора): {user_count}\n"
f"Шаблонов ответов: {templates_count}\n"
f"Входящих сообщений у всех ботов: {income_messages}\n"
f"Исходящих сообщений у всех ботов: {outgoing_messages}\n")
await message.answer(_("Количество ботов: {0}\n").format(bots_count) +
_("Количество пользователей (у конструктора): {0}\n").format(user_count) +
_("Шаблонов ответов: {0}\n").format(templates_count) +
_("Входящих сообщений у всех ботов: {0}\n").format(income_messages) +
_("Исходящих сообщений у всех ботов: {0}\n").format(outgoing_messages))

View File

@@ -7,6 +7,7 @@ from aiogram.utils.callback_data import CallbackData
from textwrap import dedent
from olgram.utils.mix import edit_or_create, button_text_limit, wrap
from olgram.commands import bot_actions
from locales.locale import _
import typing as ty
@@ -27,11 +28,11 @@ async def send_bots_menu(chat_id: int, user_id: int, call=None):
user = await User.get_or_none(telegram_id=user_id)
bots = await Bot.filter(owner=user)
if not bots:
await AioBot.get_current().send_message(chat_id, dedent("""
await AioBot.get_current().send_message(chat_id, dedent(_("""
У вас нет добавленных ботов.
Отправьте команду /addbot, чтобы добавить бот.
"""))
""")))
return
keyboard = types.InlineKeyboardMarkup(row_width=2)
@@ -42,7 +43,7 @@ async def send_bots_menu(chat_id: int, user_id: int, call=None):
chat=empty))
)
text = "Ваши боты"
text = _("Ваши боты")
if call:
await edit_or_create(call, text, keyboard)
else:
@@ -63,28 +64,28 @@ async def send_chats_menu(bot: Bot, call: types.CallbackQuery):
)
if chats:
keyboard.insert(
types.InlineKeyboardButton(text="Личные сообщения",
types.InlineKeyboardButton(text=_("Личные сообщения"),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="chat",
chat="personal"))
)
keyboard.insert(
types.InlineKeyboardButton(text="<< Назад",
types.InlineKeyboardButton(text=_("<< Назад"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty,
chat=empty))
)
if not chats:
text = dedent(f"""
text = dedent(_("""
Этот бот не добавлен в чаты, поэтому все сообщения будут приходить вам в бот.
Чтобы подключить чат — добавьте бот @{bot.name} в чат, откройте это меню ещё раз и выберите добавленный чат.
Чтобы подключить чат — добавьте бот @{0} в чат, откройте это меню ещё раз и выберите добавленный чат.
Если ваш бот состоял в групповом чате до того, как его добавили в Olgram - удалите бота из чата и добавьте
снова.
""")
""")).format(bot.name)
else:
text = dedent(f"""
В этом разделе вы можете привязать бота @{bot.name} к чату.
text = dedent(_("""
В этом разделе вы можете привязать бота @{0} к чату.
Выберите чат, куда бот будет пересылать сообщения.
""")
""")).format(bot.name)
await edit_or_create(call, text, keyboard)
@@ -93,86 +94,86 @@ async def send_bot_menu(bot: Bot, call: types.CallbackQuery):
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(
types.InlineKeyboardButton(text="Текст",
types.InlineKeyboardButton(text=_("Текст"),
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="text",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Чат",
types.InlineKeyboardButton(text=_("Чат"),
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="chat",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Удалить бот",
types.InlineKeyboardButton(text=_("Удалить бот"),
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="delete",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Статистика",
types.InlineKeyboardButton(text=_("Статистика"),
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="stat",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="<< Назад",
types.InlineKeyboardButton(text=_("<< Назад"),
callback_data=menu_callback.new(level=0, bot_id=empty, operation=empty, chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Опции",
types.InlineKeyboardButton(text=_("Опции"),
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="settings",
chat=empty))
)
await edit_or_create(call, dedent(f"""
Управление ботом @{bot.name}.
await edit_or_create(call, dedent(_("""
Управление ботом @{0}.
Если у вас возникли вопросы по настройке бота, то посмотрите нашу справку /help или напишите нам
@civsocit_feedback_bot
"""), reply_markup=keyboard)
""")).format(bot.name), reply_markup=keyboard)
async def send_bot_delete_menu(bot: Bot, call: types.CallbackQuery):
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(
types.InlineKeyboardButton(text="Да, удалить бот",
types.InlineKeyboardButton(text=_("Да, удалить бот"),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="delete_yes",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="<< Назад",
types.InlineKeyboardButton(text=_("<< Назад"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
)
await edit_or_create(call, dedent(f"""
Вы уверены, что хотите удалить бота @{bot.name}?
"""), reply_markup=keyboard)
await edit_or_create(call, dedent(_("""
Вы уверены, что хотите удалить бота @{0}?
""")).format(bot.name), reply_markup=keyboard)
async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=1)
keyboard.insert(
types.InlineKeyboardButton(text="Потоки сообщений",
types.InlineKeyboardButton(text=_("Потоки сообщений"),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="threads",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Данные пользователя",
types.InlineKeyboardButton(text=_("Данные пользователя"),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="additional_info",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="<< Назад",
types.InlineKeyboardButton(text=_("<< Назад"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty,
chat=empty))
)
thread_turn = "включены" if bot.enable_threads else "выключены"
info_turn = "включены" if bot.enable_additional_info else "выключены"
text = dedent(f"""
<a href="https://olgram.readthedocs.io/ru/latest/options.html#threads">Потоки сообщений</a>: <b>{thread_turn}</b>
<a href="https://olgram.readthedocs.io/ru/latest/options.html#user-info">Данные пользователя</a>: <b>{info_turn}</b>
""")
thread_turn = _("включены") if bot.enable_threads else _("выключены")
info_turn = _("включены") if bot.enable_additional_info else _("выключены")
text = dedent(_("""
<a href="https://olgram.readthedocs.io/ru/latest/options.html#threads">Потоки сообщений</a>: <b>{0}</b>
<a href="https://olgram.readthedocs.io/ru/latest/options.html#user-info">Данные пользователя</a>: <b>{1}</b>
""")).format(thread_turn, info_turn)
await edit_or_create(call, text, reply_markup=keyboard, parse_mode="HTML")
@@ -181,21 +182,21 @@ async def send_bot_text_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] =
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(
types.InlineKeyboardButton(text="<< Завершить редактирование",
types.InlineKeyboardButton(text=_("<< Завершить редактирование"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Автоответчик",
types.InlineKeyboardButton(text=_("Автоответчик"),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="next_text",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Сбросить текст",
types.InlineKeyboardButton(text=_("Сбросить текст"),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="reset_text",
chat=empty))
)
text = dedent("""
text = dedent(_("""
Сейчас вы редактируете текст, который отправляется после того, как пользователь отправит вашему боту @{0}
команду /start
@@ -204,7 +205,7 @@ async def send_bot_text_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] =
{1}
</pre>
Отправьте сообщение, чтобы изменить текст.
""")
"""))
text = text.format(bot.name, bot.start_text)
if call:
await edit_or_create(call, text, keyboard, parse_mode="HTML")
@@ -218,18 +219,19 @@ async def send_bot_statistic_menu(bot: Bot, call: ty.Optional[types.CallbackQuer
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(
types.InlineKeyboardButton(text="<< Назад",
types.InlineKeyboardButton(text=_("<< Назад"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
)
text = dedent(f"""
Статистика по боту @{bot.name}
text = dedent(_("""
Статистика по боту @{0}
Входящих сообщений: <b>{bot.incoming_messages_count}</b>
Ответных сообщений: <b>{bot.outgoing_messages_count}</b>
Шаблоны ответов: <b>{len(await bot.answers)}</b>
Забанено пользователей: <b>{len(await bot.banned_users)}</b>
""")
Входящих сообщений: <b>{1}</b>
Ответных сообщений: <b>{2}</b>
Шаблоны ответов: <b>{3}</b>
Забанено пользователей: <b>{4}</b>
""")).format(bot.name, bot.incoming_messages_count, bot.outgoing_messages_count, len(await bot.answers),
len(await bot.banned_users))
if call:
await edit_or_create(call, text, keyboard, parse_mode="HTML")
else:
@@ -242,26 +244,26 @@ async def send_bot_second_text_menu(bot: Bot, call: ty.Optional[types.CallbackQu
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(
types.InlineKeyboardButton(text="<< Завершить редактирование",
types.InlineKeyboardButton(text=_("<< Завершить редактирование"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Предыдущий текст",
types.InlineKeyboardButton(text=_("Предыдущий текст"),
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="text",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Шаблоны ответов...",
types.InlineKeyboardButton(text=_("Шаблоны ответов..."),
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="templates",
chat=empty))
)
keyboard.insert(
types.InlineKeyboardButton(text="Сбросить текст",
types.InlineKeyboardButton(text=_("Сбросить текст"),
callback_data=menu_callback.new(level=3, bot_id=bot.id,
operation="reset_second_text", chat=empty))
)
text = dedent("""
text = dedent(_("""
Сейчас вы редактируете текст автоответчика. Это сообщение отправляется в ответ на все входящие сообщения @{0} \
автоматически. По умолчанию оно отключено.
@@ -270,8 +272,8 @@ async def send_bot_second_text_menu(bot: Bot, call: ty.Optional[types.CallbackQu
{1}
</pre>
Отправьте сообщение, чтобы изменить текст.
""")
text = text.format(bot.name, bot.second_text if bot.second_text else "(отключено)")
"""))
text = text.format(bot.name, bot.second_text if bot.second_text else _("(отключено)"))
if call:
await edit_or_create(call, text, keyboard, parse_mode="HTML")
else:
@@ -284,11 +286,11 @@ async def send_bot_templates_menu(bot: Bot, call: ty.Optional[types.CallbackQuer
await call.answer()
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(
types.InlineKeyboardButton(text="<< Завершить редактирование",
types.InlineKeyboardButton(text=_("<< Завершить редактирование"),
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
)
text = dedent("""
text = dedent(_("""
Сейчас вы редактируете шаблоны ответов для @{0}. Текущие шаблоны:
<pre>
@@ -296,7 +298,7 @@ async def send_bot_templates_menu(bot: Bot, call: ty.Optional[types.CallbackQuer
</pre>
Отправьте какую-нибудь фразу (например: "Ваш заказ готов, ожидайте!"), чтобы добавить её в шаблон.
Чтобы удалить шаблон из списка, отправьте его номер в списке (например, 4)
""")
"""))
templates = await bot.answers
@@ -307,7 +309,7 @@ async def send_bot_templates_menu(bot: Bot, call: ty.Optional[types.CallbackQuer
templates_text = "\n".join(f"{n}. {wrap(template.text, max_len)}" for n, template in enumerate(templates))
if not templates_text:
templates_text = "(нет шаблонов)"
templates_text = _("(нет шаблонов)")
text = text.format(bot.name, templates_text)
if call:
await edit_or_create(call, text, keyboard, parse_mode="HTML")
@@ -346,20 +348,21 @@ async def template_received(message: types.Message, state: FSMContext):
number = int(message.text)
templates = await bot.answers
if not templates:
await message.answer("У вас нет шаблонов, чтобы их удалять")
await message.answer(_("У вас нет шаблонов, чтобы их удалять"))
if number < 0 or number >= len(templates):
await message.answer(f"Неправильное число. Чтобы удалить шаблон, введите число от 0 до {len(templates)}")
await message.answer(_("Неправильное число. Чтобы удалить шаблон, введите число от 0 до {0}").format(
len(templates)))
return
await templates[number].delete()
else:
# Add template
total_templates = len(await bot.answers)
if total_templates > 30:
await message.answer("У вашего бота уже слишком много шаблонов")
await message.answer(_("У вашего бота уже слишком много шаблонов"))
else:
answers = await bot.answers.filter(text=message.text)
if answers:
await message.answer("Такой текст уже есть в списке шаблонов")
await message.answer(_("Такой текст уже есть в списке шаблонов"))
else:
template = DefaultAnswer(text=message.text, bot=bot)
await template.save()
@@ -377,7 +380,7 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon
bot_id = callback_data.get("bot_id")
bot = await Bot.get_or_none(id=bot_id)
if not bot or (await bot.owner).telegram_id != call.from_user.id:
await call.answer("У вас нет прав на этого бота", show_alert=True)
await call.answer(_("У вас нет прав на этого бота"), show_alert=True)
return
if level == "1":

View File

@@ -7,6 +7,7 @@ from aiogram.dispatcher import FSMContext
from textwrap import dedent
from olgram.settings import OlgramSettings
from olgram.utils.permissions import public
from locales.locale import _
from olgram.router import dp
@@ -19,9 +20,7 @@ async def start(message: types.Message, state: FSMContext):
"""
await state.reset_state()
# TODO: locale
await message.answer(dedent("""
await message.answer(dedent(_("""
Olgram Bot — это конструктор ботов обратной связи в Telegram. Подробнее \
<a href="https://olgram.readthedocs.io">читайте здесь</a>.
@@ -31,7 +30,7 @@ async def start(message: types.Message, state: FSMContext):
/mybots - управление ботами
/help - помощь
"""), parse_mode="html")
""")), parse_mode="html")
@dp.message_handler(commands=["help"], state="*")
@@ -40,11 +39,11 @@ async def help(message: types.Message, state: FSMContext):
"""
Команда /help
"""
await message.answer(dedent(f"""
await message.answer(dedent(_("""
Читайте инструкции на нашем сайте https://olgram.readthedocs.io
Техническая поддержка: @civsocit_feedback_bot
Версия {OlgramSettings.version()}
"""))
Версия {0}
""")).format(OlgramSettings.version()))
@dp.message_handler(commands=["chatid"], state="*")