MVP системы отложенных сообщений
This commit is contained in:
@@ -288,6 +288,8 @@ class MainBot(AnyBots):
|
|||||||
|
|
||||||
self.MakeBackups.start()
|
self.MakeBackups.start()
|
||||||
self.CheckDataBases.start()
|
self.CheckDataBases.start()
|
||||||
|
else:
|
||||||
|
self.SendingDeferredMessages.start()
|
||||||
|
|
||||||
async def BotOff(self):
|
async def BotOff(self):
|
||||||
if self.task_start:
|
if self.task_start:
|
||||||
@@ -303,6 +305,25 @@ class MainBot(AnyBots):
|
|||||||
print(f"{datetime.datetime.now().strftime('%H:%M:%S %d-%m-%Y')}:: Соединение с дискордом разорвано")
|
print(f"{datetime.datetime.now().strftime('%H:%M:%S %d-%m-%Y')}:: Соединение с дискордом разорвано")
|
||||||
await self.BotOff()
|
await self.BotOff()
|
||||||
|
|
||||||
|
@tasks.loop(seconds=60)
|
||||||
|
async def SendingDeferredMessages(self):
|
||||||
|
try:
|
||||||
|
async with self.DataBaseManager.session() as session:
|
||||||
|
async with session.begin():
|
||||||
|
stmt = self.DataBaseManager.select(self.DataBaseManager.model_classes['scheduled_messages']).where(
|
||||||
|
self.DataBaseManager.model_classes['scheduled_messages'].timestamp - datetime.datetime.now().timestamp() <= 0
|
||||||
|
).with_for_update()
|
||||||
|
messages = (await session.execute(stmt)).scalars().all()
|
||||||
|
|
||||||
|
for message in messages:
|
||||||
|
webhook = await self.fetch_webhook(message.webhook_id)
|
||||||
|
await webhook.send(await message.parse_message(self))
|
||||||
|
|
||||||
|
await session.delete(message)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
print(f"{datetime.datetime.now().strftime('%H:%M:%S %d-%m-%Y')}:: err SendingDeferredMessages: {error}")
|
||||||
|
|
||||||
@tasks.loop(seconds=60)
|
@tasks.loop(seconds=60)
|
||||||
async def CheckDataBases(self):
|
async def CheckDataBases(self):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import re
|
||||||
import disnake
|
import disnake
|
||||||
from disnake.ext import commands
|
from disnake.ext import commands
|
||||||
from disnake.ext import tasks
|
from disnake.ext import tasks
|
||||||
@@ -208,3 +209,39 @@ class AdminModule(commands.Cog):
|
|||||||
session.add(user_role)
|
session.add(user_role)
|
||||||
await ctx.send(embed = self.client.SuccessEmbed(description = f'Пользователю <@{userid}> успешно назначена роль <@&{roleid}>. \n```diff\n- Эта функция не выдаёт роли автоматически, поэтому требуется выдача вручную.```', colour = 0xff9900))
|
await ctx.send(embed = self.client.SuccessEmbed(description = f'Пользователю <@{userid}> успешно назначена роль <@&{roleid}>. \n```diff\n- Эта функция не выдаёт роли автоматически, поэтому требуется выдача вручную.```', colour = 0xff9900))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@commands.slash_command(name="запланировать_сообщение", description="Позволяет запланировать отправку анонсов и других сообщений")
|
||||||
|
async def schedule_message(self, ctx: disnake.AppCmdInter,
|
||||||
|
message_id: str = commands.Param(description="Укажите id сообщения, которое будет отложено", name="сообщение"),
|
||||||
|
webhook_link: str = commands.Param(description="Укажите ссылку на вебхук, от которого будет отправлено сообщение(по умолчанию от лица бота)", name="вебхук", default=None),
|
||||||
|
timestamp: int = commands.Param(description="Временная метка для отправки сообщения", name="таймстамп", default=None)):
|
||||||
|
|
||||||
|
await ctx.response.defer()
|
||||||
|
|
||||||
|
def extract_webhook_id(webhook_url: str) -> int | None:
|
||||||
|
pattern = r"^https:\/\/(?:canary\.|ptb\.)?discord(?:app)?\.com\/api\/webhooks\/(\d+)\/[\w\-]+$"
|
||||||
|
match = re.match(pattern, webhook_url)
|
||||||
|
if match:
|
||||||
|
return int(match.group(1))
|
||||||
|
return None
|
||||||
|
|
||||||
|
if webhook_link is None:
|
||||||
|
webhook_id = None
|
||||||
|
else:
|
||||||
|
webhook_id = extract_webhook_id(webhook_link)
|
||||||
|
if webhook_id is None:
|
||||||
|
await ctx.edit_original_response(embed = self.client.ErrEmbed(description = f'Некорректная ссылка'))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
async with self.DataBaseManager.session() as session:
|
||||||
|
async with session.begin():
|
||||||
|
if not (await self.DataBaseManager.model_classes['staff_users'].is_admin_or_moder_by_id(ctx.author.id, self.DataBaseManager, session, is_admin=True, is_moder=False)):
|
||||||
|
await ctx.edit_original_response(embed = self.client.ErrEmbed(description = f'У вас недостаточно полномочий, чтобы оставлять отложенные сообщения.'))
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
scheduled_message_model = self.DataBaseManager.model_classes['scheduled_messages']
|
||||||
|
message = scheduled_message_model(source_channel_id=ctx.channel.id, source_message_id=int(message_id), webhook_id=webhook_id, timestamp=timestamp)
|
||||||
|
session.add(message)
|
||||||
|
|
||||||
|
await ctx.edit_original_response(embed = self.client.SuccessEmbed(description = f'Успешно! Текст сообщения:\n {await message.parse_message(self.client)}', colour = 0xff9900))
|
||||||
|
return 0
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ class StaffUser(Base):
|
|||||||
return await self.__class__.is_admin_or_moder_by_id(self.id, DBManager, session)
|
return await self.__class__.is_admin_or_moder_by_id(self.id, DBManager, session)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def is_admin_or_moder_by_id(member_id, DBManager, session):
|
async def is_admin_or_moder_by_id(member_id, DBManager, session, *, is_admin=True, is_moder=True):
|
||||||
staff_branches_model = DBManager.model_classes['staff_branches']
|
staff_branches_model = DBManager.model_classes['staff_branches']
|
||||||
staff_users_roles_model = DBManager.model_classes['staff_users_roles']
|
staff_users_roles_model = DBManager.model_classes['staff_users_roles']
|
||||||
|
|
||||||
@@ -162,8 +162,8 @@ class StaffUser(Base):
|
|||||||
.where(
|
.where(
|
||||||
DBManager.and_(
|
DBManager.and_(
|
||||||
DBManager.or_(
|
DBManager.or_(
|
||||||
staff_branches_model.is_admin == True,
|
(staff_branches_model.is_admin == True) if is_admin else False,
|
||||||
staff_branches_model.is_moder == True,
|
(staff_branches_model.is_moder == True) if is_moder else False,
|
||||||
),
|
),
|
||||||
staff_users_roles_model.user_id == member_id
|
staff_users_roles_model.user_id == member_id
|
||||||
)
|
)
|
||||||
@@ -233,10 +233,18 @@ class AllowedDomain(Base):
|
|||||||
|
|
||||||
class ScheduledMessage(Base):
|
class ScheduledMessage(Base):
|
||||||
__tablename__ = "scheduled_messages"
|
__tablename__ = "scheduled_messages"
|
||||||
message_id: Mapped[discord_identificator_pk]
|
source_message_id: Mapped[discord_identificator_pk]
|
||||||
webhook_id: Mapped[discord_identificator]
|
source_channel_id: Mapped[discord_identificator]
|
||||||
timestamp: Mapped[float | None] = mapped_column(Float)
|
webhook_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True)
|
||||||
|
timestamp: Mapped[float | None] = mapped_column(Float, nullable=True, index=True)
|
||||||
|
|
||||||
|
async def parse_message(self, client):
|
||||||
|
krekchat = await client.fetch_guild(client.krekchat.id)
|
||||||
|
source_channel = await krekchat.fetch_channel(self.source_channel_id)
|
||||||
|
source_message = await source_channel.fetch_message(self.source_message_id)
|
||||||
|
|
||||||
|
content = source_message.content
|
||||||
|
return content
|
||||||
|
|
||||||
all_data = {
|
all_data = {
|
||||||
'base': Base
|
'base': Base
|
||||||
|
|||||||
Reference in New Issue
Block a user