mirror of
https://github.com/civsocit/olgram.git
synced 2025-12-19 17:46:17 +00:00
Compare commits
15 Commits
6789d23c28
...
mailing
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58f551c77d | ||
|
|
696bc5368b | ||
|
|
340246b937 | ||
|
|
bb1456dda1 | ||
|
|
756f0bd89a | ||
|
|
6acc2068de | ||
|
|
d478e9d8e9 | ||
|
|
52864ed729 | ||
|
|
ac09e42f94 | ||
|
|
afc5389520 | ||
|
|
30ab7c84b4 | ||
|
|
9d8f5a97f7 | ||
|
|
16e944707f | ||
|
|
9723c70deb | ||
|
|
6e2ee437ba |
@@ -49,3 +49,16 @@ Olgram пересылает сообщения так, чтобы сообщен
|
||||
|
||||
При включении этой опции пользователю запрещается отправлять больше одного сообщения в минуту. Используйте её, если
|
||||
не успеваете обрабатывать входящие сообщения.
|
||||
|
||||
.. _mailing:
|
||||
|
||||
Рассылка
|
||||
---------------
|
||||
|
||||
После включения этой опции ваш бот будет запоминать всех пользователей, которые пишут в ваш бот.
|
||||
Вы сможете запустить рассылку по этим пользователям.
|
||||
|
||||
.. note::
|
||||
|
||||
Включение этой опции меняет текст политики конфиденциальности вашего feedback бота (команда /security_policy)
|
||||
и может отпугнуть некоторых пользователей. Не включайте эту опцию без необходимости.
|
||||
|
||||
@@ -31,5 +31,5 @@ REDIS_PATH=redis://redis
|
||||
# Set log level, can be CRITICAL, ERROR, WARNING, INFO, DEBUG. By default it set to WARNING.
|
||||
LOGLEVEL=
|
||||
|
||||
# Uncomment this to switch bot language to Chinese
|
||||
# O_LANG=zh
|
||||
# Uncomment this to switch bot language to English
|
||||
# O_LANG=en
|
||||
|
||||
@@ -5,39 +5,88 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2022-04-11 17:53+0300\n"
|
||||
"PO-Revision-Date: 2022-04-11 18:14+0300\n"
|
||||
"POT-Creation-Date: 2022-09-02 05:02+0400\n"
|
||||
"PO-Revision-Date: 2022-09-02 05:07+0400\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: en_US\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 3.0\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: en_US\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 3.1\n"
|
||||
|
||||
#: olgram/commands/bot_actions.py:21
|
||||
#: olgram/commands/admin.py:21 olgram/commands/info.py:21
|
||||
#: olgram/commands/promo.py:23 olgram/commands/promo.py:39
|
||||
msgid "Недостаточно прав"
|
||||
msgstr "Not enough permissions"
|
||||
|
||||
#: olgram/commands/admin.py:27
|
||||
msgid "Нужно указать имя бота"
|
||||
msgstr "You need to specify the bot's name"
|
||||
|
||||
#: olgram/commands/admin.py:33
|
||||
msgid "Такого бота нет в системе"
|
||||
msgstr "There is no such bot"
|
||||
|
||||
#: olgram/commands/admin.py:39 olgram/commands/admin.py:53
|
||||
msgid "Пропустить"
|
||||
msgstr "Skip"
|
||||
|
||||
#: olgram/commands/admin.py:42
|
||||
msgid ""
|
||||
"Введите текст, который будет отправлен владельцу бота {0}. Напишите "
|
||||
"'Пропустить' чтобы отменить"
|
||||
msgstr ""
|
||||
"Enter the text that will be sent to the owner of the bot {0}. Write 'Skip' "
|
||||
"to cancel"
|
||||
|
||||
#: olgram/commands/admin.py:50
|
||||
msgid "Поддерживается только текст"
|
||||
msgstr "Only text is supported"
|
||||
|
||||
#: olgram/commands/admin.py:55 olgram/commands/admin.py:71
|
||||
msgid "Отменено"
|
||||
msgstr "Cancelled"
|
||||
|
||||
#: olgram/commands/admin.py:61 olgram/commands/admin.py:69
|
||||
msgid "Отправить"
|
||||
msgstr "Send"
|
||||
|
||||
#: olgram/commands/admin.py:62
|
||||
msgid "Отменить"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: olgram/commands/admin.py:81
|
||||
msgid "Отправлено"
|
||||
msgstr "Sent"
|
||||
|
||||
#: olgram/commands/bot_actions.py:22
|
||||
msgid "Бот удалён"
|
||||
msgstr "Bot removed"
|
||||
|
||||
#: olgram/commands/bot_actions.py:37 olgram/commands/bot_actions.py:49
|
||||
#: olgram/commands/bot_actions.py:38 olgram/commands/bot_actions.py:50
|
||||
msgid "Текст сброшен"
|
||||
msgstr ""
|
||||
msgstr "Text is reset"
|
||||
|
||||
#: olgram/commands/bot_actions.py:63
|
||||
#: olgram/commands/bot_actions.py:64
|
||||
msgid "Выбран личный чат"
|
||||
msgstr "Personal chat selected"
|
||||
|
||||
#: olgram/commands/bot_actions.py:68
|
||||
#: olgram/commands/bot_actions.py:77
|
||||
msgid "Бот вышел из чатов"
|
||||
msgstr "Bot leaved chats"
|
||||
|
||||
#: olgram/commands/bot_actions.py:83
|
||||
msgid "Нельзя привязать бота к этому чату"
|
||||
msgstr "You can't bind a bot to this chat room"
|
||||
|
||||
#: olgram/commands/bot_actions.py:72
|
||||
#: olgram/commands/bot_actions.py:87
|
||||
msgid "Выбран чат {0}"
|
||||
msgstr "Selected chat {0}"
|
||||
|
||||
#: olgram/commands/bots.py:42
|
||||
#: olgram/commands/bots.py:46
|
||||
msgid ""
|
||||
"У вас уже слишком много ботов. Удалите какой-нибудь свой бот из Olgram(/"
|
||||
"mybots -> (Выбрать бота) -> Удалить бот)"
|
||||
@@ -45,7 +94,7 @@ msgstr ""
|
||||
"You already have too many bots. Remove any of your bots from Olgram(/mybots -"
|
||||
"> (Select bot) -> Remove bot)"
|
||||
|
||||
#: olgram/commands/bots.py:46
|
||||
#: olgram/commands/bots.py:50
|
||||
msgid ""
|
||||
"\n"
|
||||
" Чтобы подключить бот, вам нужно выполнить три действия:\n"
|
||||
@@ -72,7 +121,7 @@ msgstr ""
|
||||
"Chatfuel, Livegram and others).\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:66
|
||||
#: olgram/commands/bots.py:70
|
||||
msgid ""
|
||||
"\n"
|
||||
" Это не токен бота.\n"
|
||||
@@ -88,7 +137,7 @@ msgstr ""
|
||||
"abc123_AbcdEFghijKLMnopqrstu12\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:73
|
||||
#: olgram/commands/bots.py:77
|
||||
msgid ""
|
||||
"\n"
|
||||
" Не удалось запустить этого бота: неверный токен\n"
|
||||
@@ -98,7 +147,7 @@ msgstr ""
|
||||
" Failed to start this bot: Wrong token\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:78
|
||||
#: olgram/commands/bots.py:82
|
||||
msgid ""
|
||||
"\n"
|
||||
" Не удалось запустить этого бота: непредвиденная ошибка\n"
|
||||
@@ -108,7 +157,7 @@ msgstr ""
|
||||
" Failed to start this bot: unexpected error\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:83
|
||||
#: olgram/commands/bots.py:87
|
||||
msgid ""
|
||||
"\n"
|
||||
" Такой бот уже есть в базе данных\n"
|
||||
@@ -118,35 +167,34 @@ msgstr ""
|
||||
" Such a bot is already in the database\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:115
|
||||
#: olgram/commands/bots.py:122
|
||||
msgid "Бот добавлен! Список ваших ботов: /mybots"
|
||||
msgstr "Bot added! List of your bots: /mybots"
|
||||
|
||||
#: olgram/commands/info.py:21 olgram/commands/promo.py:23
|
||||
#: olgram/commands/promo.py:39
|
||||
msgid "Недостаточно прав"
|
||||
msgstr "Not enough permissions"
|
||||
|
||||
#: olgram/commands/info.py:32
|
||||
#: olgram/commands/info.py:34
|
||||
msgid "Количество ботов: {0}\n"
|
||||
msgstr "Number of bots: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:33
|
||||
#: olgram/commands/info.py:35
|
||||
msgid "Количество пользователей (у конструктора): {0}\n"
|
||||
msgstr "Number of users (at the constructor): {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:34
|
||||
#: olgram/commands/info.py:36
|
||||
msgid "Шаблонов ответов: {0}\n"
|
||||
msgstr "Answer templates: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:35
|
||||
#: olgram/commands/info.py:37
|
||||
msgid "Входящих сообщений у всех ботов: {0}\n"
|
||||
msgstr "Incoming messages from all bots: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:36
|
||||
#: olgram/commands/info.py:38
|
||||
msgid "Исходящих сообщений у всех ботов: {0}\n"
|
||||
msgstr "All bots have outgoing messages: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:39
|
||||
msgid "Промо-кодов выдано: {0}\n"
|
||||
msgstr "Promo codes issued: {0}\n"
|
||||
|
||||
#: olgram/commands/menu.py:31
|
||||
msgid ""
|
||||
"\n"
|
||||
@@ -167,15 +215,19 @@ msgstr "Your bots"
|
||||
|
||||
#: olgram/commands/menu.py:67
|
||||
msgid "Личные сообщения"
|
||||
msgstr "Личные сообщения"
|
||||
msgstr "Personal messages"
|
||||
|
||||
#: olgram/commands/menu.py:72 olgram/commands/menu.py:117
|
||||
#: olgram/commands/menu.py:143 olgram/commands/menu.py:174
|
||||
#: olgram/commands/menu.py:235
|
||||
#: olgram/commands/menu.py:72
|
||||
msgid "❗️ Выйти из всех чатов"
|
||||
msgstr "❗️ Leave all chats"
|
||||
|
||||
#: olgram/commands/menu.py:77 olgram/commands/menu.py:122
|
||||
#: olgram/commands/menu.py:148 olgram/commands/menu.py:184
|
||||
#: olgram/commands/menu.py:247
|
||||
msgid "<< Назад"
|
||||
msgstr "<< Back"
|
||||
|
||||
#: olgram/commands/menu.py:78
|
||||
#: olgram/commands/menu.py:83
|
||||
msgid ""
|
||||
"\n"
|
||||
" Этот бот не добавлен в чаты, поэтому все сообщения будут приходить "
|
||||
@@ -197,7 +249,7 @@ msgstr ""
|
||||
" again.\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:85
|
||||
#: olgram/commands/menu.py:90
|
||||
msgid ""
|
||||
"\n"
|
||||
" В этом разделе вы можете привязать бота @{0} к чату.\n"
|
||||
@@ -209,27 +261,27 @@ msgstr ""
|
||||
" Select the chat room where the bot will forward messages.\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:97
|
||||
#: olgram/commands/menu.py:102
|
||||
msgid "Текст"
|
||||
msgstr "Text"
|
||||
|
||||
#: olgram/commands/menu.py:102
|
||||
#: olgram/commands/menu.py:107
|
||||
msgid "Чат"
|
||||
msgstr "Chat"
|
||||
|
||||
#: olgram/commands/menu.py:107
|
||||
#: olgram/commands/menu.py:112
|
||||
msgid "Удалить бот"
|
||||
msgstr "Delete bot"
|
||||
|
||||
#: olgram/commands/menu.py:112
|
||||
#: olgram/commands/menu.py:117
|
||||
msgid "Статистика"
|
||||
msgstr "Statistics"
|
||||
|
||||
#: olgram/commands/menu.py:121
|
||||
#: olgram/commands/menu.py:126
|
||||
msgid "Опции"
|
||||
msgstr "Options"
|
||||
|
||||
#: olgram/commands/menu.py:126
|
||||
#: olgram/commands/menu.py:131
|
||||
msgid ""
|
||||
"\n"
|
||||
" Управление ботом @{0}.\n"
|
||||
@@ -247,11 +299,11 @@ msgstr ""
|
||||
" @civsocit_feedback_bot\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:138
|
||||
#: olgram/commands/menu.py:143
|
||||
msgid "Да, удалить бот"
|
||||
msgstr "Yes, delete the bot"
|
||||
|
||||
#: olgram/commands/menu.py:147
|
||||
#: olgram/commands/menu.py:152
|
||||
msgid ""
|
||||
"\n"
|
||||
" Вы уверены, что хотите удалить бота @{0}?\n"
|
||||
@@ -261,68 +313,87 @@ msgstr ""
|
||||
" Are you sure you want to delete the bot @{0}?\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:156
|
||||
#: olgram/commands/menu.py:161
|
||||
msgid "Потоки сообщений"
|
||||
msgstr "Message threads"
|
||||
|
||||
#: olgram/commands/menu.py:161
|
||||
#: olgram/commands/menu.py:166
|
||||
msgid "Данные пользователя"
|
||||
msgstr "User data"
|
||||
|
||||
#: olgram/commands/menu.py:168
|
||||
#: olgram/commands/menu.py:171
|
||||
msgid "Антифлуд"
|
||||
msgstr "Antiflood"
|
||||
|
||||
#: olgram/commands/menu.py:178
|
||||
msgid "Olgram подпись"
|
||||
msgstr "Olgram signature"
|
||||
|
||||
#: olgram/commands/menu.py:179 olgram/commands/menu.py:180
|
||||
#: olgram/commands/menu.py:189 olgram/commands/menu.py:190
|
||||
msgid "включены"
|
||||
msgstr "enabled"
|
||||
|
||||
#: olgram/commands/menu.py:179 olgram/commands/menu.py:180
|
||||
#: olgram/commands/menu.py:189 olgram/commands/menu.py:190
|
||||
msgid "выключены"
|
||||
msgstr "disabled"
|
||||
|
||||
#: olgram/commands/menu.py:181
|
||||
#: olgram/commands/menu.py:191
|
||||
#, fuzzy
|
||||
#| msgid "включены"
|
||||
msgid "включен"
|
||||
msgstr "enabled"
|
||||
|
||||
#: olgram/commands/menu.py:191
|
||||
#, fuzzy
|
||||
#| msgid "выключены"
|
||||
msgid "выключен"
|
||||
msgstr "disabled"
|
||||
|
||||
#: olgram/commands/menu.py:192
|
||||
msgid ""
|
||||
"\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#threads"
|
||||
"\">Потоки сообщений</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-info"
|
||||
"\">Данные пользователя</a>: <b>{1}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#threads\">Потоки сообщений</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-"
|
||||
"info\">Данные пользователя</a>: <b>{1}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#antiflood\">Антифлуд</a>: <b>{2}</b>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#threads"
|
||||
"\">Потоки сообщений</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-info"
|
||||
"\">Данные пользователя</a>: <b>{1}</b>\n"
|
||||
" "
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#threads\">Threads</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-"
|
||||
"info\">User data</a>: <b>{1}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#antiflood\">Antiflood</a>: <b>{2}</b>"
|
||||
|
||||
#: olgram/commands/menu.py:187
|
||||
#: olgram/commands/menu.py:199
|
||||
msgid "включена"
|
||||
msgstr "enabled"
|
||||
|
||||
#: olgram/commands/menu.py:187
|
||||
#: olgram/commands/menu.py:199
|
||||
msgid "выключена"
|
||||
msgstr "disabled"
|
||||
|
||||
#: olgram/commands/menu.py:188
|
||||
#: olgram/commands/menu.py:200
|
||||
msgid "Olgram подпись: <b>{0}</b>"
|
||||
msgstr "Olgram signature: <b>{0}</b>"
|
||||
|
||||
#: olgram/commands/menu.py:198 olgram/commands/menu.py:260
|
||||
#: olgram/commands/menu.py:302
|
||||
#: olgram/commands/menu.py:210 olgram/commands/menu.py:272
|
||||
#: olgram/commands/menu.py:314
|
||||
msgid "<< Завершить редактирование"
|
||||
msgstr "<< Finish editing"
|
||||
|
||||
#: olgram/commands/menu.py:202
|
||||
#: olgram/commands/menu.py:214
|
||||
msgid "Автоответчик"
|
||||
msgstr "Autoresponder"
|
||||
|
||||
#: olgram/commands/menu.py:207 olgram/commands/menu.py:274
|
||||
#: olgram/commands/menu.py:219 olgram/commands/menu.py:286
|
||||
msgid "Сбросить текст"
|
||||
msgstr "Reset text"
|
||||
|
||||
#: olgram/commands/menu.py:212
|
||||
#: olgram/commands/menu.py:224
|
||||
msgid ""
|
||||
"\n"
|
||||
" Сейчас вы редактируете текст, который отправляется после того, как "
|
||||
@@ -348,7 +419,7 @@ msgstr ""
|
||||
" Send a message to change the text.\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:239
|
||||
#: olgram/commands/menu.py:251
|
||||
msgid ""
|
||||
"\n"
|
||||
" Статистика по боту @{0}\n"
|
||||
@@ -368,15 +439,15 @@ msgstr ""
|
||||
" Banned users: <b>{4}</b>\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:264
|
||||
#: olgram/commands/menu.py:276
|
||||
msgid "Предыдущий текст"
|
||||
msgstr "Previous text"
|
||||
|
||||
#: olgram/commands/menu.py:269
|
||||
#: olgram/commands/menu.py:281
|
||||
msgid "Шаблоны ответов..."
|
||||
msgstr "Answer templates..."
|
||||
|
||||
#: olgram/commands/menu.py:279
|
||||
#: olgram/commands/menu.py:291
|
||||
msgid ""
|
||||
"\n"
|
||||
" Сейчас вы редактируете текст автоответчика. Это сообщение отправляется в "
|
||||
@@ -402,11 +473,11 @@ msgstr ""
|
||||
" Send a message to change the text.\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:289
|
||||
#: olgram/commands/menu.py:301
|
||||
msgid "(отключено)"
|
||||
msgstr "(disabled)"
|
||||
|
||||
#: olgram/commands/menu.py:306
|
||||
#: olgram/commands/menu.py:318
|
||||
msgid ""
|
||||
"\n"
|
||||
" Сейчас вы редактируете шаблоны ответов для @{0}. Текущие шаблоны:\n"
|
||||
@@ -432,27 +503,27 @@ msgstr ""
|
||||
" To remove a template from the list, send its number in the list (for "
|
||||
"example, 4) "
|
||||
|
||||
#: olgram/commands/menu.py:325
|
||||
#: olgram/commands/menu.py:337
|
||||
msgid "(нет шаблонов)"
|
||||
msgstr "(no templates)"
|
||||
|
||||
#: olgram/commands/menu.py:364
|
||||
#: olgram/commands/menu.py:376
|
||||
msgid "У вас нет шаблонов, чтобы их удалять"
|
||||
msgstr "You don't have templates to delete them"
|
||||
|
||||
#: olgram/commands/menu.py:366
|
||||
#: olgram/commands/menu.py:378
|
||||
msgid "Неправильное число. Чтобы удалить шаблон, введите число от 0 до {0}"
|
||||
msgstr "To delete a template, enter a number between 0 and {0}"
|
||||
|
||||
#: olgram/commands/menu.py:374
|
||||
#: olgram/commands/menu.py:386
|
||||
msgid "У вашего бота уже слишком много шаблонов"
|
||||
msgstr "Your bot already has too many templates"
|
||||
|
||||
#: olgram/commands/menu.py:378
|
||||
#: olgram/commands/menu.py:390
|
||||
msgid "Такой текст уже есть в списке шаблонов"
|
||||
msgstr "This text is already in the list of templates"
|
||||
|
||||
#: olgram/commands/menu.py:396
|
||||
#: olgram/commands/menu.py:408
|
||||
msgid "У вас нет прав на этого бота"
|
||||
msgstr "You have no permissions to this bot"
|
||||
|
||||
@@ -472,34 +543,35 @@ msgstr "Incorrect token"
|
||||
msgid "Такого кода не существует"
|
||||
msgstr "There is no such code"
|
||||
|
||||
#: olgram/commands/promo.py:53
|
||||
#: olgram/commands/promo.py:59
|
||||
msgid "Промокод отозван"
|
||||
msgstr "Promotion code withdrawn"
|
||||
|
||||
#: olgram/commands/promo.py:64
|
||||
#: olgram/commands/promo.py:70
|
||||
msgid ""
|
||||
"Укажите аргумент: промокод. Например: <pre>/set_promo my-promo-code</pre>"
|
||||
"Укажите аргумент: промокод. Например: <pre>/setpromo my-promo-code</pre>"
|
||||
msgstr ""
|
||||
"Specify the argument: promo code. For example: <pre>/set_promo my-promo-"
|
||||
"Specify the argument: promo code. For example: <pre>/setpromo my-promo-"
|
||||
"code</pre>"
|
||||
|
||||
#: olgram/commands/promo.py:72 olgram/commands/promo.py:76
|
||||
#: olgram/commands/promo.py:78 olgram/commands/promo.py:82
|
||||
msgid "Промокод не найден"
|
||||
msgstr "Promo code not found"
|
||||
|
||||
#: olgram/commands/promo.py:79
|
||||
#: olgram/commands/promo.py:85
|
||||
msgid "Промокод уже использован"
|
||||
msgstr "Promo code has already been used"
|
||||
|
||||
#: olgram/commands/promo.py:85
|
||||
#: olgram/commands/promo.py:91
|
||||
msgid "Промокод активирован! Спасибо 🙌"
|
||||
msgstr "Promo code activated! Thank you 🙌"
|
||||
|
||||
#: olgram/commands/start.py:25
|
||||
#: olgram/commands/start.py:23
|
||||
msgid ""
|
||||
"\n"
|
||||
" Olgram Bot — это конструктор ботов обратной связи в Telegram. Подробнее "
|
||||
"<a href=\"https://olgram.readthedocs.io\">читайте здесь</a>.\n"
|
||||
"<a href=\"https://olgram.readthedocs.io\">читайте здесь</a>. Следите за "
|
||||
"обновлениями <a href=\"https://t.me/civsoc_it\">здесь</a>.\n"
|
||||
"\n"
|
||||
" Используйте эти команды, чтобы управлять этим ботом:\n"
|
||||
"\n"
|
||||
@@ -510,18 +582,18 @@ msgid ""
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Olgram Bot — это конструктор ботов обратной связи в Telegram. Подробнее "
|
||||
"<a href=\"https://olgram.readthedocs.io\">читайте здесь</a>.\n"
|
||||
" Olgram Bot is a feedback bot contructor for Telegram. More info <a "
|
||||
"href=\"https://olgram.readthedocs.io\">here</a>.\n"
|
||||
"\n"
|
||||
" Используйте эти команды, чтобы управлять этим ботом:\n"
|
||||
" Use that commands to control bot:\n"
|
||||
"\n"
|
||||
" /addbot - добавить бот\n"
|
||||
" /mybots - управление ботами\n"
|
||||
" /addbot - add bot\n"
|
||||
" /mybots - bot control\n"
|
||||
"\n"
|
||||
" /help - помощь\n"
|
||||
" /help - help\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/start.py:44
|
||||
#: olgram/commands/start.py:43
|
||||
msgid ""
|
||||
"\n"
|
||||
" Читайте инструкции на нашем сайте https://olgram.readthedocs.io\n"
|
||||
@@ -555,7 +627,7 @@ msgstr "The bot owner has restricted access to this functionality 😞"
|
||||
msgid "Владелец бота ограничил доступ к этому функционалу😞"
|
||||
msgstr "The owner of the bot has restricted access to this function😞"
|
||||
|
||||
#: server/custom.py:47
|
||||
#: server/custom.py:55
|
||||
msgid ""
|
||||
"<b>Политика конфиденциальности</b>\n"
|
||||
"\n"
|
||||
@@ -574,7 +646,7 @@ msgstr ""
|
||||
"communicating with the operator; Olgram bots do not do mass mailings.\n"
|
||||
"\n"
|
||||
|
||||
#: server/custom.py:53
|
||||
#: server/custom.py:61
|
||||
msgid ""
|
||||
"При отправке сообщения (кроме команд /start и /security_policy) оператор "
|
||||
"<b>видит</b> ваши имя пользователя, @username и идентификатор пользователя в "
|
||||
@@ -584,7 +656,7 @@ msgstr ""
|
||||
"<b>sees</b> your username, @username and user ID by virtue of the settings "
|
||||
"that the operator specified when creating the bot."
|
||||
|
||||
#: server/custom.py:57
|
||||
#: server/custom.py:65
|
||||
msgid ""
|
||||
"В зависимости от ваших настроек конфиденциальности Telegram, оператор может "
|
||||
"видеть ваш username, имя пользователя и другую информацию."
|
||||
@@ -592,34 +664,42 @@ msgstr ""
|
||||
"Depending on your Telegram privacy settings, the operator may see your "
|
||||
"username, username and other information."
|
||||
|
||||
#: server/custom.py:68
|
||||
#: server/custom.py:76
|
||||
msgid "Сообщение от пользователя "
|
||||
msgstr "Message from the user "
|
||||
|
||||
#: server/custom.py:96
|
||||
#: server/custom.py:135
|
||||
msgid "Вы заблокированы в этом боте"
|
||||
msgstr "You are blocked in this bot"
|
||||
|
||||
#: server/custom.py:142
|
||||
#: server/custom.py:141
|
||||
msgid "Слишком много сообщений, подождите одну минуту"
|
||||
msgstr "Too many messages, wait one minute"
|
||||
|
||||
#: server/custom.py:148
|
||||
msgid "Не удаётся связаться с владельцем бота"
|
||||
msgstr "Cannot contact the owner of the bot"
|
||||
|
||||
#: server/custom.py:179
|
||||
msgid ""
|
||||
"<i>Невозможно переслать сообщение: автор не найден (сообщение слишком "
|
||||
"старое?)</i>"
|
||||
msgstr ""
|
||||
"<i>Cannot forward this message: author not found (message too old?)</i>"
|
||||
|
||||
#: server/custom.py:150
|
||||
#: server/custom.py:187
|
||||
msgid "Пользователь заблокирован"
|
||||
msgstr "User is blocked"
|
||||
|
||||
#: server/custom.py:155
|
||||
#: server/custom.py:192
|
||||
msgid "Пользователь не был забанен"
|
||||
msgstr "The user was not banned"
|
||||
|
||||
#: server/custom.py:158
|
||||
#: server/custom.py:195
|
||||
msgid "Пользователь разбанен"
|
||||
msgstr "A user has been unlocked"
|
||||
|
||||
#: server/custom.py:163
|
||||
#: server/custom.py:200
|
||||
msgid "<i>Невозможно переслать сообщение (автор заблокировал бота?)</i>"
|
||||
msgstr "<i>Cannot forward the message (has the author blocked the bot?)</i>"
|
||||
|
||||
@@ -631,21 +711,11 @@ msgstr "(Re)launch the bot"
|
||||
msgid "Политика конфиденциальности"
|
||||
msgstr "Privacy Policy"
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Этот бот создан с помощью @OlgramBot"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\n"
|
||||
"This bot was created using @OlgramBot"
|
||||
|
||||
|
||||
msgid "Не удаётся связаться с владельцем бота"
|
||||
msgstr "Cannot contact the owner of the bot"
|
||||
|
||||
msgid "Слишком много сообщений, подождите одну минуту"
|
||||
msgstr "Too many messages, wait one minute"
|
||||
|
||||
msgid "Антифлуд"
|
||||
msgstr "Antiflood"
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ "\n"
|
||||
#~ "Этот бот создан с помощью @OlgramBot"
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "\n"
|
||||
#~ "This bot was created using @OlgramBot"
|
||||
|
||||
@@ -5,40 +5,89 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2022-04-09 06:24+0300\n"
|
||||
"PO-Revision-Date: 2022-04-09 07:11+0300\n"
|
||||
"POT-Creation-Date: 2022-09-02 05:07+0400\n"
|
||||
"PO-Revision-Date: 2022-09-02 05:12+0400\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: uk_UA\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 3.0\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
|
||||
"Language: uk_UA\n"
|
||||
"X-Generator: Poedit 3.1\n"
|
||||
|
||||
#: olgram/commands/bot_actions.py:21
|
||||
#: olgram/commands/admin.py:21 olgram/commands/info.py:21
|
||||
#: olgram/commands/promo.py:23 olgram/commands/promo.py:39
|
||||
msgid "Недостаточно прав"
|
||||
msgstr "Недостатньо прав"
|
||||
|
||||
#: olgram/commands/admin.py:27
|
||||
msgid "Нужно указать имя бота"
|
||||
msgstr "Потрібно вказати ім'я бота"
|
||||
|
||||
#: olgram/commands/admin.py:33
|
||||
msgid "Такого бота нет в системе"
|
||||
msgstr "Такого бота немає в системі"
|
||||
|
||||
#: olgram/commands/admin.py:39 olgram/commands/admin.py:53
|
||||
msgid "Пропустить"
|
||||
msgstr "Пропустити"
|
||||
|
||||
#: olgram/commands/admin.py:42
|
||||
msgid ""
|
||||
"Введите текст, который будет отправлен владельцу бота {0}. Напишите "
|
||||
"'Пропустить' чтобы отменить"
|
||||
msgstr ""
|
||||
"Введіть текст, який буде надіслано власнику бота {0}. Напишіть 'Пропустити', "
|
||||
"щоб скасувати"
|
||||
|
||||
#: olgram/commands/admin.py:50
|
||||
msgid "Поддерживается только текст"
|
||||
msgstr "Підтримується лише текст"
|
||||
|
||||
#: olgram/commands/admin.py:55 olgram/commands/admin.py:71
|
||||
msgid "Отменено"
|
||||
msgstr "Скасовано"
|
||||
|
||||
#: olgram/commands/admin.py:61 olgram/commands/admin.py:69
|
||||
msgid "Отправить"
|
||||
msgstr "Надіслати"
|
||||
|
||||
#: olgram/commands/admin.py:62
|
||||
msgid "Отменить"
|
||||
msgstr "Скасувати"
|
||||
|
||||
#: olgram/commands/admin.py:81
|
||||
msgid "Отправлено"
|
||||
msgstr "Надіслано"
|
||||
|
||||
#: olgram/commands/bot_actions.py:22
|
||||
msgid "Бот удалён"
|
||||
msgstr "Бот видалений"
|
||||
|
||||
#: olgram/commands/bot_actions.py:37 olgram/commands/bot_actions.py:49
|
||||
#: olgram/commands/bot_actions.py:38 olgram/commands/bot_actions.py:50
|
||||
msgid "Текст сброшен"
|
||||
msgstr "Текст скинутий"
|
||||
|
||||
#: olgram/commands/bot_actions.py:63
|
||||
#: olgram/commands/bot_actions.py:64
|
||||
msgid "Выбран личный чат"
|
||||
msgstr "Вибраний особистий чат"
|
||||
|
||||
#: olgram/commands/bot_actions.py:68
|
||||
msgid "Нельзя привязать бота к этому чату"
|
||||
msgstr "Нельзя привязать бота к этому чату"
|
||||
#: olgram/commands/bot_actions.py:77
|
||||
msgid "Бот вышел из чатов"
|
||||
msgstr "Бот вийшов із чатів"
|
||||
|
||||
#: olgram/commands/bot_actions.py:72
|
||||
#: olgram/commands/bot_actions.py:83
|
||||
msgid "Нельзя привязать бота к этому чату"
|
||||
msgstr "Не можна прив'язати робота до цього чату"
|
||||
|
||||
#: olgram/commands/bot_actions.py:87
|
||||
msgid "Выбран чат {0}"
|
||||
msgstr "Вибраний чат {0}"
|
||||
|
||||
#: olgram/commands/bots.py:42
|
||||
#: olgram/commands/bots.py:46
|
||||
msgid ""
|
||||
"У вас уже слишком много ботов. Удалите какой-нибудь свой бот из Olgram(/"
|
||||
"mybots -> (Выбрать бота) -> Удалить бот)"
|
||||
@@ -46,7 +95,7 @@ msgstr ""
|
||||
"У вас вже надто багато роботів. Видаліть якийсь свій бот з Olgram(/mybots -> "
|
||||
"(Вибрати бота) -> Видалити бот)"
|
||||
|
||||
#: olgram/commands/bots.py:46
|
||||
#: olgram/commands/bots.py:50
|
||||
msgid ""
|
||||
"\n"
|
||||
" Чтобы подключить бот, вам нужно выполнить три действия:\n"
|
||||
@@ -75,7 +124,7 @@ msgstr ""
|
||||
" \n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:66
|
||||
#: olgram/commands/bots.py:70
|
||||
msgid ""
|
||||
"\n"
|
||||
" Это не токен бота.\n"
|
||||
@@ -91,7 +140,7 @@ msgstr ""
|
||||
"abc123_AbcdEFghijKLMnopqrstu12\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:73
|
||||
#: olgram/commands/bots.py:77
|
||||
msgid ""
|
||||
"\n"
|
||||
" Не удалось запустить этого бота: неверный токен\n"
|
||||
@@ -101,7 +150,7 @@ msgstr ""
|
||||
" Не вдалося запустити цього бота: неправильний токен\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:78
|
||||
#: olgram/commands/bots.py:82
|
||||
msgid ""
|
||||
"\n"
|
||||
" Не удалось запустить этого бота: непредвиденная ошибка\n"
|
||||
@@ -111,7 +160,7 @@ msgstr ""
|
||||
" Не вдалося запустити цього бота: непередбачена помилка\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:83
|
||||
#: olgram/commands/bots.py:87
|
||||
msgid ""
|
||||
"\n"
|
||||
" Такой бот уже есть в базе данных\n"
|
||||
@@ -121,35 +170,34 @@ msgstr ""
|
||||
" Такий бот вже є у базі даних\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/bots.py:115
|
||||
#: olgram/commands/bots.py:122
|
||||
msgid "Бот добавлен! Список ваших ботов: /mybots"
|
||||
msgstr "Бот доданий! Список ваших роботів: /mybots"
|
||||
|
||||
#: olgram/commands/info.py:21 olgram/commands/promo.py:23
|
||||
#: olgram/commands/promo.py:39
|
||||
msgid "Недостаточно прав"
|
||||
msgstr "Недостатньо прав"
|
||||
|
||||
#: olgram/commands/info.py:32
|
||||
#: olgram/commands/info.py:34
|
||||
msgid "Количество ботов: {0}\n"
|
||||
msgstr "Кількість ботів: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:33
|
||||
#: olgram/commands/info.py:35
|
||||
msgid "Количество пользователей (у конструктора): {0}\n"
|
||||
msgstr "Кількість користувачів (у конструктора): {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:34
|
||||
#: olgram/commands/info.py:36
|
||||
msgid "Шаблонов ответов: {0}\n"
|
||||
msgstr "Шаблонів відповідей: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:35
|
||||
#: olgram/commands/info.py:37
|
||||
msgid "Входящих сообщений у всех ботов: {0}\n"
|
||||
msgstr "Вхідних повідомлень у всіх роботів: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:36
|
||||
#: olgram/commands/info.py:38
|
||||
msgid "Исходящих сообщений у всех ботов: {0}\n"
|
||||
msgstr "Вихідних повідомлень у всіх роботів: {0}\n"
|
||||
|
||||
#: olgram/commands/info.py:39
|
||||
msgid "Промо-кодов выдано: {0}\n"
|
||||
msgstr "Промо-кодів видано: {0}\n"
|
||||
|
||||
#: olgram/commands/menu.py:31
|
||||
msgid ""
|
||||
"\n"
|
||||
@@ -173,13 +221,17 @@ msgstr "Ваші боти"
|
||||
msgid "Личные сообщения"
|
||||
msgstr "Особисті повідомлення"
|
||||
|
||||
#: olgram/commands/menu.py:72 olgram/commands/menu.py:117
|
||||
#: olgram/commands/menu.py:143 olgram/commands/menu.py:174
|
||||
#: olgram/commands/menu.py:235
|
||||
#: olgram/commands/menu.py:72
|
||||
msgid "❗️ Выйти из всех чатов"
|
||||
msgstr "❗️ Вийти зі всіх чатів"
|
||||
|
||||
#: olgram/commands/menu.py:77 olgram/commands/menu.py:122
|
||||
#: olgram/commands/menu.py:148 olgram/commands/menu.py:184
|
||||
#: olgram/commands/menu.py:247
|
||||
msgid "<< Назад"
|
||||
msgstr "<< Назад"
|
||||
|
||||
#: olgram/commands/menu.py:78
|
||||
#: olgram/commands/menu.py:83
|
||||
msgid ""
|
||||
"\n"
|
||||
" Этот бот не добавлен в чаты, поэтому все сообщения будут приходить "
|
||||
@@ -202,7 +254,7 @@ msgstr ""
|
||||
" \n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:85
|
||||
#: olgram/commands/menu.py:90
|
||||
msgid ""
|
||||
"\n"
|
||||
" В этом разделе вы можете привязать бота @{0} к чату.\n"
|
||||
@@ -215,27 +267,27 @@ msgstr ""
|
||||
" \n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:97
|
||||
#: olgram/commands/menu.py:102
|
||||
msgid "Текст"
|
||||
msgstr "Текст"
|
||||
|
||||
#: olgram/commands/menu.py:102
|
||||
#: olgram/commands/menu.py:107
|
||||
msgid "Чат"
|
||||
msgstr "Чат"
|
||||
|
||||
#: olgram/commands/menu.py:107
|
||||
#: olgram/commands/menu.py:112
|
||||
msgid "Удалить бот"
|
||||
msgstr "Видалити бот"
|
||||
|
||||
#: olgram/commands/menu.py:112
|
||||
#: olgram/commands/menu.py:117
|
||||
msgid "Статистика"
|
||||
msgstr "Статистика"
|
||||
|
||||
#: olgram/commands/menu.py:121
|
||||
#: olgram/commands/menu.py:126
|
||||
msgid "Опции"
|
||||
msgstr "Опції"
|
||||
|
||||
#: olgram/commands/menu.py:126
|
||||
#: olgram/commands/menu.py:131
|
||||
msgid ""
|
||||
"\n"
|
||||
" Управление ботом @{0}.\n"
|
||||
@@ -253,11 +305,11 @@ msgstr ""
|
||||
" @civsocit_feedback_bot\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:138
|
||||
#: olgram/commands/menu.py:143
|
||||
msgid "Да, удалить бот"
|
||||
msgstr "Так, видалити бот"
|
||||
|
||||
#: olgram/commands/menu.py:147
|
||||
#: olgram/commands/menu.py:152
|
||||
msgid ""
|
||||
"\n"
|
||||
" Вы уверены, что хотите удалить бота @{0}?\n"
|
||||
@@ -267,68 +319,87 @@ msgstr ""
|
||||
" Ви впевнені, що хочете видалити бота @{0}?\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:156
|
||||
#: olgram/commands/menu.py:161
|
||||
msgid "Потоки сообщений"
|
||||
msgstr "Потоки повідомлень"
|
||||
|
||||
#: olgram/commands/menu.py:161
|
||||
#: olgram/commands/menu.py:166
|
||||
msgid "Данные пользователя"
|
||||
msgstr "Дані користувача"
|
||||
|
||||
#: olgram/commands/menu.py:168
|
||||
#: olgram/commands/menu.py:171
|
||||
msgid "Антифлуд"
|
||||
msgstr "Антифлуд"
|
||||
|
||||
#: olgram/commands/menu.py:178
|
||||
msgid "Olgram подпись"
|
||||
msgstr "Olgram підпис"
|
||||
|
||||
#: olgram/commands/menu.py:179 olgram/commands/menu.py:180
|
||||
#: olgram/commands/menu.py:189 olgram/commands/menu.py:190
|
||||
msgid "включены"
|
||||
msgstr "включені"
|
||||
|
||||
#: olgram/commands/menu.py:179 olgram/commands/menu.py:180
|
||||
#: olgram/commands/menu.py:189 olgram/commands/menu.py:190
|
||||
msgid "выключены"
|
||||
msgstr "вимкнені"
|
||||
|
||||
#: olgram/commands/menu.py:181
|
||||
#: olgram/commands/menu.py:191
|
||||
#, fuzzy
|
||||
#| msgid "включены"
|
||||
msgid "включен"
|
||||
msgstr "включені"
|
||||
|
||||
#: olgram/commands/menu.py:191
|
||||
#, fuzzy
|
||||
#| msgid "выключены"
|
||||
msgid "выключен"
|
||||
msgstr "вимкнені"
|
||||
|
||||
#: olgram/commands/menu.py:192
|
||||
msgid ""
|
||||
"\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#threads"
|
||||
"\">Потоки сообщений</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-info"
|
||||
"\">Данные пользователя</a>: <b>{1}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#threads\">Потоки сообщений</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-"
|
||||
"info\">Данные пользователя</a>: <b>{1}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#antiflood\">Антифлуд</a>: <b>{2}</b>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#threads"
|
||||
"\">Потоки повідомлень</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-info"
|
||||
"\">Дані користувача</a>: <b>{1}</b>\n"
|
||||
" "
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#threads\">Потоки повідомлень</a>: <b>{0}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options.html#user-"
|
||||
"info\">Дані користувача</a>: <b>{1}</b>\n"
|
||||
" <a href=\"https://olgram.readthedocs.io/ru/latest/options."
|
||||
"html#antiflood\">Anti-flood</a>: <b>{2}</b>"
|
||||
|
||||
#: olgram/commands/menu.py:187
|
||||
#: olgram/commands/menu.py:199
|
||||
msgid "включена"
|
||||
msgstr "включена"
|
||||
|
||||
#: olgram/commands/menu.py:187
|
||||
#: olgram/commands/menu.py:199
|
||||
msgid "выключена"
|
||||
msgstr "выключена"
|
||||
msgstr "вимкнена"
|
||||
|
||||
#: olgram/commands/menu.py:188
|
||||
#: olgram/commands/menu.py:200
|
||||
msgid "Olgram подпись: <b>{0}</b>"
|
||||
msgstr "Olgram підпис: <b>{0}</b>"
|
||||
|
||||
#: olgram/commands/menu.py:198 olgram/commands/menu.py:260
|
||||
#: olgram/commands/menu.py:302
|
||||
#: olgram/commands/menu.py:210 olgram/commands/menu.py:272
|
||||
#: olgram/commands/menu.py:314
|
||||
msgid "<< Завершить редактирование"
|
||||
msgstr "<< Завершити редагування"
|
||||
|
||||
#: olgram/commands/menu.py:202
|
||||
#: olgram/commands/menu.py:214
|
||||
msgid "Автоответчик"
|
||||
msgstr "Автовідповідач"
|
||||
|
||||
#: olgram/commands/menu.py:207 olgram/commands/menu.py:274
|
||||
#: olgram/commands/menu.py:219 olgram/commands/menu.py:286
|
||||
msgid "Сбросить текст"
|
||||
msgstr "Скинути текст"
|
||||
|
||||
#: olgram/commands/menu.py:212
|
||||
#: olgram/commands/menu.py:224
|
||||
msgid ""
|
||||
"\n"
|
||||
" Сейчас вы редактируете текст, который отправляется после того, как "
|
||||
@@ -355,7 +426,7 @@ msgstr ""
|
||||
" \n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:239
|
||||
#: olgram/commands/menu.py:251
|
||||
msgid ""
|
||||
"\n"
|
||||
" Статистика по боту @{0}\n"
|
||||
@@ -375,15 +446,15 @@ msgstr ""
|
||||
" Забанено користувачів: <b>{4}</b>\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:264
|
||||
#: olgram/commands/menu.py:276
|
||||
msgid "Предыдущий текст"
|
||||
msgstr "Попередній текст"
|
||||
|
||||
#: olgram/commands/menu.py:269
|
||||
#: olgram/commands/menu.py:281
|
||||
msgid "Шаблоны ответов..."
|
||||
msgstr "Шаблони відповідей..."
|
||||
|
||||
#: olgram/commands/menu.py:279
|
||||
#: olgram/commands/menu.py:291
|
||||
msgid ""
|
||||
"\n"
|
||||
" Сейчас вы редактируете текст автоответчика. Это сообщение отправляется в "
|
||||
@@ -409,11 +480,11 @@ msgstr ""
|
||||
" Надішліть повідомлення, щоб змінити текст.\n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:289
|
||||
#: olgram/commands/menu.py:301
|
||||
msgid "(отключено)"
|
||||
msgstr "(відключено)"
|
||||
|
||||
#: olgram/commands/menu.py:306
|
||||
#: olgram/commands/menu.py:318
|
||||
msgid ""
|
||||
"\n"
|
||||
" Сейчас вы редактируете шаблоны ответов для @{0}. Текущие шаблоны:\n"
|
||||
@@ -439,27 +510,27 @@ msgstr ""
|
||||
" \n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/menu.py:325
|
||||
#: olgram/commands/menu.py:337
|
||||
msgid "(нет шаблонов)"
|
||||
msgstr "(Немає шаблонів)"
|
||||
|
||||
#: olgram/commands/menu.py:364
|
||||
#: olgram/commands/menu.py:376
|
||||
msgid "У вас нет шаблонов, чтобы их удалять"
|
||||
msgstr "У вас немає шаблонів, щоб їх видаляти"
|
||||
|
||||
#: olgram/commands/menu.py:366
|
||||
#: olgram/commands/menu.py:378
|
||||
msgid "Неправильное число. Чтобы удалить шаблон, введите число от 0 до {0}"
|
||||
msgstr "Неправильне число. Щоб видалити шаблон, введіть число від 0 до {0}"
|
||||
|
||||
#: olgram/commands/menu.py:374
|
||||
#: olgram/commands/menu.py:386
|
||||
msgid "У вашего бота уже слишком много шаблонов"
|
||||
msgstr "У вашого бота вже дуже багато шаблонів"
|
||||
|
||||
#: olgram/commands/menu.py:378
|
||||
#: olgram/commands/menu.py:390
|
||||
msgid "Такой текст уже есть в списке шаблонов"
|
||||
msgstr "Такий текст вже є у списку шаблонів"
|
||||
|
||||
#: olgram/commands/menu.py:396
|
||||
#: olgram/commands/menu.py:408
|
||||
msgid "У вас нет прав на этого бота"
|
||||
msgstr "У вас немає прав на цього бота"
|
||||
|
||||
@@ -479,25 +550,25 @@ msgstr "Неправильний токен"
|
||||
msgid "Такого кода не существует"
|
||||
msgstr "Такого коду не існує"
|
||||
|
||||
#: olgram/commands/promo.py:53
|
||||
#: olgram/commands/promo.py:59
|
||||
msgid "Промокод отозван"
|
||||
msgstr "Промокод відкликаний"
|
||||
|
||||
#: olgram/commands/promo.py:64
|
||||
#: olgram/commands/promo.py:70
|
||||
msgid ""
|
||||
"Укажите аргумент: промокод. Например: <pre>/set_promo my-promo-code</pre>"
|
||||
"Укажите аргумент: промокод. Например: <pre>/setpromo my-promo-code</pre>"
|
||||
msgstr ""
|
||||
"Зазначте аргумент: промокод. Наприклад: <pre>/set_promo my-promo-code</pre>"
|
||||
"Зазначте аргумент: промокод. Наприклад: <pre>/setpromo my-promo-code</pre>"
|
||||
|
||||
#: olgram/commands/promo.py:72 olgram/commands/promo.py:76
|
||||
#: olgram/commands/promo.py:78 olgram/commands/promo.py:82
|
||||
msgid "Промокод не найден"
|
||||
msgstr "Промокод не знайдено"
|
||||
|
||||
#: olgram/commands/promo.py:79
|
||||
#: olgram/commands/promo.py:85
|
||||
msgid "Промокод уже использован"
|
||||
msgstr "Промокод уже використаний"
|
||||
|
||||
#: olgram/commands/promo.py:85
|
||||
#: olgram/commands/promo.py:91
|
||||
msgid "Промокод активирован! Спасибо 🙌"
|
||||
msgstr "Промокод активовано! Дякую 🙌"
|
||||
|
||||
@@ -505,7 +576,8 @@ msgstr "Промокод активовано! Дякую 🙌"
|
||||
msgid ""
|
||||
"\n"
|
||||
" Olgram Bot — это конструктор ботов обратной связи в Telegram. Подробнее "
|
||||
"<a href=\"https://olgram.readthedocs.io\">читайте здесь</a>.\n"
|
||||
"<a href=\"https://olgram.readthedocs.io\">читайте здесь</a>. Следите за "
|
||||
"обновлениями <a href=\"https://t.me/civsoc_it\">здесь</a>.\n"
|
||||
"\n"
|
||||
" Используйте эти команды, чтобы управлять этим ботом:\n"
|
||||
"\n"
|
||||
@@ -517,7 +589,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Olgram Bot - це конструктор роботів зворотного зв'язку в Telegram. "
|
||||
"Докладніше <a href=\"https://olgram.readthedocs.io\">читайте тут</a>.\n"
|
||||
"Докладніше <a href=\"https://olgram.readthedocs.io\">читайте тут</a>. "
|
||||
"Слідкуйте за оновленнями <a href=\"https://t.me/civsoc_it\">тут</a>.\n"
|
||||
"\n"
|
||||
" Використовуйте ці команди, щоб керувати цим ботом:\n"
|
||||
"\n"
|
||||
@@ -528,7 +601,7 @@ msgstr ""
|
||||
" \n"
|
||||
" "
|
||||
|
||||
#: olgram/commands/start.py:42
|
||||
#: olgram/commands/start.py:43
|
||||
msgid ""
|
||||
"\n"
|
||||
" Читайте инструкции на нашем сайте https://olgram.readthedocs.io\n"
|
||||
@@ -564,7 +637,7 @@ msgstr "Власник бота обмежив доступ до цього фу
|
||||
msgid "Владелец бота ограничил доступ к этому функционалу😞"
|
||||
msgstr "Власник бота обмежив доступ до цього функціоналу 😞"
|
||||
|
||||
#: server/custom.py:40
|
||||
#: server/custom.py:55
|
||||
msgid ""
|
||||
"<b>Политика конфиденциальности</b>\n"
|
||||
"\n"
|
||||
@@ -584,7 +657,7 @@ msgstr ""
|
||||
"з оператором; боти Olgram не роблять масових розсилок.\n"
|
||||
"\n"
|
||||
|
||||
#: server/custom.py:46
|
||||
#: server/custom.py:61
|
||||
msgid ""
|
||||
"При отправке сообщения (кроме команд /start и /security_policy) оператор "
|
||||
"<b>видит</b> ваши имя пользователя, @username и идентификатор пользователя в "
|
||||
@@ -594,7 +667,7 @@ msgstr ""
|
||||
"оператор <b>бачить</b> ваше ім'я користувача, @username та ідентифікатор "
|
||||
"користувача через налаштування, які оператор вказав при створенні бота."
|
||||
|
||||
#: server/custom.py:50
|
||||
#: server/custom.py:65
|
||||
msgid ""
|
||||
"В зависимости от ваших настроек конфиденциальности Telegram, оператор может "
|
||||
"видеть ваш username, имя пользователя и другую информацию."
|
||||
@@ -602,15 +675,23 @@ msgstr ""
|
||||
"Залежно від ваших налаштувань конфіденційності Telegram оператор може бачити "
|
||||
"ваш username, ім'я користувача та іншу інформацію."
|
||||
|
||||
#: server/custom.py:61
|
||||
#: server/custom.py:76
|
||||
msgid "Сообщение от пользователя "
|
||||
msgstr "Допис від користувача "
|
||||
|
||||
#: server/custom.py:88
|
||||
#: server/custom.py:135
|
||||
msgid "Вы заблокированы в этом боте"
|
||||
msgstr "Ви заблоковані у цьому боті"
|
||||
|
||||
#: server/custom.py:132
|
||||
#: server/custom.py:141
|
||||
msgid "Слишком много сообщений, подождите одну минуту"
|
||||
msgstr "Забагато повідомлень, зачекайте одну хвилину"
|
||||
|
||||
#: server/custom.py:148
|
||||
msgid "Не удаётся связаться с владельцем бота"
|
||||
msgstr "Не вдається зв'язатися з власником бота"
|
||||
|
||||
#: server/custom.py:179
|
||||
msgid ""
|
||||
"<i>Невозможно переслать сообщение: автор не найден (сообщение слишком "
|
||||
"старое?)</i>"
|
||||
@@ -618,19 +699,19 @@ msgstr ""
|
||||
"<i>Неможливо надіслати повідомлення: автора не знайдено (повідомлення "
|
||||
"занадто старе?)</i>"
|
||||
|
||||
#: server/custom.py:140
|
||||
#: server/custom.py:187
|
||||
msgid "Пользователь заблокирован"
|
||||
msgstr "Користувач заблоковано"
|
||||
|
||||
#: server/custom.py:145
|
||||
#: server/custom.py:192
|
||||
msgid "Пользователь не был забанен"
|
||||
msgstr "Користувач не був забанений"
|
||||
|
||||
#: server/custom.py:148
|
||||
#: server/custom.py:195
|
||||
msgid "Пользователь разбанен"
|
||||
msgstr "Користувач розбанений"
|
||||
|
||||
#: server/custom.py:153
|
||||
#: server/custom.py:200
|
||||
msgid "<i>Невозможно переслать сообщение (автор заблокировал бота?)</i>"
|
||||
msgstr "<i>Неможливо надіслати повідомлення (автор заблокував робота?)</i>"
|
||||
|
||||
@@ -642,21 +723,11 @@ msgstr "(Пере) запустити бота"
|
||||
msgid "Политика конфиденциальности"
|
||||
msgstr "Політика конфіденційності"
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Этот бот создан с помощью @OlgramBot"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Цей бот створено за допомогою @OlgramBot"
|
||||
|
||||
|
||||
msgid "Не удаётся связаться с владельцем бота"
|
||||
msgstr "Не вдається зв'язатися з власником бота"
|
||||
|
||||
msgid "Слишком много сообщений, подождите одну минуту"
|
||||
msgstr "Забагато повідомлень, зачекайте одну хвилину"
|
||||
|
||||
msgid "Антифлуд"
|
||||
msgstr "Антифлуд"
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ "\n"
|
||||
#~ "Этот бот создан с помощью @OlgramBot"
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "\n"
|
||||
#~ "Цей бот створено за допомогою @OlgramBot"
|
||||
|
||||
2
main.py
2
main.py
@@ -25,7 +25,7 @@ async def init_database():
|
||||
|
||||
async def init_olgram():
|
||||
from olgram.router import bot, dp
|
||||
dp.setup_middleware(AccessMiddleware(OlgramSettings.admin_id()))
|
||||
dp.setup_middleware(AccessMiddleware(OlgramSettings.admin_ids()))
|
||||
from aiogram.types import BotCommand
|
||||
await bot.set_my_commands(
|
||||
[
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
"""
|
||||
Здесь работа с конкретным ботом
|
||||
"""
|
||||
from asyncio import sleep
|
||||
from datetime import datetime
|
||||
from aiogram import types
|
||||
from aiogram.utils.exceptions import TelegramAPIError, Unauthorized
|
||||
from aiogram.utils import exceptions
|
||||
from aiogram import Bot as AioBot
|
||||
from olgram.models.models import Bot
|
||||
from olgram.utils.mix import send_stored_message
|
||||
from server.server import unregister_token
|
||||
from locales.locale import _
|
||||
|
||||
@@ -14,14 +18,14 @@ async def delete_bot(bot: Bot, call: types.CallbackQuery):
|
||||
"""
|
||||
try:
|
||||
await unregister_token(bot.decrypted_token())
|
||||
except Unauthorized:
|
||||
except exceptions.Unauthorized:
|
||||
# Вероятно пользователь сбросил токен или удалил бот, это уже не наши проблемы
|
||||
pass
|
||||
await bot.delete()
|
||||
await call.answer(_("Бот удалён"))
|
||||
try:
|
||||
await call.message.delete()
|
||||
except TelegramAPIError:
|
||||
except exceptions.TelegramAPIError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -62,6 +66,20 @@ async def select_chat(bot: Bot, call: types.CallbackQuery, chat: str):
|
||||
await bot.save()
|
||||
await call.answer(_("Выбран личный чат"))
|
||||
return
|
||||
if chat == "leave":
|
||||
bot.group_chat = None
|
||||
await bot.save()
|
||||
chats = await bot.group_chats.all()
|
||||
a_bot = AioBot(bot.decrypted_token())
|
||||
for chat in chats:
|
||||
try:
|
||||
await chat.delete()
|
||||
await a_bot.leave_chat(chat.chat_id)
|
||||
except exceptions.TelegramAPIError:
|
||||
pass
|
||||
await call.answer(_("Бот вышел из чатов"))
|
||||
await a_bot.session.close()
|
||||
return
|
||||
|
||||
chat_obj = await bot.group_chats.filter(id=chat).first()
|
||||
if not chat_obj:
|
||||
@@ -91,3 +109,35 @@ async def olgram_text(bot: Bot, call: types.CallbackQuery):
|
||||
async def antiflood(bot: Bot, call: types.CallbackQuery):
|
||||
bot.enable_antiflood = not bot.enable_antiflood
|
||||
await bot.save(update_fields=["enable_antiflood"])
|
||||
|
||||
|
||||
async def mailing(bot: Bot, call: types.CallbackQuery):
|
||||
bot.enable_mailing = not bot.enable_mailing
|
||||
await bot.save(update_fields=["enable_mailing"])
|
||||
|
||||
|
||||
async def go_mailing(bot: Bot, context) -> int:
|
||||
users = await bot.mailing_users
|
||||
a_bot = AioBot(bot.decrypted_token())
|
||||
|
||||
count = 0
|
||||
|
||||
print(f"start mailing {context}")
|
||||
|
||||
for user in users:
|
||||
bot.last_mailing_at = datetime.now()
|
||||
await bot.save(update_fields=["last_mailing_at"])
|
||||
try:
|
||||
await sleep(0.05)
|
||||
try:
|
||||
await send_stored_message(context, a_bot, user.telegram_id)
|
||||
except exceptions.RetryAfter as err:
|
||||
await sleep(err.timeout)
|
||||
await send_stored_message(context, a_bot, user.telegram_id)
|
||||
count += 1
|
||||
except (exceptions.ChatNotFound, exceptions.BotBlocked, exceptions.UserDeactivated):
|
||||
await user.delete()
|
||||
except exceptions.TelegramAPIError:
|
||||
pass
|
||||
|
||||
return count
|
||||
|
||||
@@ -37,4 +37,4 @@ async def info(message: types.Message, state: FSMContext):
|
||||
_("Входящих сообщений у всех ботов: {0}\n").format(income_messages) +
|
||||
_("Исходящих сообщений у всех ботов: {0}\n").format(outgoing_messages) +
|
||||
_("Промо-кодов выдано: {0}\n").format(promo_count) +
|
||||
_("Рекламную плашку выключили: {0}\n".format(olgram_text_disabled)))
|
||||
_("Рекламную плашку выключили: {0}\n").format(olgram_text_disabled))
|
||||
|
||||
@@ -4,14 +4,14 @@ from aiogram import types, Bot as AioBot
|
||||
from olgram.models.models import Bot, User, DefaultAnswer
|
||||
from aiogram.dispatcher import FSMContext
|
||||
from aiogram.utils.callback_data import CallbackData
|
||||
from datetime import datetime, timedelta
|
||||
from textwrap import dedent
|
||||
from olgram.utils.mix import edit_or_create, button_text_limit, wrap
|
||||
from olgram.utils.mix import edit_or_create, button_text_limit, wrap, send_stored_message
|
||||
from olgram.commands import bot_actions
|
||||
from locales.locale import _
|
||||
|
||||
import typing as ty
|
||||
|
||||
|
||||
menu_callback = CallbackData('menu', 'level', 'bot_id', 'operation', 'chat')
|
||||
|
||||
empty = "0"
|
||||
@@ -68,6 +68,11 @@ async def send_chats_menu(bot: Bot, call: types.CallbackQuery):
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="chat",
|
||||
chat="personal"))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("❗️ Выйти из всех чатов"),
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="chat",
|
||||
chat="leave"))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("<< Назад"),
|
||||
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty,
|
||||
@@ -122,6 +127,12 @@ async def send_bot_menu(bot: Bot, call: types.CallbackQuery):
|
||||
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="settings",
|
||||
chat=empty))
|
||||
)
|
||||
if bot.enable_mailing:
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Рассылка"),
|
||||
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="go_mailing",
|
||||
chat=empty))
|
||||
)
|
||||
|
||||
await edit_or_create(call, dedent(_("""
|
||||
Управление ботом @{0}.
|
||||
@@ -151,7 +162,7 @@ async def send_bot_delete_menu(bot: Bot, call: types.CallbackQuery):
|
||||
|
||||
async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
await call.answer()
|
||||
keyboard = types.InlineKeyboardMarkup(row_width=1)
|
||||
keyboard = types.InlineKeyboardMarkup(row_width=2)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Потоки сообщений"),
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="threads",
|
||||
@@ -167,6 +178,11 @@ async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="antiflood",
|
||||
chat=empty))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Рассылка"),
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="mailing",
|
||||
chat=empty))
|
||||
)
|
||||
is_promo = await bot.is_promo()
|
||||
if is_promo:
|
||||
keyboard.insert(
|
||||
@@ -184,11 +200,13 @@ async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
thread_turn = _("включены") if bot.enable_threads else _("выключены")
|
||||
info_turn = _("включены") if bot.enable_additional_info else _("выключены")
|
||||
antiflood_turn = _("включен") if bot.enable_antiflood else _("выключен")
|
||||
mailing_turn = _("включена") if bot.enable_mailing 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>
|
||||
<a href="https://olgram.readthedocs.io/ru/latest/options.html#antiflood">Антифлуд</a>: <b>{2}</b>
|
||||
""")).format(thread_turn, info_turn, antiflood_turn)
|
||||
<a href="https://olgram.readthedocs.io/ru/latest/options.html#mailing">Рассылка</a>: <b>{3}</b>
|
||||
""")).format(thread_turn, info_turn, antiflood_turn, mailing_turn)
|
||||
|
||||
if is_promo:
|
||||
olgram_turn = _("включена") if bot.enable_olgram_text else _("выключена")
|
||||
@@ -233,6 +251,30 @@ async def send_bot_text_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] =
|
||||
await AioBot.get_current().send_message(chat_id, text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
async def send_bot_mailing_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] = None,
|
||||
chat_id: ty.Optional[int] = None):
|
||||
if call:
|
||||
await call.answer()
|
||||
keyboard = types.InlineKeyboardMarkup(row_width=1)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("<< Отменить рассылку"),
|
||||
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
|
||||
)
|
||||
|
||||
text = dedent(_("""
|
||||
Напишите сообщение, которое нужно разослать всем подписчикам вашего бота @{0}.
|
||||
У сообщения будет до {1} получателей.
|
||||
Учтите, что
|
||||
1. Рассылается только одно сообщение за раз (в т.ч. только одна картинка)
|
||||
2. Когда рассылка запущена, её нельзя отменить
|
||||
"""))
|
||||
text = text.format(bot.name, len(await bot.mailing_users))
|
||||
if call:
|
||||
await edit_or_create(call, text, keyboard, parse_mode="HTML")
|
||||
else:
|
||||
await AioBot.get_current().send_message(chat_id, text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
async def send_bot_statistic_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] = None,
|
||||
chat_id: ty.Optional[int] = None):
|
||||
if call:
|
||||
@@ -347,6 +389,49 @@ async def start_text_received(message: types.Message, state: FSMContext):
|
||||
await send_bot_text_menu(bot, chat_id=message.chat.id)
|
||||
|
||||
|
||||
@dp.message_handler(state="wait_mailing_text",
|
||||
content_types=[types.ContentType.TEXT,
|
||||
types.ContentType.LOCATION,
|
||||
types.ContentType.DOCUMENT,
|
||||
types.ContentType.PHOTO,
|
||||
types.ContentType.AUDIO,
|
||||
types.ContentType.VIDEO]) # TODO: not command
|
||||
async def mailing_text_received(message: types.Message, state: FSMContext):
|
||||
async with state.proxy() as proxy:
|
||||
bot_id = proxy["bot_id"]
|
||||
proxy["mailing_content_type"] = message.content_type
|
||||
|
||||
if message.content_type == types.ContentType.TEXT:
|
||||
proxy["mailing_text"] = message.html_text
|
||||
elif message.content_type == types.ContentType.LOCATION:
|
||||
proxy["mailing_location"] = message.location
|
||||
elif message.content_type == types.ContentType.PHOTO:
|
||||
proxy["mailing_photo"] = message.photo[0].file_id
|
||||
proxy["mailing_caption"] = message.caption
|
||||
elif message.content_type == types.ContentType.DOCUMENT:
|
||||
proxy["mailing_document"] = message.document.file_id
|
||||
proxy["mailing_caption"] = message.caption
|
||||
elif message.content_type == types.ContentType.AUDIO:
|
||||
proxy["mailing_audio"] = message.audio.file_id
|
||||
proxy["mailing_caption"] = message.caption
|
||||
elif message.content_type == types.ContentType.VIDEO:
|
||||
proxy["mailing_video"] = message.video.file_id
|
||||
proxy["mailing_video"] = message.caption
|
||||
|
||||
_message_id = await send_stored_message(proxy, AioBot.get_current(), message.chat.id)
|
||||
|
||||
keyboard = types.InlineKeyboardMarkup(row_width=1)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Да, начать рассылку"),
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot_id, operation="go_go_mailing",
|
||||
chat=empty))
|
||||
)
|
||||
|
||||
await AioBot.get_current().send_message(message.chat.id, reply_to_message_id=_message_id.message_id,
|
||||
text="Вы уверены, что хотите разослать это сообщение всем пользователям?",
|
||||
reply_markup=keyboard)
|
||||
|
||||
|
||||
@dp.message_handler(state="wait_second_text", content_types="text", regexp="^[^/].+") # Not command
|
||||
async def second_text_received(message: types.Message, state: FSMContext):
|
||||
async with state.proxy() as proxy:
|
||||
@@ -418,6 +503,15 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon
|
||||
return await send_bot_statistic_menu(bot, call)
|
||||
if operation == "settings":
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
if operation == "go_mailing":
|
||||
if bot.last_mailing_at and bot.last_mailing_at >= datetime.now() - timedelta(minutes=5):
|
||||
return await call.answer(_("Рассылка была совсем недавно, подождите немного"), show_alert=True)
|
||||
if not await bot.mailing_users:
|
||||
return await call.answer(_("Нет пользователей для рассылки"))
|
||||
await state.set_state("wait_mailing_text")
|
||||
async with state.proxy() as proxy:
|
||||
proxy["bot_id"] = bot.id
|
||||
return await send_bot_mailing_menu(bot, call)
|
||||
if operation == "text":
|
||||
await state.set_state("wait_start_text")
|
||||
async with state.proxy() as proxy:
|
||||
@@ -435,6 +529,9 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon
|
||||
if operation == "antiflood":
|
||||
await bot_actions.antiflood(bot, call)
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
if operation == "mailing":
|
||||
await bot_actions.mailing(bot, call)
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
if operation == "additional_info":
|
||||
await bot_actions.additional_info(bot, call)
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
@@ -449,6 +546,20 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon
|
||||
async with state.proxy() as proxy:
|
||||
proxy["bot_id"] = bot.id
|
||||
return await send_bot_second_text_menu(bot, call)
|
||||
if operation == "go_go_mailing":
|
||||
if (await state.get_state()) == "wait_mailing_text":
|
||||
async with state.proxy() as proxy:
|
||||
mailing_data = dict(proxy)
|
||||
await state.reset_state()
|
||||
|
||||
if bot.last_mailing_at and bot.last_mailing_at >= datetime.now() - timedelta(minutes=5):
|
||||
return await call.answer(_("Рассылка была совсем недавно, подождите немного"), show_alert=True)
|
||||
if not await bot.mailing_users:
|
||||
return await call.answer(_("Нет пользователей для рассылки"))
|
||||
|
||||
await call.answer(_("Рассылка запущена"))
|
||||
count = await bot_actions.go_mailing(bot, mailing_data)
|
||||
await call.message.answer(_("Рассылка завершена, отправлено {0} сообщений").format(count))
|
||||
if operation == "reset_second_text":
|
||||
await bot_actions.reset_bot_second_text(bot, call)
|
||||
return await send_bot_second_text_menu(bot, call)
|
||||
|
||||
@@ -60,14 +60,14 @@ async def del_promo(message: types.Message, state: FSMContext):
|
||||
|
||||
|
||||
@dp.message_handler(commands=["setpromo"], state="*")
|
||||
async def set_promo(message: types.Message, state: FSMContext):
|
||||
async def setpromo(message: types.Message, state: FSMContext):
|
||||
"""
|
||||
Команда /setpromo
|
||||
"""
|
||||
|
||||
arg = message.get_args()
|
||||
if not arg:
|
||||
return await message.answer(_("Укажите аргумент: промокод. Например: <pre>/set_promo my-promo-code</pre>"),
|
||||
return await message.answer(_("Укажите аргумент: промокод. Например: <pre>/setpromo my-promo-code</pre>"),
|
||||
parse_mode="HTML")
|
||||
|
||||
arg = arg.strip()
|
||||
|
||||
14
olgram/migrations/models/15_20221106042712_update.sql
Normal file
14
olgram/migrations/models/15_20221106042712_update.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- upgrade --
|
||||
ALTER TABLE "bot" ADD "last_mailing_at" TIMESTAMPTZ;
|
||||
ALTER TABLE "bot" ADD "enable_mailing" BOOL NOT NULL DEFAULT False;
|
||||
CREATE TABLE IF NOT EXISTS "mailinguser" (
|
||||
"id" BIGSERIAL NOT NULL PRIMARY KEY,
|
||||
"telegram_id" BIGINT NOT NULL,
|
||||
"bot_id" INT NOT NULL REFERENCES "bot" ("id") ON DELETE CASCADE,
|
||||
CONSTRAINT "uid_mailinguser_bot_id_906a76" UNIQUE ("bot_id", "telegram_id")
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "idx_mailinguser_telegra_55de60" ON "mailinguser" ("telegram_id");;
|
||||
-- downgrade --
|
||||
ALTER TABLE "bot" DROP COLUMN "last_mailing_at";
|
||||
ALTER TABLE "bot" DROP COLUMN "enable_mailing";
|
||||
DROP TABLE IF EXISTS "mailinguser";
|
||||
@@ -46,6 +46,8 @@ class Bot(Model):
|
||||
enable_additional_info = fields.BooleanField(default=False)
|
||||
enable_olgram_text = fields.BooleanField(default=True)
|
||||
enable_antiflood = fields.BooleanField(default=False)
|
||||
enable_mailing = fields.BooleanField(default=False)
|
||||
last_mailing_at = fields.DatetimeField(null=True, default=None)
|
||||
|
||||
def decrypted_token(self):
|
||||
cryptor = DatabaseSettings.cryptor()
|
||||
@@ -70,6 +72,17 @@ class Bot(Model):
|
||||
table = 'bot'
|
||||
|
||||
|
||||
class MailingUser(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
telegram_id = fields.BigIntField(index=True)
|
||||
|
||||
bot = fields.ForeignKeyField("models.Bot", related_name="mailing_users", on_delete=fields.relational.CASCADE)
|
||||
|
||||
class Meta:
|
||||
table = 'mailinguser'
|
||||
unique_together = (("bot", "telegram_id"), )
|
||||
|
||||
|
||||
class User(Model):
|
||||
id = fields.IntField(pk=True)
|
||||
telegram_id = fields.BigIntField(index=True, unique=True)
|
||||
|
||||
@@ -41,13 +41,13 @@ class OlgramSettings(AbstractSettings):
|
||||
|
||||
@classmethod
|
||||
def version(cls):
|
||||
return "0.4.3"
|
||||
return "0.5.0"
|
||||
|
||||
@classmethod
|
||||
@lru_cache
|
||||
def admin_id(cls):
|
||||
_id = cls._get_env("ADMIN_ID", True)
|
||||
return int(_id) if _id else None
|
||||
def admin_ids(cls):
|
||||
_ids = cls._get_env("ADMIN_ID", True)
|
||||
return set(map(int, _ids.split(","))) if _ids else None
|
||||
|
||||
@classmethod
|
||||
@lru_cache
|
||||
@@ -105,7 +105,7 @@ class ServerSettings(AbstractSettings):
|
||||
return int(timedelta(days=1).total_seconds() * 1000.0)
|
||||
|
||||
|
||||
logging.basicConfig(level=os.environ.get("LOGLEVEL", "WARNING"),
|
||||
logging.basicConfig(level=os.environ.get("LOGLEVEL") or "WARNING",
|
||||
format='%(asctime)s %(levelname)-8s %(message)s')
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup
|
||||
from aiogram import types, Bot as AioBot
|
||||
from aiogram.utils.exceptions import TelegramAPIError
|
||||
|
||||
from typing import Optional
|
||||
@@ -30,3 +31,23 @@ def wrap(data: str, max_len: int) -> str:
|
||||
|
||||
def button_text_limit(data: str) -> str:
|
||||
return wrap(data, 30)
|
||||
|
||||
|
||||
async def send_stored_message(storage: dict, bot: AioBot, chat_id: int):
|
||||
content_type = storage["mailing_content_type"]
|
||||
if content_type == types.ContentType.TEXT:
|
||||
return await bot.send_message(chat_id, storage["mailing_text"], parse_mode="HTML")
|
||||
if content_type == types.ContentType.LOCATION:
|
||||
return await bot.send_location(chat_id, storage["mailing_location"][0], storage["mailing_location"][1])
|
||||
if content_type == types.ContentType.AUDIO:
|
||||
return await bot.send_audio(chat_id, audio=storage["mailing_audio"], caption=storage.get("mailing_caption"))
|
||||
if content_type == types.ContentType.DOCUMENT:
|
||||
return await bot.send_document(chat_id, document=storage["mailing_document"],
|
||||
caption=storage.get("mailing_caption"))
|
||||
if content_type == types.ContentType.PHOTO:
|
||||
return await bot.send_photo(chat_id, photo=storage["mailing_photo"],
|
||||
caption=storage.get("mailing_caption"))
|
||||
if content_type == types.ContentType.VIDEO:
|
||||
return await bot.send_video(chat_id, video=storage["mailing_video"],
|
||||
caption=storage.get("mailing_caption"))
|
||||
raise NotImplementedError("Mailing, unknown content type")
|
||||
@@ -1,6 +1,7 @@
|
||||
import aiogram.types as types
|
||||
from aiogram.dispatcher.handler import CancelHandler, current_handler
|
||||
from aiogram.dispatcher.middlewares import BaseMiddleware
|
||||
import typing as ty
|
||||
from locales.locale import _
|
||||
|
||||
|
||||
@@ -19,8 +20,8 @@ def public():
|
||||
|
||||
|
||||
class AccessMiddleware(BaseMiddleware):
|
||||
def __init__(self, access_chat_id: int):
|
||||
self._access_chat_id = access_chat_id
|
||||
def __init__(self, access_chat_ids: ty.Iterable[int]):
|
||||
self._access_chat_ids = access_chat_ids
|
||||
super(AccessMiddleware, self).__init__()
|
||||
|
||||
@classmethod
|
||||
@@ -29,25 +30,25 @@ class AccessMiddleware(BaseMiddleware):
|
||||
return handler and getattr(handler, "access_public", False)
|
||||
|
||||
async def on_process_message(self, message: types.Message, data: dict):
|
||||
admin_id = self._access_chat_id
|
||||
if not admin_id:
|
||||
return # Администратор бота вообще не указан
|
||||
admin_ids = self._access_chat_ids
|
||||
if not admin_ids:
|
||||
return # Администраторы бота вообще не указаны
|
||||
|
||||
if self._is_public_command(): # Эта команда разрешена всем пользователям
|
||||
return
|
||||
|
||||
if message.chat.id != admin_id:
|
||||
if message.chat.id not in admin_ids:
|
||||
await message.answer(_("Владелец бота ограничил доступ к этому функционалу 😞"))
|
||||
raise CancelHandler()
|
||||
|
||||
async def on_process_callback_query(self, call: types.CallbackQuery, data: dict):
|
||||
admin_id = self._access_chat_id
|
||||
if not admin_id:
|
||||
return # Администратор бота вообще не указан
|
||||
admin_ids = self._access_chat_ids
|
||||
if not admin_ids:
|
||||
return # Администраторы бота вообще не указаны
|
||||
|
||||
if self._is_public_command(): # Эта команда разрешена всем пользователям
|
||||
return
|
||||
|
||||
if call.message.chat.id != admin_id:
|
||||
if call.message.chat.id not in admin_ids:
|
||||
await call.answer(_("Владелец бота ограничил доступ к этому функционалу😞"))
|
||||
raise CancelHandler()
|
||||
|
||||
@@ -11,7 +11,7 @@ from tortoise.expressions import F
|
||||
import logging
|
||||
import typing as ty
|
||||
from olgram.settings import ServerSettings
|
||||
from olgram.models.models import Bot, GroupChat, BannedUser
|
||||
from olgram.models.models import Bot, GroupChat, BannedUser, MailingUser
|
||||
from locales.locale import _, translators
|
||||
from server.inlines import inline_handler
|
||||
|
||||
@@ -55,15 +55,20 @@ def _on_security_policy(message: types.Message, bot):
|
||||
text = _("<b>Политика конфиденциальности</b>\n\n"
|
||||
"Этот бот не хранит ваши сообщения, имя пользователя и @username. При отправке сообщения (кроме команд "
|
||||
"/start и /security_policy) ваш идентификатор пользователя записывается в кеш на некоторое время и потом "
|
||||
"удаляется из кеша. Этот идентификатор используется только для общения с оператором; боты Olgram "
|
||||
"не делают массовых рассылок.\n\n")
|
||||
"удаляется из кеша. Этот идентификатор используется для общения с оператором.\n\n")
|
||||
if bot.enable_additional_info:
|
||||
text += _("При отправке сообщения (кроме команд /start и /security_policy) оператор <b>видит</b> ваши имя "
|
||||
"пользователя, @username и идентификатор пользователя в силу настроек, которые оператор указал при "
|
||||
"создании бота.")
|
||||
"создании бота.\n\n")
|
||||
else:
|
||||
text += _("В зависимости от ваших настроек конфиденциальности Telegram, оператор может видеть ваш username, "
|
||||
"имя пользователя и другую информацию.")
|
||||
"имя пользователя и другую информацию.\n\n")
|
||||
|
||||
if bot.enable_mailing:
|
||||
text += _("В этом боте включена массовая рассылка в силу настроек, которые оператор указал при создании бота. "
|
||||
"Ваш идентификатор пользователя может быть записан в базу данных на долгое время")
|
||||
else:
|
||||
text += _("В этом боте нет массовой рассылки сообщений")
|
||||
|
||||
return SendMessage(chat_id=message.chat.id,
|
||||
text=text,
|
||||
@@ -128,6 +133,10 @@ async def handle_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
_ = _get_translator(message)
|
||||
is_super_group = super_chat_id < 0
|
||||
|
||||
# Записать пользователя для рассылки, если она включена
|
||||
if bot.enable_mailing:
|
||||
_, __ = await MailingUser.get_or_create(telegram_id=message.chat.id, bot=bot)
|
||||
|
||||
# Проверить, не забанен ли пользователь
|
||||
banned = await bot.banned_users.filter(telegram_id=message.chat.id)
|
||||
if banned:
|
||||
@@ -319,7 +328,8 @@ class CustomRequestHandler(WebhookRequestHandler):
|
||||
types.ContentType.PHOTO,
|
||||
types.ContentType.STICKER,
|
||||
types.ContentType.VIDEO,
|
||||
types.ContentType.VOICE]
|
||||
types.ContentType.VOICE,
|
||||
types.ContentType.LOCATION]
|
||||
dp.register_message_handler(message_handler, content_types=supported_messages)
|
||||
dp.register_edited_message_handler(edited_message_handler, content_types=supported_messages)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user