mirror of
https://github.com/civsocit/olgram.git
synced 2023-07-22 01:29:12 +03:00
add broadcasting
This commit is contained in:
parent
30ab7c84b4
commit
992daa5b30
@ -1,11 +1,13 @@
|
||||
"""
|
||||
Здесь работа с конкретным ботом
|
||||
"""
|
||||
import asyncio
|
||||
from aiogram import types
|
||||
from aiogram.utils.exceptions import TelegramAPIError, Unauthorized
|
||||
from aiogram import Bot as AioBot
|
||||
from olgram.models.models import Bot
|
||||
from olgram.models.models import Bot, User
|
||||
from server.server import unregister_token
|
||||
from typing import Optional
|
||||
from locales.locale import _
|
||||
|
||||
|
||||
@ -87,6 +89,28 @@ async def select_chat(bot: Bot, call: types.CallbackQuery, chat: str):
|
||||
await call.answer(_("Выбран чат {0}").format(chat_obj.name))
|
||||
|
||||
|
||||
async def start_broadcast(bot: Bot, call: types.CallbackQuery, text: Optional[str]):
|
||||
if not text:
|
||||
return await call.answer(_("Отправьте текст для рассылки"))
|
||||
|
||||
user_chat_ids = await User.all().values_list("telegram_id", flat=True)
|
||||
a_bot = AioBot(bot.decrypted_token())
|
||||
count = 0
|
||||
await call.answer(_("Рассылка начата"))
|
||||
try:
|
||||
for telegram_id in user_chat_ids:
|
||||
try:
|
||||
if await a_bot.send_message(telegram_id, text, parse_mode="HTML"):
|
||||
count += 1
|
||||
except Unauthorized:
|
||||
continue
|
||||
else:
|
||||
await asyncio.sleep(0.05) # 20 messages per second (Limit: 30 messages per second)
|
||||
finally:
|
||||
await call.bot.send_message(call.from_user.id, _("Рассылка закончена. Сообщений отправлено: {0}").format(count))
|
||||
await a_bot.session.close()
|
||||
|
||||
|
||||
async def threads(bot: Bot, call: types.CallbackQuery):
|
||||
bot.enable_threads = not bot.enable_threads
|
||||
await bot.save(update_fields=["enable_threads"])
|
||||
|
@ -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))
|
||||
|
@ -119,14 +119,19 @@ async def send_bot_menu(bot: Bot, call: types.CallbackQuery):
|
||||
chat=empty))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("<< Назад"),
|
||||
callback_data=menu_callback.new(level=0, bot_id=empty, operation=empty, chat=empty))
|
||||
types.InlineKeyboardButton(text=_("Рассылка"),
|
||||
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="broadcast",
|
||||
chat=empty))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Опции"),
|
||||
callback_data=menu_callback.new(level=2, bot_id=bot.id, operation="settings",
|
||||
chat=empty))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("<< Назад"),
|
||||
callback_data=menu_callback.new(level=0, bot_id=empty, operation=empty, chat=empty))
|
||||
)
|
||||
|
||||
await edit_or_create(call, dedent(_("""
|
||||
Управление ботом @{0}.
|
||||
@ -202,6 +207,41 @@ async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
await edit_or_create(call, text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
async def send_bot_broadcast_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] = None,
|
||||
chat_id: ty.Optional[int] = None, text: ty.Optional[str] = None):
|
||||
if call:
|
||||
await call.answer()
|
||||
keyboard = types.InlineKeyboardMarkup(row_width=2)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("<< Назад"),
|
||||
callback_data=menu_callback.new(level=1, bot_id=bot.id, operation=empty, chat=empty))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Начать рассылку"),
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id, operation="start_broadcast",
|
||||
chat=empty))
|
||||
)
|
||||
|
||||
if text:
|
||||
text = dedent(_("""
|
||||
Сейчас вы редактируете текст, который будет отправлен всем пользователям бота @{0} после начала рассылки.
|
||||
|
||||
Текущий текст:
|
||||
<pre>
|
||||
{1}
|
||||
</pre>
|
||||
Отправьте сообщение, чтобы изменить текст.
|
||||
""")).format(bot.name, text)
|
||||
else:
|
||||
text = _(
|
||||
"Отправьте сообщение с текстом, который будет отправлен всем пользователям бота @{0} после начала рассылки."
|
||||
).format(bot.name)
|
||||
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_text_menu(bot: Bot, call: ty.Optional[types.CallbackQuery] = None, chat_id: ty.Optional[int] = None):
|
||||
if call:
|
||||
await call.answer()
|
||||
@ -342,7 +382,17 @@ async def send_bot_templates_menu(bot: Bot, call: ty.Optional[types.CallbackQuer
|
||||
await AioBot.get_current().send_message(chat_id, text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
@dp.message_handler(state="wait_start_text", content_types="text", regexp="^[^/].+") # Not command
|
||||
@dp.message_handler(state="wait_broadcast_text", content_types="text", regexp="^[^/].*") # Not command
|
||||
async def broadcast_text_received(message: types.Message, state: FSMContext):
|
||||
broadcast_text = message.html_text
|
||||
async with state.proxy() as proxy:
|
||||
bot_id = proxy.get("bot_id")
|
||||
proxy["broadcast_text"] = broadcast_text
|
||||
bot = await Bot.get_or_none(pk=bot_id)
|
||||
await send_bot_broadcast_menu(bot, chat_id=message.chat.id, text=broadcast_text)
|
||||
|
||||
|
||||
@dp.message_handler(state="wait_start_text", content_types="text", regexp="^[^/].*") # Not command
|
||||
async def start_text_received(message: types.Message, state: FSMContext):
|
||||
async with state.proxy() as proxy:
|
||||
bot_id = proxy.get("bot_id")
|
||||
@ -352,7 +402,7 @@ 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_second_text", content_types="text", regexp="^[^/].+") # Not command
|
||||
@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:
|
||||
bot_id = proxy.get("bot_id")
|
||||
@ -362,7 +412,7 @@ async def second_text_received(message: types.Message, state: FSMContext):
|
||||
await send_bot_second_text_menu(bot, chat_id=message.chat.id)
|
||||
|
||||
|
||||
@dp.message_handler(state="wait_template", content_types="text", regexp="^[^/](.+)?") # Not command
|
||||
@dp.message_handler(state="wait_template", content_types="text", regexp="^[^/].*") # Not command
|
||||
async def template_received(message: types.Message, state: FSMContext):
|
||||
async with state.proxy() as proxy:
|
||||
bot_id = proxy.get("bot_id")
|
||||
@ -423,6 +473,11 @@ 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 == "broadcast":
|
||||
await state.set_state("wait_broadcast_text")
|
||||
async with state.proxy() as proxy:
|
||||
proxy["bot_id"] = bot.id
|
||||
return await send_bot_broadcast_menu(bot, call)
|
||||
if operation == "text":
|
||||
await state.set_state("wait_start_text")
|
||||
async with state.proxy() as proxy:
|
||||
@ -457,6 +512,10 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon
|
||||
if operation == "reset_second_text":
|
||||
await bot_actions.reset_bot_second_text(bot, call)
|
||||
return await send_bot_second_text_menu(bot, call)
|
||||
if operation == "start_broadcast":
|
||||
async with state.proxy() as proxy:
|
||||
text = proxy.get("broadcast_text")
|
||||
return await bot_actions.start_broadcast(bot, call, text)
|
||||
if operation == "templates":
|
||||
await state.set_state("wait_template")
|
||||
async with state.proxy() as proxy:
|
||||
|
@ -91,8 +91,8 @@ class ServerSettings(AbstractSettings):
|
||||
return "/cert/public.pem"
|
||||
|
||||
@classmethod
|
||||
def append_text(cls) -> str:
|
||||
return "\n\nЭтот бот создан с помощью @OlgramBot"
|
||||
def append_text(cls, _: ty.Callable) -> str:
|
||||
return _("\n\nЭтот бот создан с помощью @OlgramBot")
|
||||
|
||||
@classmethod
|
||||
@lru_cache
|
||||
|
@ -213,14 +213,13 @@ async def handle_operator_message(message: types.Message, super_chat_id: int, bo
|
||||
|
||||
|
||||
async def message_handler(message: types.Message, *args, **kwargs):
|
||||
_ = _get_translator(message)
|
||||
bot = db_bot_instance.get()
|
||||
|
||||
if message.text and message.text == "/start":
|
||||
# На команду start нужно ответить, не пересылая сообщение никуда
|
||||
text = bot.start_text
|
||||
if bot.enable_olgram_text:
|
||||
text += _(ServerSettings.append_text())
|
||||
text += ServerSettings.append_text(_get_translator(message))
|
||||
return SendMessage(chat_id=message.chat.id, text=text, parse_mode="HTML")
|
||||
|
||||
if message.text and message.text == "/security_policy":
|
||||
|
Loading…
Reference in New Issue
Block a user