mirror of
https://github.com/civsocit/olgram.git
synced 2025-12-17 10:16:17 +00:00
Compare commits
13 Commits
1b1fe239f8
...
stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
103618cbd2 | ||
|
|
7e4f671911 | ||
|
|
eca5c53233 | ||
|
|
2305590899 | ||
|
|
a34e633b98 | ||
|
|
16da3634db | ||
|
|
a0c6c9415e | ||
|
|
dab803a4e8 | ||
|
|
0ceea778fe | ||
|
|
7ce6df7fd9 | ||
|
|
59da56d463 | ||
|
|
1c12730a4e | ||
|
|
d0b570baa9 |
@@ -140,6 +140,11 @@ async def mailing(bot: Bot, call: types.CallbackQuery):
|
||||
await bot.save(update_fields=["enable_mailing"])
|
||||
|
||||
|
||||
async def tags(bot: Bot, call: types.CallbackQuery):
|
||||
bot.enable_tags = not bot.enable_tags
|
||||
await bot.save(update_fields=["enable_tags"])
|
||||
|
||||
|
||||
async def go_mailing(bot: Bot, context: dict) -> int:
|
||||
users = await bot.mailing_users
|
||||
a_bot = AioBot(bot.decrypted_token())
|
||||
|
||||
@@ -197,6 +197,12 @@ async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
operation="thread_interrupt",
|
||||
chat=empty))
|
||||
)
|
||||
keyboard.insert(
|
||||
types.InlineKeyboardButton(text=_("Теги"),
|
||||
callback_data=menu_callback.new(level=3, bot_id=bot.id,
|
||||
operation="tags",
|
||||
chat=empty))
|
||||
)
|
||||
is_promo = await bot.is_promo()
|
||||
if is_promo:
|
||||
keyboard.insert(
|
||||
@@ -217,6 +223,7 @@ async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
enable_always_second_message = _("включён") if bot.enable_always_second_message else _("выключен")
|
||||
thread_interrupt = _("да") if bot.enable_thread_interrupt else _("нет")
|
||||
mailing_turn = _("включена") if bot.enable_mailing else _("выключена")
|
||||
tags_turn = _("включены") if bot.enable_tags 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>
|
||||
@@ -224,8 +231,9 @@ async def send_bot_settings_menu(bot: Bot, call: types.CallbackQuery):
|
||||
<a href="https://olgram.readthedocs.io/ru/latest/options.html#always_second_message">Автоответчик всегда</a>: <b>{3}</b>
|
||||
<a href="https://olgram.readthedocs.io/ru/latest/options.html#thread_interrupt">Прерывать поток</a>: <b>{4}</b>
|
||||
<a href="https://olgram.readthedocs.io/ru/latest/options.html#mailing">Рассылка</a>: <b>{5}</b>
|
||||
Теги: <b>{6}</b>
|
||||
""")).format(thread_turn, info_turn, antiflood_turn, enable_always_second_message, thread_interrupt,
|
||||
mailing_turn)
|
||||
mailing_turn, tags_turn)
|
||||
|
||||
if is_promo:
|
||||
olgram_turn = _("включена") if bot.enable_olgram_text else _("выключена")
|
||||
@@ -672,6 +680,9 @@ async def callback(call: types.CallbackQuery, callback_data: dict, state: FSMCon
|
||||
if operation == "mailing":
|
||||
await bot_actions.mailing(bot, call)
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
if operation == "tags":
|
||||
await bot_actions.tags(bot, call)
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
if operation == "thread_interrupt":
|
||||
await bot_actions.thread_interrupt(bot, call)
|
||||
return await send_bot_settings_menu(bot, call)
|
||||
|
||||
4
olgram/migrations/models/22_20240317143246_update.sql
Normal file
4
olgram/migrations/models/22_20240317143246_update.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- upgrade --
|
||||
ALTER TABLE "bot_start_message" ALTER COLUMN "locale" TYPE VARCHAR(15) USING "locale"::VARCHAR(15);
|
||||
-- downgrade --
|
||||
ALTER TABLE "bot_start_message" ALTER COLUMN "locale" TYPE VARCHAR(5) USING "locale"::VARCHAR(5);
|
||||
4
olgram/migrations/models/24_20240322034823_update.sql
Normal file
4
olgram/migrations/models/24_20240322034823_update.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- upgrade --
|
||||
ALTER TABLE "bot" ADD "enable_tags" BOOL NOT NULL DEFAULT False;
|
||||
-- downgrade --
|
||||
ALTER TABLE "bot" DROP COLUMN "enable_tags";
|
||||
@@ -49,6 +49,7 @@ class Bot(Model):
|
||||
enable_always_second_message = fields.BooleanField(default=False)
|
||||
enable_thread_interrupt = fields.BooleanField(default=True)
|
||||
enable_mailing = fields.BooleanField(default=False)
|
||||
enable_tags = fields.BooleanField(default=False)
|
||||
last_mailing_at = fields.DatetimeField(null=True, default=None)
|
||||
|
||||
def decrypted_token(self):
|
||||
@@ -77,7 +78,7 @@ class Bot(Model):
|
||||
class BotStartMessage(Model):
|
||||
id = fields.IntField(pk=True)
|
||||
bot = fields.ForeignKeyField("models.Bot", related_name="start_texts", on_delete=fields.CASCADE)
|
||||
locale = fields.CharField(max_length=5)
|
||||
locale = fields.CharField(max_length=15)
|
||||
text = fields.TextField()
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -40,7 +40,7 @@ class OlgramSettings(AbstractSettings):
|
||||
|
||||
@classmethod
|
||||
def version(cls):
|
||||
return "0.7.1"
|
||||
return "0.7.3"
|
||||
|
||||
@classmethod
|
||||
@lru_cache
|
||||
|
||||
@@ -26,9 +26,12 @@ _redis: ty.Optional[Redis] = None
|
||||
|
||||
|
||||
def _get_translator(message: types.Message) -> ty.Callable:
|
||||
if not message.from_user.locale:
|
||||
try:
|
||||
if not message.from_user.locale:
|
||||
return _
|
||||
return translators.get(message.from_user.locale.language, _)
|
||||
except Exception:
|
||||
return _
|
||||
return translators.get(message.from_user.locale.language, _)
|
||||
|
||||
|
||||
async def init_redis():
|
||||
@@ -81,7 +84,7 @@ def _on_security_policy(message: types.Message, bot):
|
||||
parse_mode="HTML")
|
||||
|
||||
|
||||
async def send_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
async def send_user_message(message: types.Message, super_chat_id: int, bot, tag: str = ""):
|
||||
"""Переслать сообщение от пользователя, добавлять к нему user info при необходимости"""
|
||||
if bot.enable_additional_info:
|
||||
user_info = _("Сообщение от пользователя ")
|
||||
@@ -89,8 +92,11 @@ async def send_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
if message.from_user.username:
|
||||
user_info += " | @" + message.from_user.username
|
||||
user_info += f" | #ID{message.from_user.id}"
|
||||
if message.from_user.locale:
|
||||
user_info += f" | lang: {message.from_user.locale}"
|
||||
try:
|
||||
if message.from_user.locale:
|
||||
user_info += f" | lang: {message.from_user.locale}"
|
||||
except Exception:
|
||||
pass
|
||||
if message.forward_sender_name:
|
||||
user_info += f" | fwd: {message.forward_sender_name}"
|
||||
tag = await _redis.get(_tag_uid(bot.pk, message.from_user.id), encoding="utf-8")
|
||||
@@ -106,6 +112,15 @@ async def send_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
new_message_2 = await message.copy_to(super_chat_id, reply_to_message_id=new_message.message_id)
|
||||
await _redis.set(_message_unique_id(bot.pk, new_message_2.message_id), message.chat.id,
|
||||
pexpire=ServerSettings.redis_timeout_ms())
|
||||
elif tag:
|
||||
# добавлять тег в конец текста
|
||||
if message.content_type == types.ContentType.TEXT and len(message.text) + len(tag) < 4093:
|
||||
new_message = await message.bot.send_message(super_chat_id, message.text + "\n\n" + tag)
|
||||
else:
|
||||
new_message = await message.bot.send_message(super_chat_id, text=tag)
|
||||
new_message_2 = await message.copy_to(super_chat_id, reply_to_message_id=new_message.message_id)
|
||||
await _redis.set(_message_unique_id(bot.pk, new_message_2.message_id), message.chat.id,
|
||||
pexpire=ServerSettings.redis_timeout_ms())
|
||||
else:
|
||||
try:
|
||||
new_message = await message.forward(super_chat_id)
|
||||
@@ -119,6 +134,13 @@ async def send_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
|
||||
async def send_to_superchat(is_super_group: bool, message: types.Message, super_chat_id: int, bot):
|
||||
"""Пересылка сообщения от пользователя оператору (логика потоков сообщений)"""
|
||||
if bot.enable_tags:
|
||||
tag = await _redis.get(_tag_uid(bot.pk, message.chat.id), encoding="utf-8")
|
||||
else:
|
||||
tag = ""
|
||||
if tag:
|
||||
tag = str(tag)
|
||||
|
||||
if is_super_group and bot.enable_threads:
|
||||
if bot.enable_thread_interrupt:
|
||||
thread_timeout = ServerSettings.thread_timeout_ms()
|
||||
@@ -128,20 +150,34 @@ async def send_to_superchat(is_super_group: bool, message: types.Message, super_
|
||||
if thread_first_message:
|
||||
# переслать в супер-чат, отвечая на предыдущее сообщение
|
||||
try:
|
||||
new_message = await message.copy_to(super_chat_id, reply_to_message_id=int(thread_first_message))
|
||||
if tag:
|
||||
if message.content_type == types.ContentType.TEXT and len(message.text) + len(tag) < 4093:
|
||||
new_message = await message.bot.send_message(
|
||||
super_chat_id,
|
||||
message.text + "\n\n" + tag,
|
||||
reply_to_message_id=int(thread_first_message))
|
||||
else:
|
||||
new_message = await message.copy_to(super_chat_id,
|
||||
reply_to_message_id=int(thread_first_message))
|
||||
new_message_2 = await message.bot.send_message(
|
||||
super_chat_id, reply_to_message_id=new_message.message_id, text=tag)
|
||||
await _redis.set(_message_unique_id(bot.pk, new_message_2.message_id), message.chat.id,
|
||||
pexpire=thread_timeout)
|
||||
else:
|
||||
new_message = await message.copy_to(super_chat_id, reply_to_message_id=int(thread_first_message))
|
||||
await _redis.set(_message_unique_id(bot.pk, new_message.message_id), message.chat.id,
|
||||
pexpire=thread_timeout)
|
||||
except exceptions.BadRequest:
|
||||
new_message = await send_user_message(message, super_chat_id, bot)
|
||||
new_message = await send_user_message(message, super_chat_id, bot, tag)
|
||||
await _redis.set(
|
||||
_thread_unique_id(bot.pk, message.chat.id), new_message.message_id, pexpire=thread_timeout)
|
||||
else:
|
||||
# переслать супер-чат
|
||||
new_message = await send_user_message(message, super_chat_id, bot)
|
||||
new_message = await send_user_message(message, super_chat_id, bot, tag)
|
||||
await _redis.set(_thread_unique_id(bot.pk, message.chat.id), new_message.message_id,
|
||||
pexpire=thread_timeout)
|
||||
else: # личные сообщения не поддерживают потоки сообщений: просто отправляем сообщение
|
||||
await send_user_message(message, super_chat_id, bot)
|
||||
await send_user_message(message, super_chat_id, bot, tag)
|
||||
|
||||
|
||||
async def _increase_count(_bot):
|
||||
@@ -175,6 +211,9 @@ async def handle_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
await send_to_superchat(is_super_group, message, super_chat_id, bot)
|
||||
except (exceptions.Unauthorized, exceptions.ChatNotFound):
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Не удаётся связаться с владельцем бота"))
|
||||
except exceptions.RetryAfter:
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Слишком много сообщений, подождите одну минуту"),
|
||||
reply_to_message_id=message.message_id)
|
||||
except exceptions.TelegramAPIError as err:
|
||||
_logger.error(f"(exception on forwarding) {err}")
|
||||
return
|
||||
@@ -186,7 +225,10 @@ async def handle_user_message(message: types.Message, super_chat_id: int, bot):
|
||||
send_auto = not await _redis.get(_last_message_uid(bot.pk, message.chat.id))
|
||||
await _redis.setex(_last_message_uid(bot.pk, message.chat.id), 60 * 60 * 3, 1)
|
||||
if send_auto or bot.enable_always_second_message:
|
||||
text_obj = await BotSecondMessage.get_or_none(bot=bot, locale=str(message.from_user.locale))
|
||||
try:
|
||||
text_obj = await BotSecondMessage.get_or_none(bot=bot, locale=str(message.from_user.locale))
|
||||
except Exception:
|
||||
text_obj = None
|
||||
return SendMessage(chat_id=message.chat.id, text=text_obj.text if text_obj else bot.second_text,
|
||||
parse_mode="HTML")
|
||||
|
||||
@@ -223,14 +265,15 @@ async def handle_operator_message(message: types.Message, super_chat_id: int, bo
|
||||
else:
|
||||
await banned_user.delete()
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Пользователь разбанен"))
|
||||
if message.text.startswith("/tag "):
|
||||
tag = message.text.replace("/tag ", "")[:20].strip()
|
||||
if tag:
|
||||
await _redis.set(_tag_uid(bot.pk, chat_id), tag, pexpire=ServerSettings.redis_timeout_ms())
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Тег выставлен"))
|
||||
else:
|
||||
await _redis.delete(_tag_uid(bot.pk, chat_id))
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Тег убран"))
|
||||
if bot.enable_tags:
|
||||
if message.text and message.text.startswith("/tag "):
|
||||
tag = message.text.replace("/tag ", "")[:20].strip()
|
||||
if tag:
|
||||
await _redis.set(_tag_uid(bot.pk, chat_id), tag, pexpire=ServerSettings.redis_timeout_ms())
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Тег выставлен"))
|
||||
else:
|
||||
await _redis.delete(_tag_uid(bot.pk, chat_id))
|
||||
return SendMessage(chat_id=message.chat.id, text=_("Тег убран"))
|
||||
|
||||
try:
|
||||
await message.copy_to(chat_id)
|
||||
@@ -246,7 +289,10 @@ async def handle_operator_message(message: types.Message, super_chat_id: int, bo
|
||||
# в супер-чате кто-то пишет сообщение сам себе, только для личных сообщений
|
||||
if bot.enable_mailing:
|
||||
asyncio.create_task(MailingUser.get_or_create(telegram_id=message.chat.id, bot=bot))
|
||||
await message.forward(super_chat_id)
|
||||
try:
|
||||
await message.forward(super_chat_id)
|
||||
except exceptions.MessageCantBeForwarded:
|
||||
await message.copy_to(super_chat_id)
|
||||
# И отправить пользователю специальный текст, если он указан
|
||||
if bot.second_text:
|
||||
return SendMessage(chat_id=message.chat.id, text=bot.second_text, parse_mode="HTML")
|
||||
@@ -258,7 +304,10 @@ async def message_handler(message: types.Message, *args, **kwargs):
|
||||
|
||||
if message.text and message.text == "/start":
|
||||
# На команду start нужно ответить, не пересылая сообщение никуда
|
||||
text_obj = await BotStartMessage.get_or_none(bot=bot, locale=str(message.from_user.locale))
|
||||
try:
|
||||
text_obj = await BotStartMessage.get_or_none(bot=bot, locale=str(message.from_user.locale))
|
||||
except Exception:
|
||||
text_obj = None
|
||||
text = text_obj.text if text_obj else bot.start_text
|
||||
if bot.enable_olgram_text:
|
||||
text += _(ServerSettings.append_text())
|
||||
|
||||
Reference in New Issue
Block a user