Добавил проект с учетом .gitignore

This commit is contained in:
2025-07-06 19:24:54 +03:00
parent 41ad5a5b92
commit e796892942
20 changed files with 6162 additions and 3 deletions

927
src/cogs/roles.py Normal file
View File

@@ -0,0 +1,927 @@
import disnake
from disnake.ext import commands
from disnake.ext import tasks
import requests
import numpy as np
import aiohttp
import asyncio
import sqlite3
import sys
import os
import copy
import datetime
import math
import random
import json
import shutil
from constants.global_constants import *
def setup(bot):
bot.add_cog(MainRolesModule(bot))
class MainRolesModule(commands.Cog):
def __init__(self, client):
self.client = client
self.DataBaseManager = client.DataBaseManager
self.costrolecreate = client.costrolecreate
self.costrolerenewal = client.costrolerenewal
@commands.Cog.listener()
async def on_ready(self):
print(f'KrekFunBot roles module activated')
krekchat = await self.client.fetch_guild(constants["krekchat"])
self.me = disnake.utils.get(krekchat.roles, id=constants["me"])
@commands.slash_command(name="создать")
async def CreateSlash(self, ctx):
pass
@CreateSlash.sub_command(
description=f"создайте свою роль за {constants['costrolecreate']} крошек (ежемесячная оплата за роль:{constants['costrolerenewal']})",
name="роль")
async def CreateRoleSub(self, ctx: disnake.AppCmdInter,
name: str = commands.Param(description="Название роли", name="название"),
cost: int = commands.Param(description="цена роли для других участников в магазине", name="цена"),
colour: disnake.Colour = commands.Param(
description="цвет роли (указывается в hex формате, например: #ff9900)",
name="цвет", default=0xff9900)):
await ctx.response.defer()
error_helper = self.client.ErrorOutHelper(send_function = ctx.edit_original_message, err_name = "Ошибка создания роли")
if ctx.guild is None:
await error_helper.out(d="Эта команда не работает в личных сообщениях!")
return
async with self.DataBaseManager.session() as session:
await self.client.UserUpdate(member = ctx.author, session = session)
received_roles_custom_model = self.DataBaseManager.model_classes['received_roles_custom']
roles_custom_model = self.DataBaseManager.model_classes['roles_custom']
users_model = self.DataBaseManager.model_classes['users']
transaction_history_crumbs = self.DataBaseManager.model_classes['transaction_history_crumbs']
async with session.begin():
stmt = self.DataBaseManager.select(roles_custom_model).where(roles_custom_model.creator_id == ctx.author.id)
custom_role = (await session.execute(stmt)).scalars().first()
if not custom_role is None:
await error_helper.out(d=f'Вы уже владеете кастомной ролью')
return
krekchat = await self.client.fetch_guild(constants["krekchat"])
bordertop = krekchat.get_role(1221400083736690698)
borderbottom = krekchat.get_role(1221400071908753480)
if not (100 < cost < 2147483647):
await error_helper.out(d=f"Минимальная стоимость: 100 крошек")
return
if disnake.utils.get(ctx.guild.roles, name=name):
await error_helper.out(d=f"Роль с таким названием уже есть на сервере")
return
stmt = self.DataBaseManager.select(self.DataBaseManager.func.count()).select_from(roles_custom_model)
count = (await session.execute(stmt)).scalars().first()
if count >= 50:
await error_helper.out(d=f"На сервере сейчас максимальное количество кастомных ролей ({count}), попробуйте позже")
return
async with session.begin():
stmt = self.DataBaseManager.select(users_model).where(users_model.id == ctx.author.id).with_for_update()
user = (await session.execute(stmt)).scalars().first()
if user.crumbs < self.costrolecreate:
await error_helper.out(d=f"Для создания роли необходимо заплатить {self.costrolecreate} крошек, а у вас есть только {round(user.crumbs)}")
return
role = await ctx.guild.create_role(name=name, colour=colour)
await role.edit(position=bordertop.position - 1)
await ctx.author.add_roles(role)
custom_role = roles_custom_model(id = role.id, creator_id = ctx.author.id, cost = cost, renewal_date = 0)
await custom_role.renewal_date_update(self.client.TimeFormater)
session.add(custom_role)
transaction = transaction_history_crumbs(sender_id = ctx.author.id, amount = self.costrolecreate, description = f"Создание кастомной роли {role.mention}")
session.add(transaction)
user.crumbs -= self.costrolecreate
await session.flush()
received_role_custom = received_roles_custom_model(role_id = role.id, user_id = ctx.author.id)
session.add(received_role_custom)
await ctx.edit_original_message(embed=disnake.Embed(
title=f"Роль успешно создана! Вы можете проверить её статус или поменять настройки через команду /изменить роль",
description=f'', colour=0x2F3136))
@commands.slash_command(name="роль")
async def RoleInfoSlash(self, ctx):
pass
@RoleInfoSlash.sub_command(description="Показывает информацию о ролях", name="инфо")
async def RoleInfoSub(self, ctx: disnake.AppCmdInter,
role: disnake.Role = commands.Param(description="О какой роли хотите получить информацию?",
name="роль", default=None)):
await ctx.response.defer()
error_helper = self.client.ErrorOutHelper(send_function = ctx.edit_original_message, err_name = "Ошибка")
krekchat = await self.client.fetch_guild(constants["krekchat"])
roles_custom_model = self.DataBaseManager.model_classes['roles_custom']
roles_static_model = self.DataBaseManager.model_classes['roles_static']
custom_role = None
async with self.DataBaseManager.session() as session:
async with session.begin():
if role is None:
stmt = self.DataBaseManager.select(roles_custom_model).options(self.DataBaseManager.selectinload(roles_custom_model.users)).where(roles_custom_model.creator_id == ctx.author.id)
custom_role = (await session.execute(stmt)).scalars().first()
if custom_role is None:
await error_helper.out(d=f'Вы не создавали кастомных ролей.\nЧтобы получить информацию о статичной роли, введите целевую роль в поле "роль" при вызове команды "/роль инфо"')
return
role = krekchat.get_role(custom_role.id)
if role is None:
await error_helper.out(d=f'Вашей роли нет на сервере, вероятно, произошла ошибка, обратитесь к администратору')
return
else:
stmt = self.DataBaseManager.select(roles_static_model).where(roles_static_model.id == role.id)
static_role = (await session.execute(stmt)).scalars().first()
if not static_role is None:
embed = disnake.Embed(title=f"", description=f'### Информация о статичной роли {role.mention}', colour=0x2F3136)
embed.add_field(name=f"Описание", value=f"> {static_role.description}", inline=True)
await ctx.edit_original_message(embed=embed)
return
else:
stmt = self.DataBaseManager.select(roles_custom_model).options(self.DataBaseManager.selectinload(roles_custom_model.users)).where(roles_custom_model.id == role.id)
custom_role = (await session.execute(stmt)).scalars().first()
if custom_role is None:
await error_helper.out(d=f'Описания этой роли пока не существует.')
return
embed = disnake.Embed(title=f"", description=f'### Информация о кастомной роли {role.mention}', colour=0x2F3136)
embed.add_field(name=f"Время продления", value=f"> <t:{int(custom_role.renewal_date)}:D>", inline=True)
embed.add_field(name=f"Цена продления", value=f"> {constants['costrolerenewal']}", inline=True)
embed.add_field(name=f"", value=f"", inline=False)
embed.add_field(name=f"Количество покупок", value=f"> {len(custom_role.users)-1}", inline=True)
embed.add_field(name=f"Цена роли", value=f"> {custom_role.cost}", inline=True)
embed.add_field(name=f"", value=f"", inline=False)
try:
creator = await krekchat.fetch_member(custom_role.creator_id)
except:
creator = custom_role.creator_id
embed.add_field(name=f"Создатель", value=f"> {creator.mention if creator else custom_role.creator_id}", inline=True)
await ctx.edit_original_message(embed=embed)
@commands.slash_command(name="изменить")
async def RoleChangeSlash(self, ctx):
pass
@RoleChangeSlash.sub_command(description="Позволяет изменить вашу роль", name="роль")
async def RoleChangeSub(self, ctx: disnake.AppCmdInter):
await ctx.response.defer()
error_helper = self.client.ErrorOutHelper(send_function = ctx.edit_original_message, err_name = "Ошибка изменения роли")
if ctx.guild is None:
await error_helper.out(d="Эта команда не работает в личных сообщениях!")
return
krekchat = await self.client.fetch_guild(constants["krekchat"])
client = self.client
HexToRgb = self.client.HexToRgb
class ButtonsEditRole(disnake.ui.View):
client = self.client
def __init__(self, ctx, role, embed):
super().__init__(timeout=180)
self.ctx = ctx
self.role = role
self.embed = embed
@disnake.ui.button(label="Стоимость", custom_id="cost", style=disnake.ButtonStyle.blurple)
async def cost(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете редактировать эту роль", ephemeral = True)
await error.out()
return
modal = ActionModal(self.role, self.ctx, self.embed, "cost")
await inter.response.send_modal(modal)
@disnake.ui.button(label="Цвет", custom_id="color", style=disnake.ButtonStyle.blurple)
async def color(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете редактировать эту роль", ephemeral = True)
await error.out()
return
modal = ActionModal(self.role, self.ctx, self.embed, "color")
await inter.response.send_modal(modal)
@disnake.ui.button(label="Название", custom_id="name", style=disnake.ButtonStyle.blurple)
async def name(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете редактировать эту роль", ephemeral = True)
await error.out()
return
modal = ActionModal(self.role, self.ctx, self.embed, "name")
await inter.response.send_modal(modal)
@disnake.ui.button(label="Иконку", custom_id="icon", style=disnake.ButtonStyle.blurple)
async def icon(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете редактировать эту роль", ephemeral = True)
await error.out()
return
modal = ActionModal(self.role, self.ctx, self.embed, "icon")
await inter.response.send_modal(modal)
async def on_timeout(self):
for child in self.children:
if isinstance(child, (disnake.ui.Button, disnake.ui.BaseSelect)):
child.disabled = True
await self.ctx.edit_original_message(view=self)
class ActionModal(disnake.ui.Modal):
DataBaseManager = self.DataBaseManager
def __init__(self, role, ctx, embed, operation):
self.role = role
self.ctx = ctx
self.embed = embed
self.operation = operation
if operation == "name":
components = [
disnake.ui.TextInput(label="Новое название", placeholder="Например: abc", custom_id="name",
style=disnake.TextInputStyle.short, max_length=25)
]
if operation == "cost":
components = [
disnake.ui.TextInput(label="Новая стоимость", placeholder="Например: 123", custom_id="cost",
style=disnake.TextInputStyle.short, min_length=3)
]
if operation == "color":
components = [
disnake.ui.TextInput(label="Новый цвет", placeholder="Например: #ff9900", custom_id="color",
style=disnake.TextInputStyle.short)
]
if operation == "icon":
components = [
disnake.ui.TextInput(label="Введите ссылку на новую иконку", placeholder="Например: https://i.imgur.com/zWsCJun.png", custom_id="icon",
style=disnake.TextInputStyle.short)
]
super().__init__(title=operation, components=components, timeout=300)
async def callback(self, interaction: disnake.Interaction):
ctx = self.ctx
error_helper.send_function = interaction.send
async with self.DataBaseManager.session() as session:
key, value, = list(interaction.text_values.items())[0]
await interaction.response.defer(ephemeral=True)
if self.operation == "name":
await self.role.edit(name=value)
if self.operation == "color":
rgb = HexToRgb(value)
await self.role.edit(color=disnake.Colour.from_rgb(rgb[0], rgb[1], rgb[2]))
if self.operation == "cost":
cost = abs(int(value))
if not 100 < cost < 2147483647:
await error_helper.out(d = "Нельзя ставить стоимость роли меньше 100")
return
async with session.begin():
async with self.DataBaseManager.models['roles_custom'] as roles_custom_model:
stmt = self.DataBaseManager.update(roles_custom_model).where(roles_custom_model.creator_id == ctx.author.id).values(cost = cost)
await session.execute(stmt)
if self.operation == "icon":
image_url = value
TRUSTED_DOMAINS = ["imgur.com", "cdn.discordapp.com", "i.imgur.com"]
if ctx.guild.premium_tier < 2:
await error_helper.out(d = "Этот сервер должен быть уровня 2 буста для изменения иконок ролей")
return
if not any(domain in image_url for domain in TRUSTED_DOMAINS):
await error_helper.out(d = "Загрузка изображений разрешена только с ресурса https://imgur.com/")
return
if not image_url.lower().endswith((".png", ".jpg", ".jpeg")):
await error_helper.out(d = "Разрешены только файлы с расширением .png, .jpg или .jpeg")
return
async with aiohttp.ClientSession() as session:
try:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
async with session.get(image_url, headers=headers) as resp:
if resp.status != 200:
await error_helper.out(d = "Не удалось загрузить изображение")
return
content_type = resp.headers.get("Content-Type", "").lower()
if content_type not in ("image/png", "image/jpeg"):
await error_helper.out(d = "Файл должен быть изображением в формате PNG или JPEG")
return
# Проверка размера файла (не более 5 МБ)
content_length = int(resp.headers.get("Content-Length", 0))
if content_length > 5 * 1024 * 1024: # 5 МБ
await error_helper.out(d = "Размер файла не должен превышать 5 МБ")
return
image_data = await resp.read() # Получаем изображение в виде bytes
except aiohttp.ClientError as e:
await error_helper.out(d = f"Ошибка при загрузке изображения: {e}")
return
try:
await self.role.edit(icon=image_data, reason=f"Иконка изменена пользователем {ctx.author}")
except disnake.Forbidden:
await error_helper.out(d = "У бота недостаточно прав для изменения роли")
return
except disnake.HTTPException as e:
await error_helper.out(d = f"Ошибка при изменении роли: {e}")
return
krekchat = await client.fetch_guild(constants["krekchat"])
role = krekchat.get_role(self.role.id)
async with session.begin():
async with self.DataBaseManager.models['roles_custom'] as roles_custom_model:
stmt = self.DataBaseManager.select(roles_custom_model).where(roles_custom_model.id == self.role.id)
custom_role = (await session.execute(stmt)).scalars().first()
self.embed.description = f"**Укажите, какой параметр вы хотите изменить у роли {role.mention}:**\n\n**1) Стоимость: **```{custom_role.cost} крошек```\n**2) Цвет: **```{role.color}```\n**3) Название: **```{role.name}```"
await interaction.edit_original_message(embed=disnake.Embed(title="Роль успешно изменена!", description=f'', colour=0x2F3136))
await self.ctx.edit_original_message(embed=self.embed)
async with self.DataBaseManager.session() as session:
async with session.begin():
async with self.DataBaseManager.models['users'] as users_model:
stmt = self.DataBaseManager.select(users_model).options(self.DataBaseManager.joinedload(users_model.creation_role)).where(users_model.id == ctx.author.id)
user = (await session.execute(stmt)).scalars().first()
if user.creation_role is None:
await error_helper.out(d=f"Вы не создавали кастомных ролей")
return
role = krekchat.get_role(user.creation_role.id)
if not role:
await error_helper.out(d=f'Вашей роли нет на сервере')
return
embed = disnake.Embed(title=f"Управление ролью",
description=f'**Укажите, какой параметр вы хотите изменить у роли {role.mention}:**\n\n**1) Стоимость: **```{user.creation_role.cost} крошек```\n**2) Цвет: **```{role.color}```\n**3) Название: **```{role.name}```',
colour=0x2F3136)
embed.set_thumbnail(ctx.author.avatar)
EditRole = ButtonsEditRole(ctx, role, embed)
krekchat = await self.client.fetch_guild(constants["krekchat"])
await ctx.edit_original_message(embed=embed, view=EditRole)
@commands.slash_command(name="инвентарь")
async def RoleInventorySlash(self, ctx):
pass
@RoleInventorySlash.sub_command(description="Показывает все роли, которыми вы владеете", name="ролей")
async def RoleInventorySub(self, ctx: disnake.AppCmdInter):
await ctx.response.defer()
error_helper = self.client.ErrorOutHelper(send_function = ctx.edit_original_message, err_name = "Ошибка инвентаря")
if ctx.guild is None:
await error_helper.out(d="Эта команда не работает в личных сообщениях!")
return
krekchat = await self.client.fetch_guild(constants["krekchat"])
class RolesInventoryButtons(disnake.ui.View):
DataBaseManager = self.DataBaseManager
client = self.client
def __init__(self, ctx, inventory, embed):
super().__init__(timeout=180)
self.inventory = inventory
self.ctx = ctx
self.embed = embed
self.page = 1
self.maxpage = len(inventory) if len(inventory) > 0 else 1
self.left.disabled = (self.page == 1)
self.right.disabled = (self.page == self.maxpage)
@disnake.ui.button(label="1", custom_id="1", style=disnake.ButtonStyle.blurple)
async def one(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
await self.ToggleRoles(inter, button)
@disnake.ui.button(label="2", custom_id="2", style=disnake.ButtonStyle.blurple)
async def two(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
await self.ToggleRoles(inter, button)
@disnake.ui.button(label="3", custom_id="3", style=disnake.ButtonStyle.blurple)
async def three(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
await self.ToggleRoles(inter, button)
@disnake.ui.button(label="4", custom_id="4", style=disnake.ButtonStyle.blurple)
async def four(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
await self.ToggleRoles(inter, button)
@disnake.ui.button(label="5", custom_id="5", style=disnake.ButtonStyle.blurple)
async def five(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
await self.ToggleRoles(inter, button)
@disnake.ui.button(label="<", custom_id="left", style=disnake.ButtonStyle.secondary)
async def left(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
self.page -= 1
self.left.disabled = (self.page == 1)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedRoleInventoryChanger(self.inventory, self.embed, self.page, self.ctx.author)
await inter.response.edit_message(embed=self.embed, view=self)
@disnake.ui.button(label=">", custom_id="right", style=disnake.ButtonStyle.secondary)
async def right(self, button, inter):
if inter.author != self.ctx.author:
error = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете управлять ролями другого участника", ephemeral = True)
await error.out()
return
self.page += 1
self.left.disabled = (self.page == 1)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedRoleInventoryChanger(self.inventory, self.embed, self.page, self.ctx.author)
await inter.response.edit_message(embed=self.embed, view=self)
async def ToggleRoles(self, inter, button):
error_helper = self.client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка инвентаря", ephemeral = True)
if len(self.inventory) < 1:
await error_helper.out(d=f'Роли с таким номером нет на странице')
return
if len(self.inventory[self.page - 1]) < int(button.custom_id):
await error_helper.out(d=f'Роли с таким номером нет на странице')
return
role = self.inventory[self.page - 1][int(button.custom_id) - 1]
role = krekchat.get_role(role)
if not role:
return
if role in self.ctx.author.roles:
await self.ctx.author.remove_roles(role)
else:
roles_inventory_ids = []
async with self.DataBaseManager.session() as session:
async with session.begin():
async with self.DataBaseManager.models['received_roles_custom'] as received_roles_custom_model:
stmt = self.DataBaseManager.select(received_roles_custom_model).where(
received_roles_custom_model.user_id == ctx.author.id
)
custom_roles = (await session.execute(stmt)).scalars().all()
roles_inventory_ids += [role.role_id for role in custom_roles if not role.role_id in roles_inventory_ids]
async with self.DataBaseManager.models['received_roles_prize'] as received_roles_prize_model:
stmt = self.DataBaseManager.select(received_roles_prize_model).where(
received_roles_prize_model.user_id == ctx.author.id
)
prize_roles = (await session.execute(stmt)).scalars().all()
roles_inventory_ids += [role.role_id for role in prize_roles if not role.role_id in roles_inventory_ids]
if not role.id in roles_inventory_ids:
await error_helper.out(d=f"Эта роль пропала из вашего инвентаря")
return
await self.ctx.author.add_roles(role)
self.embed = await EmbedRoleInventoryChanger(self.inventory, self.embed, self.page, self.ctx.author)
await inter.response.edit_message(embed=self.embed, view=self)
async def on_timeout(self):
for child in self.children:
if isinstance(child, (disnake.ui.Button, disnake.ui.BaseSelect)):
child.disabled = True
await self.ctx.edit_original_message(view=self)
async def EmbedRoleInventoryChanger(inventory, embed, selfpage, member):
embed.clear_fields()
if len(inventory) == 0:
embed.add_field(name=f"В инвентаре пока ничего нет", value=f"", inline=False)
return embed
page = inventory[selfpage - 1]
c = 1
for roleid in page:
role = krekchat.get_role(roleid)
wearing = role in member.roles
embed.add_field(name=f"",
value=f"**{c})** {role.mention if role else roleid} {':green_circle:' if wearing else ':red_circle:'}",
inline=False)
c += 1
return embed
roles_inventory_sorted_ids = []
async with self.DataBaseManager.session() as session:
async with session.begin():
async with self.DataBaseManager.models['roles_custom'] as roles_custom_model:
stmt = self.DataBaseManager.select(roles_custom_model).where(
roles_custom_model.creator_id == ctx.author.id
)
creation_role = (await session.execute(stmt)).scalars().first()
if not creation_role is None:
roles_inventory_sorted_ids.append(creation_role.id)
async with self.DataBaseManager.models['received_roles_prize'] as received_roles_prize_model:
stmt = self.DataBaseManager.select(received_roles_prize_model).where(
received_roles_prize_model.user_id == ctx.author.id
)
prize_roles = (await session.execute(stmt)).scalars().all()
roles_inventory_sorted_ids += [role.role_id for role in prize_roles if not role.role_id in roles_inventory_sorted_ids]
async with self.DataBaseManager.models['received_roles_custom'] as received_roles_custom_model:
stmt = self.DataBaseManager.select(received_roles_custom_model).where(
received_roles_custom_model.user_id == ctx.author.id
)
custom_roles = (await session.execute(stmt)).scalars().all()
roles_inventory_sorted_ids += [role.role_id for role in custom_roles if not role.role_id in roles_inventory_sorted_ids]
ready_array = self.client.PartitioningEmbeder(roles_inventory_sorted_ids)
embed = disnake.Embed(title=f"Инвентарь ролей", description=f'', colour=0x2F3136)
embed.set_thumbnail(ctx.author.avatar)
view = RolesInventoryButtons(ctx, ready_array, embed)
embed = await EmbedRoleInventoryChanger(ready_array, embed, 1, ctx.author)
await ctx.edit_original_message(embed=embed, view=view)
@commands.slash_command(name="магазин")
async def ShopSlash(self, ctx):
pass
@ShopSlash.sub_command(description="Тут вы можете купить себе роль", name="ролей")
async def RolesShopSub(self, ctx: disnake.AppCmdInter):
'''
магазин ролей
'''
await ctx.response.defer()
error_helper = self.client.ErrorOutHelper(send_function = ctx.edit_original_message, err_name = "Ошибка магазина")
DataBaseManager = self.DataBaseManager
if ctx.guild is None:
await error_helper.out(d="Эта команда не работает в личных сообщениях!")
return
PartitioningEmbeder = self.client.PartitioningEmbeder
client = self.client
krekchat = await client.fetch_guild(constants["krekchat"])
class ShopView(disnake.ui.View):
def __init__(self, ctx, embed):
super().__init__(timeout=180)
self.ctx = ctx
self.embed = embed
async def initialize(self):
async with DataBaseManager.session() as session:
async with session.begin():
async with DataBaseManager.models['roles_custom'] as roles_custom_model:
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.asc(roles_custom_model.date_of_creation))
self.sortbydateofcreation = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.asc(roles_custom_model.cost))
self.sortbycost = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.desc(roles_custom_model.cost))
self.sortbycostreversed = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.desc(roles_custom_model.date_of_creation))
self.sortbydateofcreationreversed = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).outerjoin(roles_custom_model.users).group_by(roles_custom_model.id).order_by(DataBaseManager.func.count(DataBaseManager.models['users'].model.id).desc())
self.sortbypopularityreversed = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).outerjoin(roles_custom_model.users).group_by(roles_custom_model.id).order_by(DataBaseManager.func.count(DataBaseManager.models['users'].model.id).asc())
self.sortbypopularity = (await session.execute(stmt)).scalars().all()
self.sortvalues = {"sortbydateofcreation": self.sortbydateofcreation, "sortbycost": self.sortbycost,
"sortbycostreversed": self.sortbycostreversed,
"sortbydateofcreationreversed": self.sortbydateofcreationreversed,
"sortbypopularityreversed": self.sortbypopularity,
"sortbypopularity": self.sortbypopularityreversed}
self.maxpage = len(PartitioningEmbeder([i for i in self.sortbydateofcreation]))
self.page = 1
@disnake.ui.button(label="<<", custom_id="leftmax")
async def leftmax(self, button, inter):
await inter.response.defer()
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
self.page = 1
self.leftmax.disabled = (self.page == 1)
self.left.disabled = (self.page == 1)
self.rightmax.disabled = (self.page == self.maxpage)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedShopChanger(self.sort.values, self.embed, self.page, self.sortvalues)
await inter.message.edit(view=self, embed=self.embed)
@disnake.ui.button(label="<", custom_id="left")
async def left(self, button, inter):
await inter.response.defer()
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
self.page = max(self.page - 1, 1)
self.leftmax.disabled = (self.page == 1)
self.left.disabled = (self.page == 1)
self.rightmax.disabled = (self.page == self.maxpage)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedShopChanger(self.sort.values, self.embed, self.page, self.sortvalues)
await inter.message.edit(view=self, embed=self.embed)
@disnake.ui.button(label=">", custom_id="right")
async def right(self, button, inter):
await inter.response.defer()
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
self.page = min(self.page + 1, self.maxpage)
self.leftmax.disabled = (self.page == 1)
self.left.disabled = (self.page == 1)
self.rightmax.disabled = (self.page == self.maxpage)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedShopChanger(self.sort.values, self.embed, self.page, self.sortvalues)
await inter.message.edit(view=self, embed=self.embed)
@disnake.ui.button(label=">>", custom_id="rightmax")
async def rightmax(self, button, inter):
await inter.response.defer()
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
self.page = self.maxpage
self.leftmax.disabled = (self.page == 1)
self.left.disabled = (self.page == 1)
self.rightmax.disabled = (self.page == self.maxpage)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedShopChanger(self.sort.values, self.embed, self.page, self.sortvalues)
await inter.message.edit(view=self, embed=self.embed)
@disnake.ui.string_select(
placeholder="Сначала новые",
options=[
disnake.SelectOption(label="Сначала новые", value="sortbydateofcreationreversed", default=True),
disnake.SelectOption(label="Сначала старые", value="sortbydateofcreation", default=False),
disnake.SelectOption(label="Сначала дешёвые", value="sortbycost", default=False),
disnake.SelectOption(label="Сначала дорогие", value="sortbycostreversed", default=False),
disnake.SelectOption(label="Сначала популярные", value="sortbypopularity", default=False),
disnake.SelectOption(label="Сначала не популярные", value="sortbypopularityreversed", default=False),
],
min_values=1,
max_values=1,
)
async def sort(self, select: disnake.ui.StringSelect, inter: disnake.MessageInteraction):
await inter.response.defer()
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
self.page = 1
self.leftmax.disabled = (self.page == 1)
self.left.disabled = (self.page == 1)
self.rightmax.disabled = (self.page == self.maxpage)
self.right.disabled = (self.page == self.maxpage)
self.embed = await EmbedShopChanger(self.sort.values, self.embed, self.page, self.sortvalues)
for opt in range(len(self.sort.options)):
if self.sort.options[opt].value == self.sort.values[0]:
self.sort.options[opt].default = True
else:
self.sort.options[opt].default = False
await inter.message.edit(view=self, embed=self.embed)
@disnake.ui.button(label="1", custom_id="1", style=disnake.ButtonStyle.blurple, row=3)
async def one(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
await self.BuyRoles(inter, button)
@disnake.ui.button(label="2", custom_id="2", style=disnake.ButtonStyle.blurple, row=3)
async def two(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
await self.BuyRoles(inter, button)
@disnake.ui.button(label="3", custom_id="3", style=disnake.ButtonStyle.blurple, row=3)
async def three(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
await self.BuyRoles(inter, button)
@disnake.ui.button(label="4", custom_id="4", style=disnake.ButtonStyle.blurple, row=3)
async def four(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
await self.BuyRoles(inter, button)
@disnake.ui.button(label="5", custom_id="5", style=disnake.ButtonStyle.blurple, row=3)
async def five(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли в магазине другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
await self.BuyRoles(inter, button)
async def on_timeout(self):
for child in self.children:
if isinstance(child, (disnake.ui.Button, disnake.ui.BaseSelect)):
child.disabled = True
await self.ctx.edit_original_message(view=self)
async def BuyRoles(self, inter, button):
error_helper = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка покупки", ephemeral = True)
async with DataBaseManager.session() as session:
async with session.begin():
async with DataBaseManager.models['users'] as users_model:
stmt = DataBaseManager.select(users_model).options(DataBaseManager.selectinload(users_model.custom_roles)).where(users_model.id == inter.author.id)
user = (await session.execute(stmt)).scalars().first()
page = (PartitioningEmbeder(
self.sortvalues[self.sort.values[0] if len(self.sort.values) == 1 else "sortbydateofcreationreversed"]))[
self.page - 1]
if len(page) < int(button.custom_id):
await error_helper.out(d=f'Роли с таким номером нет на странице')
return
custom_role = page[int(button.custom_id) - 1]
if user.crumbs < custom_role.cost:
await error_helper.out(d=f'У вас недостаточно крошек')
return
if custom_role.id in [role.id for role in user.custom_roles]:
await error_helper.out(d=f'У вас уже есть эта роль')
return
role = krekchat.get_role(custom_role.id)
confirmembed = disnake.Embed(description=f'Вы уверены, что хотите преобрести роль {role.mention if role else custom_role.id} за {custom_role.cost} крошек?',
colour=0x2F3136)
ConfMessage = ConfirmView(self.ctx, role, custom_role)
await inter.response.edit_message(view=ConfMessage, embed=confirmembed)
class ConfirmView(disnake.ui.View):
def __init__(self, ctx, role, custom_role):
super().__init__(timeout=180)
self.ctx = ctx
self.role = role
self.custom_role = custom_role
@disnake.ui.button(label="Да", custom_id="yes", style=disnake.ButtonStyle.green)
async def yes(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли за другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
if not self.role:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка покупки", err_description = "Такая роль не найдена на сервере. Возможно, это ошибка базы данных", ephemeral = True)
await error.out()
return
ctx = self.ctx
async with DataBaseManager.session() as session:
async with session.begin():
async with DataBaseManager.models['users'] as users_model:
stmt = DataBaseManager.select(users_model).where(users_model.id == inter.author.id).with_for_update()
user = (await session.execute(stmt)).scalars().first()
stmt = DataBaseManager.select(users_model).where(users_model.id == self.custom_role.creator_id).with_for_update()
creator = (await session.execute(stmt)).scalars().first()
user.crumbs -= self.custom_role.cost
creator.crumbs += self.custom_role.cost
receive = DataBaseManager.models['received_roles_custom'].m(role_id = self.custom_role.id, user_id = user.id)
session.add(receive)
history = DataBaseManager.models['transaction_history_crumbs'].m(sender_id = user.id, recipient_id = creator.id, amount = self.custom_role.cost, description = f"Покупка роли {self.role.mention}")
await self.ctx.author.add_roles(self.role)
embed = disnake.Embed(description=f'Роль {self.role.mention} успешно преобретена!', colour=0x2F3136)
await self.ctx.edit_original_message(embed=embed, view=None)
@disnake.ui.button(label="Нет", custom_id="no", style=disnake.ButtonStyle.red)
async def no(self, button, inter):
if inter.author != self.ctx.author:
error = client.ErrorOutHelper(send_function = inter.send, err_name = "Ошибка доступа", err_description = "Вы не можете покупать роли за другого участника. Используйте команду `/магазин ролей`, чтобы купить роли", ephemeral = True)
await error.out()
return
ctx = self.ctx
embed = disnake.Embed(title=f"Магазин ролей", description=f'', colour=0x2F3136)
ShopMessage = ShopView(ctx, embed)
await ShopMessage.initialize()
ShopMessage.leftmax.disabled = (ShopMessage.page == 1)
ShopMessage.left.disabled = (ShopMessage.page == 1)
ShopMessage.rightmax.disabled = (ShopMessage.page == ShopMessage.maxpage)
ShopMessage.right.disabled = (ShopMessage.page == ShopMessage.maxpage)
embed = await EmbedShopChanger([], embed, 1)
embed.set_thumbnail(ctx.author.avatar)
await ctx.edit_original_message(view=ShopMessage, embed=embed)
async def on_timeout(self):
for child in self.children:
if isinstance(child, (disnake.ui.Button, disnake.ui.BaseSelect)):
child.disabled = True
await self.ctx.edit_original_message(view=self)
async def EmbedShopChanger(sortvalues, embed, selfpage, constvalues=None):
if not constvalues:
async with DataBaseManager.session() as session:
async with session.begin():
async with DataBaseManager.models['roles_custom'] as roles_custom_model:
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.asc(roles_custom_model.date_of_creation))
sortbydateofcreation = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.asc(roles_custom_model.cost))
sortbycost = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.desc(roles_custom_model.cost))
sortbycostreversed = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).order_by(DataBaseManager.desc(roles_custom_model.date_of_creation))
sortbydateofcreationreversed = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).outerjoin(roles_custom_model.users).group_by(roles_custom_model.id).order_by(DataBaseManager.func.count(DataBaseManager.models['users'].model.id).desc())
sortbypopularityreversed = (await session.execute(stmt)).scalars().all()
stmt = DataBaseManager.select(roles_custom_model).outerjoin(roles_custom_model.users).group_by(roles_custom_model.id).order_by(DataBaseManager.func.count(DataBaseManager.models['users'].model.id).asc())
sortbypopularity = (await session.execute(stmt)).scalars().all()
constvalues = {"sortbydateofcreation": sortbydateofcreation, "sortbycost": sortbycost,
"sortbycostreversed": sortbycostreversed,
"sortbydateofcreationreversed": sortbydateofcreationreversed,
"sortbypopularityreversed": sortbypopularity,
"sortbypopularity": sortbypopularityreversed}
embed.clear_fields()
page = \
(PartitioningEmbeder(constvalues[sortvalues[0] if len(sortvalues) == 1 else "sortbydateofcreationreversed"]))[
selfpage - 1]
c = 1
for custom_role in page:
try:
creator = await krekchat.fetch_member(custom_role.creator_id)
except:
creator = custom_role.creator_id
role = krekchat.get_role(custom_role.id)
embed.add_field(name=f"",
value=f"**{c})** {role.mention if role else custom_role.id}\n**Цена: **{custom_role.cost} крошек\n**Создатель: **{creator.mention if type(creator)!=int else creator}",
inline=False)
c += 1
return embed
embed = disnake.Embed(title=f"Магазин ролей", description=f'', colour=0x2F3136)
async with DataBaseManager.session() as session:
await self.client.UserUpdate(ctx.author, session = session)
async with session.begin():
async with DataBaseManager.models['roles_custom'] as roles_custom_model:
stmt = DataBaseManager.select(roles_custom_model)
roles = (await session.execute(stmt)).scalars().all()
if len(roles) == 0:
embed.description = "В магазине пока нет ни одной роли"
embed.set_thumbnail(ctx.author.avatar)
await ctx.edit_original_message(embed=embed)
return
ShopMessage = ShopView(ctx, embed)
await ShopMessage.initialize()
ShopMessage.leftmax.disabled = (ShopMessage.page == 1)
ShopMessage.left.disabled = (ShopMessage.page == 1)
ShopMessage.rightmax.disabled = (ShopMessage.page == ShopMessage.maxpage)
ShopMessage.right.disabled = (ShopMessage.page == ShopMessage.maxpage)
embed = await EmbedShopChanger([], embed, 1)
embed.set_thumbnail(ctx.author.avatar)
await ctx.edit_original_message(view=ShopMessage, embed=embed)