mirror of
https://github.com/yawaflua/AoyoBot.git
synced 2025-12-08 19:39:32 +02:00
Initialize project
This commit is contained in:
44
.github/workflows/docker-push.yml
vendored
Normal file
44
.github/workflows/docker-push.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Publish Docker image
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
|
||||
jobs:
|
||||
push_to_registries:
|
||||
name: Push Docker image to multiple registries
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/${{ github.repository }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Dima YaFlay
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
12
README.md
Normal file
12
README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Aoyo
|
||||
Aoyo is multifunctional discord bot, worked on disnake, supports localization and audit log(indev), 50% string objects is russian language
|
||||
|
||||
# Bot can:
|
||||
1. Create ticket(and save then)
|
||||
2. Mute|Unmute user
|
||||
3. Create custom voice channel with setuping(using bot alright)
|
||||
4. Give report command to user (Right button on mouse on user or message)
|
||||
5. Save channel
|
||||
6. Localizations
|
||||
# Support
|
||||
If u know some languages(English, Spanish, etc.), u can help to localize this bot (create pull or issue)
|
||||
123
cogs/auditChannel.py
Normal file
123
cogs/auditChannel.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from disnake.ext import commands
|
||||
from log import rootLogger
|
||||
from handlers import *
|
||||
import datetime
|
||||
class audit(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
rootLogger.info(f"{self.__class__.__name__} подключен")
|
||||
|
||||
@bot.event
|
||||
async def on_guild_channel_create(channel):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if "logs" in data["guilds"][f"{channel.guild.id}"]:
|
||||
embed = disnake.Embed(title="Создание канала", description=f"Создан канал: {channel.name}! \n Категория канала: {channel.category.name}", timestamp=datetime.datetime.now())
|
||||
await bot.get_channel(data["guilds"][f"{channel.guild.id}"]["logs"]).send(embed=embed)
|
||||
|
||||
@bot.event
|
||||
async def on_guild_channel_update(before, after):
|
||||
channel = before
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
after_changed = []
|
||||
before_changed = []
|
||||
if before.position != after.position:
|
||||
after_changed.append(f"Position: {after.position}")
|
||||
before_changed.append(f"Position: {before.position}")
|
||||
if before.changed_roles != after.changed_roles:
|
||||
after_changed.append(f'Roles: {after.changed_roles}')
|
||||
before_changed.append(f'Roles: {before.changed_roles}')
|
||||
if before.overwrites != after.overwrites:
|
||||
for item in after.overwrites:
|
||||
after_changed_perms = list(iter(after.overwrites[item].pair()[0]))
|
||||
a_item_mention = item.mention
|
||||
|
||||
for item in before.overwrites:
|
||||
before_changed_perms = list(iter(before.overwrites[item].pair()[0]))
|
||||
for item in range(len(before_changed_perms)):
|
||||
|
||||
if after_changed_perms[item][1] != before_changed_perms[item][1]:
|
||||
before_changed.append({a_item_mention: before_changed_perms[item]})
|
||||
after_changed.append({a_item_mention: after_changed_perms[item]})
|
||||
|
||||
if before.name != after.name:
|
||||
after_changed.append(f'Name: {after.name}')
|
||||
before_changed.append(f'Name: {before.name}')
|
||||
after_changed = str(after_changed).replace("'", '').replace('{', '').replace('}', '').replace('[', '').replace(']', '')
|
||||
before_changed = str(before_changed).replace("'", '').replace("{", '').replace("}", '').replace('[', '').replace(']', '')
|
||||
print(after_changed)
|
||||
if "logs" in data["guilds"][f"{channel.guild.id}"]:
|
||||
embed = disnake.Embed(title="Создание канала",
|
||||
description=f"Изменен канал: {channel.name}! \nКатегория канала: {channel.category.name};\nИзмененные настройки до: {before_changed};\nИзмененные настройки после: {after_changed};",
|
||||
timestamp=datetime.datetime.now())
|
||||
await bot.get_channel(data["guilds"][f"{channel.guild.id}"]["logs"]).send(embed=embed)
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_guild_channel_delete(channel):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if "logs" in data["guilds"][f"{channel.guild.id}"]:
|
||||
embed = disnake.Embed(title="Удаление канала", description=f"Удален канал: {channel.name}! \n Категория канала: {channel.category.name}", timestamp=datetime.datetime.now())
|
||||
await bot.get_channel(data["guilds"][f"{channel.guild.id}"]["logs"]).send(embed=embed)
|
||||
|
||||
@bot.event
|
||||
async def on_message_edit(before, after):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if "logs" in data["guilds"][f"{before.guild.id}"] and before.content != after.content:
|
||||
embed = disnake.Embed(title="Изменение сообщения.", description=f"Автор: {before.author.mention}\n Канал: {before.channel.name}",timestamp=datetime.datetime.now(), color=0x00ff00)
|
||||
embed.add_field(name="Сообщение до: ", value=before.content, inline=True)
|
||||
embed.add_field(name="Сообщение после: ", value=after.content, inline=True)
|
||||
embed.set_thumbnail(url=before.author.avatar)
|
||||
await bot.get_channel(data["guilds"][f"{before.guild.id}"]["logs"]).send(embed=embed)
|
||||
|
||||
@bot.event
|
||||
async def on_message_delete(message):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if "logs" in data["guilds"][f"{message.guild.id}"]:
|
||||
embed = disnake.Embed(title="Удаление сообщения.", description=f"Автор: {message.author.mention}\n Канал: {message.channel.name}\n Сообщение: {message.content}",timestamp=datetime.datetime.now(), color=disnake.Colour.from_rgb(186, 0, 6))
|
||||
embed.set_thumbnail(url=message.author.avatar)
|
||||
await bot.get_channel(data["guilds"][f"{message.guild.id}"]["logs"]).send(embed=embed)
|
||||
|
||||
@bot.event
|
||||
async def on_member_update(before, after):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if "logs" in data["guilds"][f"{before.guild.id}"]:
|
||||
if len(before.roles) > len(after.roles) or len(before.roles) < len(after.roles):
|
||||
embed = disnake.Embed(title="Изменение ролей.", description=f"Пользователь: {before.mention}",timestamp=datetime.datetime.now(), color=0x00ff00)
|
||||
rolesBefore = []
|
||||
rolesAfter = []
|
||||
for role in before.roles:
|
||||
rolesBefore.append(role.mention)
|
||||
for role in after.roles:
|
||||
rolesAfter.append(role.mention)
|
||||
embed.add_field(name="Роли до: ", value=str(rolesBefore).replace('[', '').replace(']', '').replace("'", ''), inline=True)
|
||||
embed.add_field(name="Роли после: ", value=str(rolesAfter).replace('[', '').replace(']', '').replace("'", ''), inline=True)
|
||||
embed.set_thumbnail(url=before.avatar)
|
||||
if len(rolesAfter) > len(rolesBefore):
|
||||
|
||||
for role in before.roles:
|
||||
try:
|
||||
rolesAfter.remove(role.mention)
|
||||
except:
|
||||
pass
|
||||
|
||||
embed.add_field(name="Измененная роль:", value=str(rolesAfter).replace('[', '').replace(']', '').replace("'", ''))
|
||||
else:
|
||||
for role in after.roles:
|
||||
try:
|
||||
rolesBefore.remove(role.mention)
|
||||
except:
|
||||
pass
|
||||
|
||||
embed.add_field(name="Измененная роль:", value=str(rolesBefore).replace('[', '').replace(']', '').replace("'", ''))
|
||||
await bot.get_channel(data["guilds"][f"{before.guild.id}"]["logs"]).send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(audit(bot))
|
||||
|
||||
102
cogs/automatization.py
Normal file
102
cogs/automatization.py
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
from handlers import *
|
||||
from disnake.ext import commands, tasks
|
||||
import disnake
|
||||
from datetime import datetime
|
||||
from log import rootLogger
|
||||
import pyspw
|
||||
import json
|
||||
import aiogram
|
||||
from aiogram import types
|
||||
class automatization(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.mutes.start()
|
||||
rootLogger.info("Starting automatization...")
|
||||
|
||||
@tasks.loop(seconds=60.0)
|
||||
async def mutes(self):
|
||||
thisTime = datetime.now().strftime("%d/%m/%Y %H:%M")
|
||||
path = Path("mute.json")
|
||||
userData = json.loads(path.read_text(encoding="utf-8"))
|
||||
if f"{thisTime}" in userData["mutes"]:
|
||||
for items in userData["mutes"][f"{thisTime}"]:
|
||||
guild = self.bot.get_guild(int(userData["mutes"][f"{thisTime}"][items]["guild"]))
|
||||
member = await guild.fetch_member(int(userData["mutes"][f"{thisTime}"][items]["user"]))
|
||||
await member.remove_roles(disnake.utils.get(guild.roles, id = int(takeSettings(guild.id, "mute_role"))))
|
||||
del userData["mutes"][f"{thisTime}"]
|
||||
path.write_text(json.dumps(userData, indent=4, ensure_ascii=False), encoding="utf-8", newline="\n")
|
||||
|
||||
@bot.listen()
|
||||
async def on_message(message: disnake.Message):
|
||||
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if "autoreaction" in data["guilds"][f"{message.guild.id}"] and not message.author.bot:
|
||||
if f"{message.channel.id}" in data["guilds"][f"{message.guild.id}"]["autoreaction"]:
|
||||
reaction1 = bot.get_emoji(int(data["guilds"][f"{message.guild.id}"]["autoreaction"][f"{message.channel.id}"]["reaction1"]))
|
||||
await message.add_reaction(reaction1)
|
||||
try:
|
||||
reaction2 = bot.get_emoji(int(data["guilds"][f"{message.guild.id}"]["autoreaction"][f"{message.channel.id}"]["reaction2"]))
|
||||
await message.add_reaction(reaction2)
|
||||
except: pass
|
||||
if "autobrench" in data["guilds"][f"{message.guild.id}"] and not message.author.bot:
|
||||
if f"{message.channel.id}" in data["guilds"][f"{message.guild.id}"]["autobrench"]:
|
||||
await message.create_thread(name='Autobranch')
|
||||
|
||||
@bot.event
|
||||
async def on_member_join(member):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
guildData = data["guilds"][f"{member.guild.id}"]
|
||||
onJoinRole = disnake.utils.get(member.guild.roles, id = int(takeSettings(member.guild.id, "on_join_role")))
|
||||
if "guest_room" in guildData or guildData["server"] != ["None", {}]:
|
||||
if "guest_room" in guildData:
|
||||
channelGuestRoom = bot.get_channel(int(guildData["guest_room"]))
|
||||
try:
|
||||
description = guildData["guest_text"].format(user=member.mention)
|
||||
except:
|
||||
description = guildData["guest_text"]
|
||||
emb = disnake.Embed(title=f"**Привет, {member.name}!**", description=description, colour=disnake.Colour.from_rgb(47, 49, 54))
|
||||
try:
|
||||
emb.set_image(url=guildData["image_url"])
|
||||
except:
|
||||
print()
|
||||
|
||||
if guildData["server"] != ["None", {}]:
|
||||
if guildData["server"]["server"] == "POOP":
|
||||
try:
|
||||
api = pyspw.SpApi(card_id=api_id, card_token=api_token).get_user(member.id).nickname
|
||||
except:
|
||||
print('Api error.... Again')
|
||||
if api:
|
||||
await member.edit(nick=api)
|
||||
await member.add_roles(bot.get_guild(member.guild.id).get_role(int(guildData["server"]["role"])))
|
||||
if "guest_room" in guildData:
|
||||
emb.set_footer(text=f"Игрок подтвержден! Ник: {api}")
|
||||
else:
|
||||
if "guest_room" in guildData:
|
||||
emb.set_footer(text=f"Игрок не подтвержден!")
|
||||
else:
|
||||
await member.add_roles(onJoinRole)
|
||||
if "guest_room" in guildData:
|
||||
await channelGuestRoom.send(member.mention,embed=emb)
|
||||
|
||||
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_member_remove(member):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
guildData = data["guilds"][f"{member.guild.id}"]
|
||||
if "image" in guildData:
|
||||
channelGuestRoom = bot.get_channel(int(takeSettings(member.guild.id, "guest_room")))
|
||||
emb = disnake.Embed(title=f"**Пока-пока, {member.name}!**", colour=disnake.Colour.from_rgb(47, 49, 54))
|
||||
emb.set_image(url=guildData["image"])
|
||||
emb.set_footer(text="Ждем тебя снова!")
|
||||
await channelGuestRoom.send(embed=emb)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(automatization(bot))
|
||||
281
cogs/buttons.py
Normal file
281
cogs/buttons.py
Normal file
@@ -0,0 +1,281 @@
|
||||
from disnake.ext import commands
|
||||
import disnake
|
||||
import json
|
||||
from pathlib import Path
|
||||
import pyspw
|
||||
from disnake import TextInputStyle
|
||||
from handlers import api_id, api_token, takeSettings, bot
|
||||
from asyncio import sleep
|
||||
from random import randint
|
||||
import datetime
|
||||
import chat_exporter
|
||||
import io
|
||||
|
||||
class buttons(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@bot.listen("on_button_click")
|
||||
async def button(inter: disnake.MessageInteraction):
|
||||
if inter.component.custom_id in ['role1', 'role2', 'role3']:
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
role = bot.get_guild(inter.guild.id).get_role(data["guilds"][f"{inter.guild.id}"]['issues'][f"{inter.message.id}"][inter.component.custom_id])
|
||||
await inter.author.add_roles(role)
|
||||
await inter.response.send_message(f'{role.mention} вам выдалась!', ephemeral=True)
|
||||
elif inter.component.custom_id == "buttonOnModal":
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
modalData = data["guilds"][f"{inter.guild.id}"]["modals"][f"{inter.channel.id}"][f"{inter.message.id}"]
|
||||
if data["guilds"][f"{inter.guild.id}"]["server"] != {}:
|
||||
try:
|
||||
api = pyspw.SpApi(card_id=api_id, card_token=api_token).get_user(inter.author.id).nickname
|
||||
custom_id="customModal-api"
|
||||
except Exception:
|
||||
api = None
|
||||
custom_id = "customModal"
|
||||
|
||||
component=[
|
||||
disnake.ui.TextInput(
|
||||
label=modalData["0"],
|
||||
custom_id=modalData["0"],
|
||||
style=TextInputStyle.short,
|
||||
),
|
||||
]
|
||||
for i in range(len(modalData)-3):
|
||||
i = i + 1
|
||||
modalDatas = modalData[f"{i}"]
|
||||
component.append(
|
||||
disnake.ui.TextInput(
|
||||
label=f"{modalDatas}",
|
||||
custom_id=f"{modalDatas}",
|
||||
style=TextInputStyle.short,
|
||||
),
|
||||
)
|
||||
|
||||
await inter.response.send_modal(
|
||||
title="Aoyo Modal System",
|
||||
custom_id=custom_id,
|
||||
components=component,)
|
||||
elif inter.component.custom_id in ["closePrivateRoom", "hidePrivateRoom"]:
|
||||
guild = bot.get_guild(inter.guild.id)
|
||||
role = guild.get_role(int(takeSettings(inter.guild.id, "on_join_role")))
|
||||
member = inter.author
|
||||
if inter.component.custom_id == "closePrivateRoom":
|
||||
overwrites = {
|
||||
guild.default_role: disnake.PermissionOverwrite(connect=False),
|
||||
role: disnake.PermissionOverwrite(connect=False),
|
||||
member: disnake.PermissionOverwrite(connect=True)
|
||||
}
|
||||
else:
|
||||
overwrites = {
|
||||
guild.default_role: disnake.PermissionOverwrite(view_channel=False),
|
||||
role: disnake.PermissionOverwrite(view_channel=False),
|
||||
member: disnake.PermissionOverwrite(view_channel=True)
|
||||
}
|
||||
await bot.get_channel(inter.channel.id).edit(overwrites=overwrites)
|
||||
await inter.response.send_message("Готово.", ephemeral=True)
|
||||
|
||||
elif inter.component.custom_id in ["giveOwner", "kickUser", "deleteChannel"]:
|
||||
path = Path("tempFiles/voiceTempFile.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if int(data["voice_channels"][f"{inter.channel.id}"]["channel_owner"]) == inter.author.id:
|
||||
if inter.component.custom_id == "giveOwner": await inter.response.send_message("Отправьте пинг игрока, которому хотите передать права", ephemeral=True)
|
||||
elif inter.component.custom_id == "deleteChannel": await inter.channel.delete()
|
||||
else: await inter.response.send_message("Отправьте пинг игрока, которого хотите кикннуть", ephemeral=True)
|
||||
def check(m):
|
||||
return m.author == inter.author and m.channel == inter.channel
|
||||
try:
|
||||
message = await bot.wait_for('message', timeout=30.0, check=check)
|
||||
except TimeoutError:
|
||||
return
|
||||
else:
|
||||
content = message.mentions[0].id
|
||||
await message.delete()
|
||||
if inter.component.custom_id == "giveOwner":
|
||||
data["voice_channels"][f"{inter.channel.id}"]["channel_owner"] = content
|
||||
data["voice_channels"][f"{inter.channel.id}"]["old_channel_owner"] = inter.author.id
|
||||
path.write_text(json.dumps(data, indent=6), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message(f"Готово! Владелец канала теперь: <@{content}>", ephemeral=True)
|
||||
else:
|
||||
member = await bot.get_guild(inter.guild.id).fetch_member(int(content))
|
||||
await member.edit(voice_channel=None)
|
||||
await inter.response.send_message(f"Готово! <@{content}> был кикнут", ephemeral=True)
|
||||
else:
|
||||
await inter.response.send_message("Вы не создатель канала!", ephemeral=True)
|
||||
|
||||
elif inter.component.custom_id == "takeOwner":
|
||||
path = Path("tempFiles/voiceTempFile.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if data["voice_channels"][f"{inter.channel.id}"]["old_channel_owner"] == inter.author.id:
|
||||
data["voice_channels"][f"{inter.channel.id}"]["channel_owner"] = inter.author.id
|
||||
path.write_text(json.dumps(data, indent=6), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message(f"Готово! Владелец канала теперь: <@{inter.author.id}>", ephemeral=True)
|
||||
elif inter.component.custom_id == "renamePrivateRoom":
|
||||
await inter.response.send_modal(
|
||||
title="Aoyo Modal System",
|
||||
custom_id="renamePrivateRoom",
|
||||
components=[
|
||||
disnake.ui.TextInput(
|
||||
label='Новое название канала:',
|
||||
placeholder="Я люблю нюхать бебру",
|
||||
custom_id='newNamePrivateRoom',
|
||||
style=disnake.TextInputStyle.short,
|
||||
)
|
||||
],
|
||||
)
|
||||
elif inter.component.custom_id == "setUsersLimit":
|
||||
await inter.response.send_modal(
|
||||
title="Aoyo Modal System",
|
||||
custom_id="setUsersLimit",
|
||||
components=[
|
||||
disnake.ui.TextInput(
|
||||
label='Новое максимальное кол-во пользователей:',
|
||||
placeholder="1",
|
||||
custom_id='newUserLimit',
|
||||
style=disnake.TextInputStyle.short,
|
||||
)
|
||||
],
|
||||
)
|
||||
# tickets
|
||||
elif inter.component.custom_id in ["firstTicket", "secondTicket", "thirdTicket", "createTicket", "reportCreateTicket"]:
|
||||
path = Path("guilds/guilds.json")
|
||||
ticketData = Path("tempFiles/ticket.json")
|
||||
aJsonData = json.loads(path.read_text(encoding="utf-8"))
|
||||
fromJsonData = json.loads(path.read_text(encoding="utf-8")).get('guilds')[f"{inter.guild_id}"]
|
||||
toJsonData = json.loads(ticketData.read_text(encoding="utf-8"))
|
||||
mention = inter.author.mention
|
||||
if inter.component.custom_id == "firstTicket":
|
||||
role = fromJsonData["ticket"][f"{inter.channel.id}"][f"{inter.message.id}"]["first_role"]
|
||||
if inter.component.custom_id == "secondTicket":
|
||||
role = fromJsonData["ticket"][f"{inter.channel.id}"][f"{inter.message.id}"]["second_role"]
|
||||
if inter.component.custom_id == "thirdTicket":
|
||||
role = fromJsonData["ticket"][f"{inter.channel.id}"][f"{inter.message.id}"]["third_role"]
|
||||
if inter.component.custom_id == "reportCreateTicket":
|
||||
role = fromJsonData["moderation_role"]
|
||||
embedMessage = inter.message.embeds[0]
|
||||
mention = f"<@{embedMessage.footer.text}> \n{inter.author.mention}"
|
||||
|
||||
await inter.message.edit(components=[
|
||||
disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id="reportAccept", label="Принять"),
|
||||
disnake.ui.Button(label="Создать тикет", style=disnake.ButtonStyle.success, custom_id="reportCreateTicket", disabled=True),
|
||||
disnake.ui.Button(label="Удалить репорт", style=disnake.ButtonStyle.danger, custom_id="deleteReport"),
|
||||
],)
|
||||
embed = disnake.Embed(title="Управление тикетом", description="Если вы готовы завершить тикет, нажмите ниже.", colour=disnake.Color.blue())
|
||||
buttons = disnake.ui.View()
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id="closeTicket", label="Закрыть тикет"))
|
||||
|
||||
guild = bot.get_guild(inter.guild.id)
|
||||
roleOverwrite = guild.get_role(int(takeSettings(inter.guild.id, "on_join_role")))
|
||||
roleTicket = guild.get_role(int(role))
|
||||
overwrites = {
|
||||
guild.default_role: disnake.PermissionOverwrite(view_channel=False),
|
||||
roleOverwrite: disnake.PermissionOverwrite(view_channel=False),
|
||||
inter.author: disnake.PermissionOverwrite(view_channel=True),
|
||||
roleTicket: disnake.PermissionOverwrite(view_channel=True)
|
||||
}
|
||||
if not fromJsonData['ticket'].get('counter'):
|
||||
aJsonData['guilds'][f'{inter.guild.id}']['ticket']['counter'] = 1
|
||||
aJsonData['guilds'][f'{inter.guild.id}']['ticket']['counter'] = int(aJsonData['guilds'][f'{inter.guild.id}']['ticket']['counter']) + 1
|
||||
count = aJsonData['guilds'][f'{inter.guild.id}']['ticket']['counter']
|
||||
category = disnake.utils.get(guild.categories, id=inter.channel.category.id)
|
||||
channel = await guild.create_text_channel(name=f"ticket-{count}", category=category, overwrites=overwrites)
|
||||
await channel.send(content=f"{mention}\n<@&{role}>",embed=embed, view=buttons)
|
||||
newJsonData = {
|
||||
"channel_owner": f"{inter.author.mention}",
|
||||
"channel_name": f"{channel.name}",
|
||||
"panel": f"{inter.component.custom_id}"
|
||||
}
|
||||
if not toJsonData["ticket"].get(f"{inter.guild_id}"):
|
||||
toJsonData["ticket"][f"{inter.guild_id}"] = {}
|
||||
|
||||
toJsonData["ticket"][f"{inter.guild_id}"][f"{channel.id}"] = newJsonData
|
||||
|
||||
if inter.component.custom_id == "reportCreateTicket":
|
||||
toJsonData["ticket"][f"{inter.guild_id}"][f"{channel.id}"]["user_name"] = f"{embedMessage.footer.text}"
|
||||
path.write_text(json.dumps(aJsonData, indent=3), encoding="utf-8", newline="\n")
|
||||
ticketData.write_text(json.dumps(toJsonData, indent=3), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message(f'Ваш тикет: {channel.mention}', ephemeral=True)
|
||||
|
||||
elif inter.component.custom_id == "closeTicket":
|
||||
embed = disnake.Embed(title="Подтверждение", description=f"Вы уверены, что хотите закрыть тикет, {inter.author.name}?")
|
||||
buttons = disnake.ui.View()
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id="closeTicketPerm", label="Да, закрыть тикет"))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id="cancelCloseTicket", label="Нет"))
|
||||
await inter.response.send_message(embed=embed, view=buttons)
|
||||
await inter.message.edit(components=[
|
||||
disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id="closeTicket", label="Закрыть тикет", disabled=True),
|
||||
],)
|
||||
elif inter.component.custom_id == "cancelCloseTicket":
|
||||
for message in (await inter.channel.history(limit=None, oldest_first=True).flatten()):
|
||||
msg = await bot.get_channel(inter.channel.id).fetch_message(message.id)
|
||||
break
|
||||
await msg.edit(components=[
|
||||
disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id="closeTicket", label="Закрыть тикет", disabled=False),
|
||||
],)
|
||||
await inter.message.delete()
|
||||
elif inter.component.custom_id == "closeTicketPerm":
|
||||
embed = disnake.Embed(title='**Aoyo ticket system**', description=f'Канал закрыт {inter.author.mention}', color=0x00ff00)
|
||||
embed.set_image('https://media.discordapp.net/attachments/876280751488909332/979778066417070151/Frame_280.png?width=1440&height=4')
|
||||
buttons = disnake.ui.View().add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id='deleteChannelTicket', label='Удалить канал'))
|
||||
channel = bot.get_channel(inter.channel.id)
|
||||
overwrites = {
|
||||
inter.author: disnake.PermissionOverwrite(view_channel=False),
|
||||
}
|
||||
await inter.message.delete()
|
||||
await channel.edit(overwrites=overwrites, name=f"closed-{channel.name[7:]}")
|
||||
await channel.send(embed=embed, view=buttons)
|
||||
|
||||
elif inter.component.custom_id == "deleteChannelTicket":
|
||||
path = Path("guilds/guilds.json")
|
||||
ticketData = Path("tempFiles/ticket.json")
|
||||
fromJsonData = json.loads(path.read_text(encoding="utf-8"))
|
||||
toJsonData = json.loads(ticketData.read_text(encoding="utf-8"))
|
||||
guild = bot.get_guild(inter.guild.id)
|
||||
member = await guild.fetch_member(int(toJsonData["ticket"][f"{inter.guild.id}"][f"{inter.channel.id}"]["channel_owner"].replace('<@', '').replace('>', '')))
|
||||
channel = bot.get_channel(int(fromJsonData["guilds"][f"{inter.guild_id}"]["transcript_channel"]))
|
||||
transcript = await chat_exporter.export(
|
||||
inter.channel,
|
||||
bot=bot,
|
||||
)
|
||||
embed = disnake.Embed(title='**Aoyo ticket system**', colour=disnake.Color.green())
|
||||
embed.add_field(name="Создатель", value=member.mention)
|
||||
embed.add_field(name="Название канала", value=toJsonData["ticket"][f"{inter.guild.id}"][f"{inter.channel.id}"]["channel_name"], inline=False)
|
||||
embed.add_field(name="Причина открытия", value=toJsonData["ticket"][f"{inter.guild.id}"][f"{inter.channel.id}"]["panel"], inline=True)
|
||||
embed.set_image('https://media.discordapp.net/attachments/876280751488909332/979778066417070151/Frame_280.png?width=1440&height=4')
|
||||
|
||||
transcript_file = disnake.File(
|
||||
io.BytesIO(transcript.encode()),
|
||||
filename=f"transcript-{inter.channel.name}.html",
|
||||
)
|
||||
|
||||
await bot.get_channel(int(fromJsonData["guilds"][f"{inter.guild.id}"]["transcript_channel"])).send(f"**Сохранен и отправлен {inter.channel.name}**",file=transcript_file)
|
||||
embed = disnake.Embed(title='**Aoyo ticket system**', description='Канал удалится в течении 10 секунд.', colour=disnake.Color.purple())
|
||||
await inter.message.edit(view=None)
|
||||
await inter.response.send_message(embed=embed)
|
||||
await sleep(9)
|
||||
await bot.get_channel(inter.channel.id).delete(reason=f'Deleted by {inter.author.id}')
|
||||
del toJsonData["ticket"][f"{inter.guild.id}"][f"{inter.channel.id}"]
|
||||
ticketData.write_text(json.dumps(toJsonData, indent=3), encoding="utf-8", newline="\n")
|
||||
# report
|
||||
elif inter.component.custom_id == "reportAccept":
|
||||
member = await bot.get_guild(inter.guild.id).fetch_member(int(inter.message.embeds[0].footer.text))
|
||||
await member.send(embed=disnake.Embed(title="Aoyo REPORT", description=f"Ваш репорт был принят и рассмотрен модератором {inter.author.mention}", color=0x00ff00,timestamp=datetime.datetime.now()))
|
||||
await inter.message.edit(components=[
|
||||
disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id="reportAccept", label="Принять", disabled=True),
|
||||
disnake.ui.Button(label="Создать тикет", style=disnake.ButtonStyle.success, custom_id="reportCreateTicket", disabled=True),
|
||||
disnake.ui.Button(label="Удалить репорт", style=disnake.ButtonStyle.danger, custom_id="deleteReport", disabled=True),
|
||||
],)
|
||||
await inter.message.edit(embed=inter.message.embeds[0].add_field(name="Репорт был принят!", value=f"Репорт принял {inter.author.mention}"))
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
elif inter.component.custom_id == "deleteReport":
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
await inter.message.edit(components=[
|
||||
disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id="reportAccept", label="Принять", disabled=True),
|
||||
disnake.ui.Button(label="Создать тикет", style=disnake.ButtonStyle.success, custom_id="reportCreateTicket", disabled=True),
|
||||
disnake.ui.Button(label="Удалить репорт", style=disnake.ButtonStyle.danger, custom_id="deleteReport", disabled=True),
|
||||
],)
|
||||
else:
|
||||
await inter.response.send_message('Ошибка!', ephemeral=True)
|
||||
def setup(bot):
|
||||
bot.add_cog(buttons(bot))
|
||||
47
cogs/court.py
Normal file
47
cogs/court.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from handlers import bot
|
||||
from disnake.ext import commands
|
||||
import disnake
|
||||
class courtCogs(commands.Cog):
|
||||
def __init__(self, bot: disnake.Client):
|
||||
self.bot = bot
|
||||
|
||||
|
||||
@commands.slash_command(name="court")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def court(self, inter):
|
||||
embed = disnake.Embed(title="**Города, где проходил суд**")
|
||||
embed.add_field(name=" Селестия", value="> **Расположение**: -1050 -500 \n > **Количество проведенных судов**: (3)", inline=False)
|
||||
embed.add_field(name=" South Point", value="> **Расположение**: -444 727 \n > **Количество проведенных судов**: (3)", inline=False)
|
||||
embed.set_footer(text="Города добавляются через кнопки ниже. За пренебрежение командами следует наказание!")
|
||||
view = disnake.ui.View()
|
||||
view.add_item(disnake.ui.Button(style=disnake.ButtonStyle.blurple, label="Добавить город", custom_id="addSity"))
|
||||
view.add_item(disnake.ui.Button(style=disnake.ButtonStyle.blurple, label="Провести суд", custom_id="addCourt"))
|
||||
|
||||
await inter.response.send_message(embed=embed, view=view)
|
||||
|
||||
@commands.Cog.listener("on_button_click")
|
||||
async def on_button_click_court(self, inter: disnake.MessageInteraction):
|
||||
|
||||
if inter.component.custom_id == "addSity":
|
||||
await inter.response.send_modal(title="Добавить город", custom_id="addSityModal", components=[
|
||||
disnake.ui.TextInput(
|
||||
label="Название города",
|
||||
custom_id="sityName",
|
||||
style=disnake.TextInputStyle.short,
|
||||
),
|
||||
disnake.ui.TextInput(
|
||||
label="Координаты города",
|
||||
custom_id="sityCoordinates",
|
||||
style=disnake.TextInputStyle.short,
|
||||
)])
|
||||
if inter.component.custom_id == "addCourt":
|
||||
await inter.response.send_modal(title="Провести суд", custom_id="addCourtModal", components=[
|
||||
disnake.ui.TextInput(
|
||||
label="Название города",
|
||||
custom_id="sityName",
|
||||
style=disnake.TextInputStyle.short,
|
||||
)])
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(courtCogs(bot))
|
||||
70
cogs/customModals.py
Normal file
70
cogs/customModals.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from handlers import *
|
||||
from disnake.ext import *
|
||||
from disnake import *
|
||||
import disnake
|
||||
from pathlib import Path
|
||||
import pyspw
|
||||
import json
|
||||
|
||||
class customModals(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
rootLogger.info(f"{__class__.__name__} подключен!")
|
||||
|
||||
|
||||
@commands.slash_command(
|
||||
name=Localised("createmodal", key="CREATE_MODAL_NAME"),
|
||||
description=Localised("Create your`s own modal`s window.", key="CREATE_MODAL_DESC")
|
||||
)
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def createCustomModals(inter, channel: disnake.TextChannel, text_in_message: str, first_label: str, second_label: str, third_label: str, fourth_label: str=Option("fourth_label"), fifth_label: str=Option("fifth_label")):
|
||||
"""Creation of your own windows (profiles)
|
||||
|
||||
Args:
|
||||
channel (disnake.TextChannel): This is required to transfer the channel where the message will go about the application
|
||||
text_in_message (str): This requires to transmit the text that will be above the application button (questionnaire/modal)
|
||||
first_label (str): Enter here what you want to see in the first line of the questionnaire (tests are welcome)
|
||||
second_label (str): Enter here what you want to see in the second line of the questionnaire (tests are welcome)
|
||||
third_label (str): Enter here what you want to see in the third line of the questionnaire (tests are welcome)
|
||||
fourth_label (str, optional): Enter here what you want to see in the fourth line of the questionnaire (tests are welcome)
|
||||
fifth_label (str, optional): Enter here what you want to see in the fifth line of the questionnaire (tests are welcome)
|
||||
"""
|
||||
embed = disnake.Embed(title="**Aoyo Modal SYSTEM**")
|
||||
embed.add_field(name="Нажмите на кнопку нижу для подачи заявки!", value=f"{text_in_message}")
|
||||
buttons = disnake.ui.View().add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id='buttonOnModal', label='Нажми на меня!'))
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
msg = await bot.get_channel(inter.channel.id).send(embed=embed, view=buttons)
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
arrayToSql = ["guild_id", "message_id", "channel_id", "first", "second", "third"]
|
||||
dataToSql = [inter.guild.id, msg.id, channel.id, first_label, second_label, third_label]
|
||||
newData = {
|
||||
"channel": channel.id,
|
||||
0: first_label,
|
||||
1: second_label,
|
||||
2: third_label,
|
||||
"message_id": msg.id
|
||||
}
|
||||
if type(fourth_label) == str:
|
||||
newData["3"] = fourth_label
|
||||
arrayToSql.append("fourth")
|
||||
dataToSql.append(fourth_label)
|
||||
if type(fifth_label) == str:
|
||||
newData["4"] = fifth_label
|
||||
arrayToSql.append("fifths")
|
||||
dataToSql.append(fifth_label)
|
||||
print(SQL().createTable("modals"))
|
||||
print(SQL().insertData(arrayToSql, dataToSql, "modals"))
|
||||
if f"modals" not in data["guilds"][f"{inter.guild.id}"]:
|
||||
data["guilds"][f"{inter.guild.id}"]["modals"] = {}
|
||||
if f"{inter.channel.id}" not in data["guilds"][f"{inter.guild.id}"]["modals"]:
|
||||
data["guilds"][f"{inter.guild.id}"]["modals"][f"{inter.channel.id}"] = {}
|
||||
|
||||
data["guilds"][f"{inter.guild.id}"]["modals"][f"{inter.channel.id}"][f"{msg.id}"] = newData
|
||||
path.write_text(json.dumps(data, indent=6), encoding="utf-8", newline="\n")
|
||||
|
||||
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(customModals(bot))
|
||||
166
cogs/modals.py
Normal file
166
cogs/modals.py
Normal file
@@ -0,0 +1,166 @@
|
||||
# modals.py
|
||||
from handlers import logger, bot, api_id, api_token
|
||||
|
||||
import disnake
|
||||
from pathlib import Path
|
||||
import json
|
||||
from disnake.ext import commands
|
||||
import pyspw
|
||||
import sqlite3
|
||||
import psycopg2
|
||||
from handlers import execute
|
||||
class modals(commands.Cog):
|
||||
def __init__(self, bot: disnake.Client):
|
||||
self.bot = bot
|
||||
logger.info(f"Модуль {self.__class__.__name__} включен!")
|
||||
|
||||
@commands.Cog.listener("on_modal_submit")
|
||||
async def on_modal_submit(self, inter: disnake.ModalInteraction):
|
||||
await inter.response.send_message(f"{inter.custom_id}", ephemeral=True)
|
||||
if inter.custom_id in ["changeNamePrivateRoom", "newUsersLimit"]:
|
||||
path = Path("tempFiles/voiceTempFile.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if (
|
||||
int(data["voice_channels"][f"{inter.channel.id}"]["channel_owner"])
|
||||
== inter.author.id
|
||||
):
|
||||
path = Path("tempFiles/voiceName.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
for key, value in inter.text_values.items():
|
||||
if inter.custom_id == "changeNamePrivateRoom":
|
||||
data[f"{inter.author.id}"] = {
|
||||
"chat_name": f"{value[:1024]}",
|
||||
"channel_id": f"{inter.channel.id}",
|
||||
}
|
||||
path.write_text(
|
||||
json.dumps(data, indent=7), encoding="utf-8", newline="\n"
|
||||
)
|
||||
await self.bot.get_channel(inter.channel_id).edit(name=value[:1024])
|
||||
else:
|
||||
await self.bot.get_channel(inter.channel_id).edit(
|
||||
user_limit=int(value[:1024])
|
||||
)
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
else:
|
||||
await inter.response.send_message(
|
||||
"Вы не создатель канала!", ephemeral=True
|
||||
)
|
||||
elif inter.custom_id in ["customModal", "customModal-api", "interpol", "interpol-api"]:
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
embed = disnake.Embed(
|
||||
description=f"{inter.author.mention}", colour=inter.author.colour
|
||||
)
|
||||
for key, value in inter.text_values.items():
|
||||
embed.add_field(
|
||||
name=key.capitalize(),
|
||||
value=value[:1024],
|
||||
inline=False,
|
||||
)
|
||||
|
||||
embed.set_image(url=inter.author.avatar.url if inter.author.avatar else None)
|
||||
if inter.custom_id in ["customModal-api", "interpol-api"]:
|
||||
api = (
|
||||
pyspw.SpApi(card_id=api_id, card_token=api_token)
|
||||
.get_user(inter.author.id)
|
||||
.nickname
|
||||
)
|
||||
embed.set_footer(text=f"Игрок подтвержден! Никнейм: {api}")
|
||||
if inter.custom_id in ["interpol-api", "interpol"]:
|
||||
embed.set_footer(text=f"{inter.channel.id}")
|
||||
await self.bot.get_channel(
|
||||
data["guilds"][f"{inter.guild.id}"]["modals"][f"{inter.channel.id}"]["channel"]).send(
|
||||
f"{inter.author.mention}",
|
||||
embed=embed,
|
||||
components=[
|
||||
disnake.ui.Button(
|
||||
label="Принять",
|
||||
style=disnake.ButtonStyle.success,
|
||||
custom_id="acceptInterpol",
|
||||
),
|
||||
disnake.ui.Button(
|
||||
label="Отклонить",
|
||||
style=disnake.ButtonStyle.danger,
|
||||
custom_id="declineInterpol",
|
||||
),
|
||||
disnake.ui.Button(
|
||||
label="Создать тикет",
|
||||
style=disnake.ButtonStyle.blurple,
|
||||
custom_id="createInterpolTicket",
|
||||
),
|
||||
],
|
||||
)
|
||||
else:
|
||||
await self.bot.get_channel(
|
||||
data["guilds"][f"{inter.guild.id}"]["modals"][f"{inter.channel.id}"][
|
||||
f"{inter.message.id}"
|
||||
]["channel"]
|
||||
).send(f"{inter.author.mention}", embed=embed)
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
elif inter.custom_id in ["addCourtModal", "addSityModal"]:
|
||||
modal_inter = inter
|
||||
if inter.custom_id == "addCourtModal":
|
||||
print("no")
|
||||
sityName = "Unbound"
|
||||
for key, values in modal_inter.text_values.items():
|
||||
sityName = values
|
||||
i = -1
|
||||
embed = inter.message.embeds[0]
|
||||
fieldFromEmbed = None
|
||||
for field in embed.fields:
|
||||
i = i + 1
|
||||
if field.name == sityName:
|
||||
fieldFromEmbed = field
|
||||
break
|
||||
if not fieldFromEmbed:
|
||||
await modal_inter.response.send_message("Вы указали неправильный город", ephemeral=True)
|
||||
return False
|
||||
symbol = (list(fieldFromEmbed.value)[-2])
|
||||
embed = inter.message.embeds[0]
|
||||
embed.set_field_at(i, name=sityName, value=fieldFromEmbed.value.replace(f"({symbol})", f"({str(int(symbol)+1)})"), inline=False)
|
||||
await modal_inter.response.send_message("Готово!", ephemeral=True)
|
||||
await inter.message.edit(embed=embed)
|
||||
else:
|
||||
await modal_inter.response.send_message("Готово!", ephemeral=True)
|
||||
sityName = "Unbound"
|
||||
sityCoordinates = "Unbound"
|
||||
for key, values in modal_inter.text_values.items():
|
||||
if key == "sityName":
|
||||
sityName = values
|
||||
elif key == "sityCoordinates":
|
||||
sityCoordinates = values
|
||||
embed = inter.message.embeds[0]
|
||||
embed.add_field(name=sityName, value=f"> **Расположение**: {sityCoordinates} \n > **Количество проведенных судов**: (0)", inline=False)
|
||||
await inter.message.edit(embed=embed)
|
||||
elif inter.custom_id == "addFarmModal":
|
||||
|
||||
|
||||
farmName = "Unbound"
|
||||
farmCoordinates = "Unbound"
|
||||
farmType = "Unbound"
|
||||
sityName = "Unbound"
|
||||
for key, values in inter.text_values.items():
|
||||
if key == "farmName":
|
||||
farmName = values
|
||||
elif key == "farmCoordinates":
|
||||
farmCoordinates = values
|
||||
elif key == "farmType":
|
||||
farmType = values
|
||||
elif key == "sityName":
|
||||
sityName = values
|
||||
if ";" in farmName or ";" in farmCoordinates or ";" in farmType or ";" in sityName:
|
||||
await inter.response.send_message("SQL инъекции не работает, сын шалавы", ephemeral=True)
|
||||
await (await inter.guild.fetch_member(945317832290336798)).send(f"Сын шлюхи {inter.author.mention} попытался использовать sql-инъекцию в {inter.channel.mention}")
|
||||
return
|
||||
if inter.message.embeds[0].title == "**Фермы**":
|
||||
execute("INSERT INTO farms VALUES ({}, {}, {}, {}, {})".format(f'"{farmName}"', f'"{farmCoordinates}"', f'"{farmType}"', f'"{sityName}"', inter.author.id))
|
||||
else:
|
||||
execute("INSERT INTO private_farms VALUES ({}, {}, {}, {}, {})".format(f'"{farmName}"', f'"{farmCoordinates}"', f'"{farmType}"', f'"{sityName}"', inter.author.id))
|
||||
|
||||
embed = inter.message.embeds[0]
|
||||
embed.add_field(name=sityName, value=f"> **Название фермы**: {farmName} \n > **Расположение**: {farmCoordinates} \n > **Тип фермы**: {farmType}", inline=False)
|
||||
await inter.message.edit(embed=embed)
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(modals(bot))
|
||||
328
cogs/moderation.py
Normal file
328
cogs/moderation.py
Normal file
@@ -0,0 +1,328 @@
|
||||
import asyncio
|
||||
import datetime as dt
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
import disnake
|
||||
from disnake import Localized, OptionChoice
|
||||
from disnake.ext import commands, tasks
|
||||
from handlers import bot, now, takeSettings
|
||||
from log import rootLogger
|
||||
|
||||
|
||||
class common:
|
||||
def __init__(self,
|
||||
bot,
|
||||
user_id: Optional[int] = None,
|
||||
guild_id: Optional[int] = None):
|
||||
"""Common functions
|
||||
|
||||
Args:
|
||||
user_id (Optional[int], optional): _description_. Defaults to None.
|
||||
guild_id (Optional[int], optional): _description_. Defaults to None.
|
||||
"""
|
||||
self.bot = bot
|
||||
self.path = Path("mute.json")
|
||||
self.guild_id = guild_id if guild_id is not None else None
|
||||
self.user_id = user_id if user_id is not None else None
|
||||
self.role = None
|
||||
|
||||
async def embed_message(self, end_time: str, time: int, reason: str, muted: int, file: Optional[str] = None):
|
||||
guild = bot.get_guild(self.guild_id)
|
||||
member = await guild.fetch_member(muted)
|
||||
channel = self.bot.get_channel(int(takeSettings(self.guild_id, "mute_channel")))
|
||||
emb = disnake.Embed(title=f"**System - Mute**", color=disnake.Color.purple(), timestamp=datetime.now())
|
||||
emb.add_field(name="**Выдал:**", value=f"<@{self.user_id}>", inline=True)
|
||||
emb.add_field(name="**Нарушитель:**", value=f"<@{muted}>", inline=True)
|
||||
emb.add_field(name="**Причина:**", value=reason, inline=False)
|
||||
if file != None:
|
||||
emb.set_image(file)
|
||||
if end_time in ["м", "m"]:
|
||||
emb.add_field(name="**Длительность:**", value="{} минут()".format(time))
|
||||
timesdelta = timedelta(minutes=float(time))
|
||||
elif end_time in ["ч", "h"]:
|
||||
emb.add_field(name="**Длительность:**", value="{} час(ов)".format(time))
|
||||
timesdelta = timedelta(hours=float(time))
|
||||
elif end_time in ["д", "d"]:
|
||||
emb.add_field(name="**Длительность:**", value="{} день(ей)".format(time))
|
||||
timesdelta = timedelta(days=float(time))
|
||||
|
||||
local_time = ((datetime.now() + timesdelta)
|
||||
.astimezone()
|
||||
.strftime("%d/%m/%Y %H:%M")
|
||||
)
|
||||
path = Path("mute.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
data["mutes"][f"{local_time}"] = {f"{member.id}": {"user": f"{member.id}", "guild": f"{self.guild_id}"}}
|
||||
path.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
|
||||
await channel.send(embed=emb)
|
||||
emb.remove_field(index=0)
|
||||
emb.add_field(name="**Сервер:**", value=guild.name, inline=True)
|
||||
await member.send(embed=emb)
|
||||
|
||||
def checkIsInMuted(self):
|
||||
"""Проверка на наличие в базе мутов игрока
|
||||
|
||||
Args:
|
||||
user (int): айдишечка пользователя
|
||||
|
||||
Returns:
|
||||
bool: возвращается результат
|
||||
"""
|
||||
userData = json.loads(self.path.read_text(encoding="utf-8"))
|
||||
for key in userData["mutes"]:
|
||||
for data in userData["mutes"][key]:
|
||||
|
||||
return int(self.user_id) == int(userData["mutes"][key][data]['user'])
|
||||
|
||||
def new_DB(self):
|
||||
"""Create db
|
||||
|
||||
Args:
|
||||
guild_id (int): guild`s id for db
|
||||
member (disnake.Member): member for data into db
|
||||
"""
|
||||
if not os.path.isfile(f"users/users_{self.guild_id}.json"):
|
||||
with open(f"users/users_{self.guild_id}.json", "a") as file:
|
||||
writeinfiledata = {
|
||||
f"{self.guild_id}": {
|
||||
f"{self.user_id}": {
|
||||
"userID": f"{self.user_id}",
|
||||
"warnCounter": "0",
|
||||
"muteCounter": "1",
|
||||
"userMention": f"<@{self.user_id}>",
|
||||
"guild": f"{self.guild_id}",
|
||||
}
|
||||
}
|
||||
}
|
||||
json.dump(writeinfiledata, file)
|
||||
file.close()
|
||||
|
||||
path = Path(f"users/users_{self.guild_id}.json")
|
||||
userData = json.loads(path.read_text(encoding="utf-8"))
|
||||
if f"{self.user_id}" not in userData[f"{self.guild_id}"]:
|
||||
newUserData = {
|
||||
"userID": f"{self.user_id}",
|
||||
"warnCounter": "0",
|
||||
"muteCounter": "1",
|
||||
"userMention": f"<@{self.user_id}>",
|
||||
"guild": f"{self.guild_id}",
|
||||
}
|
||||
userData[f"{self.guild_id}"]["muteCounter"] = newUserData
|
||||
else:
|
||||
userData[f"{self.guild_id}"]["muteCounter"] = +1
|
||||
path.write_text(json.dumps(userData, indent=7), encoding="utf-8", newline="\n")
|
||||
|
||||
def deleteMute(self):
|
||||
"""Удаление мута из базы данных
|
||||
|
||||
Args:
|
||||
user (int): Айди пользователя
|
||||
"""
|
||||
userData = json.loads(self.path.read_text(encoding="utf-8"))
|
||||
for key in userData["mutes"]:
|
||||
for data in userData["mutes"][key]:
|
||||
if data == self.user_id:
|
||||
del userData["mutes"][key]
|
||||
self.path.write_text(
|
||||
json.dumps(userData, indent=4, ensure_ascii=False),
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
)
|
||||
return
|
||||
|
||||
def mute(self): return int(takeSettings(self.guild_id, "mute_role"))
|
||||
def moderator(self): return int(takeSettings(self.guild_id, "moderation_role"))
|
||||
|
||||
async def issuedRole(self, types):
|
||||
"""Выдача роли в отдельной функции для выдачи роли
|
||||
|
||||
Args:
|
||||
guild_id (int): _description_
|
||||
user_id (int): _description_
|
||||
|
||||
"""
|
||||
guild: disnake.Guild = self.bot.get_guild(int(self.guild_id))
|
||||
member: disnake.Member = await guild.fetch_member(int(self.user_id))
|
||||
|
||||
return bool(await member.add_roles(guild.get_role(types(self))))
|
||||
|
||||
|
||||
async def removeRole(self, type: str):
|
||||
"""Забирать роли для оптимизации кода
|
||||
|
||||
Args:
|
||||
guild_id (int): Передавать guild id для забирания роли
|
||||
user_id (int): Передавать user id для забирания роли
|
||||
type (str): Передавать вид роли для выполнения функции
|
||||
|
||||
"""
|
||||
guild: disnake.Guild = self.bot.get_guild(int(self.guild_id))
|
||||
if type == "mute":
|
||||
role: disnake.Role = guild.get_role((takeSettings(self.guild.id, "mute_role")))
|
||||
member: disnake.Member = await guild.fetch_member(int(self.user_id))
|
||||
await member.remove_roles(role)
|
||||
|
||||
|
||||
class moderationCommands(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.path = Path("mute.json")
|
||||
rootLogger.info("Модуль {} Включен".format(self.__class__.__name__))
|
||||
|
||||
|
||||
async def preMuteFunc(self, user: int, guild: int):
|
||||
"""Передача данных для полной работы с всеми требуемыми функциями
|
||||
|
||||
Args:
|
||||
user (int): _description_
|
||||
guild (int): _description_
|
||||
|
||||
Returns:
|
||||
_type_: _description_
|
||||
"""
|
||||
|
||||
common(self.bot, user_id=user, guild_id=guild).new_DB()
|
||||
if common(self.bot, user_id=user).checkIsInMuted():
|
||||
common(self.bot, user_id=user).deleteMute()
|
||||
await common(self.bot, user_id=user, guild_id=guild).issuedRole(common.mute)
|
||||
|
||||
|
||||
@commands.slash_command(name=Localized("clear", key="CLEAR_NAME"), description=Localized("Clear message in current channel", key="CLEAR_DESC"))
|
||||
@commands.has_permissions(manage_messages=True)
|
||||
async def clear(inter, amount: int):
|
||||
await inter.response.send_message("Выполняется!", ephemeral=True)
|
||||
channel = bot.get_channel(inter.channel.id)
|
||||
await channel.purge(limit=amount + 1)
|
||||
|
||||
|
||||
@commands.user_command(name=Localized("Mute", key="APP_MUTE_NAME") )
|
||||
@commands.has_permissions(manage_messages=True)
|
||||
async def muteUserByApplication(self, inter: disnake.ApplicationCommandInteraction, member: disnake.Member):
|
||||
await inter.response.send_modal(
|
||||
title='Mute',
|
||||
custom_id='muteByApp',
|
||||
components=[
|
||||
disnake.ui.TextInput(
|
||||
label="Время мута",
|
||||
placeholder='2h',
|
||||
custom_id='muteTime',
|
||||
style=disnake.TextInputStyle.short,
|
||||
max_length=3,
|
||||
),
|
||||
disnake.ui.TextInput(
|
||||
label="Причина",
|
||||
placeholder='Флуд',
|
||||
custom_id='muteReason',
|
||||
style=disnake.TextInputStyle.short,
|
||||
),
|
||||
],
|
||||
)
|
||||
try:
|
||||
def check(m):
|
||||
return m.author == inter.author and m.channel == inter.channel
|
||||
modal_inter: disnake.ModalInteraction = await self.bot.wait_for(
|
||||
event="modal_submit",
|
||||
check=check,
|
||||
timeout=30.0,
|
||||
)
|
||||
await modal_inter.response.send_message('Готово!', ephemeral=True)
|
||||
amount = modal_inter.text_values['muteTime']
|
||||
reason = modal_inter.text_values['muteReason']
|
||||
await self.preMuteFunc(member.id, inter.guild.id)
|
||||
|
||||
await common(bot, inter.author.id, inter.guild.id).embed_message(end_time = amount[-1:], time = amount[:-1], reason = reason, muted=member.id)
|
||||
except asyncio.TimeoutError:
|
||||
return
|
||||
|
||||
|
||||
|
||||
@commands.slash_command(name="embed", description=Localized("Create Embedded Message", key="CREATE_EMBED_DESC"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def embed_message(self, inter, title: str, description: str, file: Optional[disnake.Attachment] = None):
|
||||
emb = disnake.Embed(title=title, description=f"{description}", color=disnake.Color.purple())
|
||||
# emb.add_field(name=field_name, value=field_value, inline=False)
|
||||
if file != None: emb.set_image(file.url)
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
await self.bot.get_channel(inter.channel.id).send(embed=emb)
|
||||
|
||||
@commands.slash_command(name=Localized("mute", key="MUTE_NAME"), description=Localized("Mute user", key="MUTE_DESC"))
|
||||
@commands.has_permissions(manage_messages=True)
|
||||
async def add(self, inter, member: disnake.Member, amount: str, reason: str, file: disnake.Attachment):
|
||||
await self.preMuteFunc(member.id, inter.guild.id)
|
||||
await common(bot, inter.author.id, inter.guild.id).embed_message(end_time = amount[-1:], time = amount[:-1], reason = reason, muted=member.id, file= file.url)
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
|
||||
@commands.slash_command(
|
||||
name=Localized("enableslowmode", key="ENABLEWLOWMODE_NAME"), description=Localized("Enable or disable slowmode in this channel", key="ENABLEWLOWMODE_DESC")
|
||||
)
|
||||
@commands.has_permissions(kick_members=True)
|
||||
async def enableslowmode(inter, amount: int, time: str = commands.Param(
|
||||
choices=[
|
||||
OptionChoice("minute", "m"),
|
||||
OptionChoice("second", "s"),
|
||||
]
|
||||
)
|
||||
):
|
||||
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
if time == "s":
|
||||
await inter.channel.edit(slowmode_delay=amount)
|
||||
elif time == "m":
|
||||
await inter.channel.edit(slowmode_delay=(amount * 60))
|
||||
|
||||
else:
|
||||
await inter.response.send_message(
|
||||
"Неправильно указано время, или иное", ephemeral=True
|
||||
)
|
||||
|
||||
|
||||
@commands.slash_command(name=Localized("unmute", key="UNMUTE_NAME"), description=Localized("Unmute user", key="UNMUTE_DESC"))
|
||||
@commands.has_permissions(kick_members=True)
|
||||
async def unmute(self, inter, user: disnake.Member):
|
||||
role = self.bot.get_guild(inter.guild.id).get_role(
|
||||
takeSettings(inter.guild.id, "mute_role")
|
||||
)
|
||||
if role in user.roles:
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
await common(bot, user.id, inter.guild.id).removeRole("mute_role")
|
||||
else:
|
||||
await inter.response.send("Неправильный аргумент, или пользователь не замучен", ephemeral=True)
|
||||
|
||||
@commands.slash_command(name=Localized("changenick", key='CHANGENICK_NAME'), description=Localized("Changes nickname ", key="CHANGENICK_DESC"))
|
||||
async def changenick(self, inter, member: disnake.Member, changednick):
|
||||
path= Path(f"users/users_{inter.guild.id}.json")
|
||||
common(bot, member.id, inter.guild.id).new_DB()
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
readedData = json.loads(path.read_text(encoding="utf-8"))
|
||||
warnCounter = int(
|
||||
readedData[f"{inter.guild.id}"][f"{member.id}"]["warnCounter"]
|
||||
)
|
||||
e = disnake.Embed(
|
||||
description="Aoyo.Moderation SYSTEM", color=disnake.Color.purple()
|
||||
)
|
||||
e.add_field(name="**Сменил:**", value=inter.author.mention)
|
||||
e.add_field(name="**Старый ник:**", value=member.name)
|
||||
e.add_field(name="**Новый ник:**", value=changednick)
|
||||
e.add_field(name="**Количество смененных ников:**", value=f"{warnCounter+1}")
|
||||
|
||||
readedData[f"{inter.guild_id}"][f"{member.id}"]["warnCounter"] = +1
|
||||
path.write_text(
|
||||
json.dumps(readedData, indent=6), encoding="utf-8", newline="\n"
|
||||
)
|
||||
|
||||
await member.edit(nick=changednick)
|
||||
await self.bot.get_channel(
|
||||
int(takeSettings(inter.guild_id, "mute_channel"))
|
||||
).send(embed=e)
|
||||
e.remove_field(index=0)
|
||||
e.add_field(name="**Сервер:**", value=inter.guild.name, inline=True)
|
||||
await member.send(embed=e)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(moderationCommands(bot))
|
||||
172
cogs/multiguild.py
Normal file
172
cogs/multiguild.py
Normal file
@@ -0,0 +1,172 @@
|
||||
from disnake import *
|
||||
from disnake.ext import commands
|
||||
from handlers import *
|
||||
from log import rootLogger
|
||||
import json
|
||||
from dislash import Option
|
||||
from pathlib import Path
|
||||
import disnake
|
||||
from validators import url
|
||||
|
||||
|
||||
|
||||
class multiGuildSettings(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
rootLogger.info("Модуль {} подключен!".format(self.__class__.__name__))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@commands.slash_command(name=Localized('settings', key="SETTINGS"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def settings(self, inter):
|
||||
pass
|
||||
|
||||
|
||||
@settings.sub_command(
|
||||
name=Localized("setup", key="SETUP_NAME"),
|
||||
description=Localized("Setting a bot on the server.", key="SETUP_DESC"),)
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def allsettings(inter,
|
||||
mute_role: disnake.Role,
|
||||
mute_channel: disnake.TextChannel,
|
||||
moderation_role: disnake.Role,
|
||||
on_join_role: disnake.Role,
|
||||
report_channel: disnake.TextChannel,
|
||||
transcript_channel: disnake.TextChannel,
|
||||
):
|
||||
writedData={
|
||||
"mute_role": f"{mute_role.id}",
|
||||
"mute_channel": f"{mute_channel.id}",
|
||||
"on_join_role": f"{on_join_role.id}",
|
||||
"moderation_role": f"{moderation_role.id}",
|
||||
"report_channel": f"{report_channel.id}",
|
||||
}
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
if f"{inter.guild.id}" not in data["guilds"]:
|
||||
data["guilds"][f"{inter.guild.id}"] = {}
|
||||
data["guilds"][f"{inter.guild.id}"]["mute_role"] = mute_role.id
|
||||
data["guilds"][f"{inter.guild.id}"]["mute_channel"]= mute_channel.id
|
||||
data["guilds"][f"{inter.guild.id}"]["on_join_role"] = on_join_role.id
|
||||
data["guilds"][f"{inter.guild.id}"]["report_channel"] = report_channel.id
|
||||
data["guilds"][f"{inter.guild.id}"]["moderation_role"] = moderation_role.id
|
||||
data["guilds"][f"{inter.guild.id}"]["transcript_channel"] = transcript_channel.id
|
||||
path.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
else:
|
||||
data["guilds"][f"{inter.guild.id}"]["mute_role"] = mute_role.id
|
||||
data["guilds"][f"{inter.guild.id}"]["mute_channel"]= mute_channel.id
|
||||
data["guilds"][f"{inter.guild.id}"]["on_join_role"] = on_join_role.id
|
||||
data["guilds"][f"{inter.guild.id}"]["report_channel"] = report_channel.id
|
||||
data["guilds"][f"{inter.guild.id}"]["moderation_role"] = moderation_role.id
|
||||
data["guilds"][f"{inter.guild.id}"]["transcript_channel"] = transcript_channel.id
|
||||
path.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message("Готово! Ваш сервер сохранен в настройках бота!", ephemeral=True)
|
||||
|
||||
|
||||
@settings.sub_command(name=Localized('guestroom', key="GUESTROOM_NAME"), description=Localized('Settings of the Entrance of the player', key="GUESTROOM_DESC"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def guestroom(inter,
|
||||
guest_room: disnake.TextChannel=Option("guest_room",description="Укажите канал, в который будет отправляться сообщение о входе пользователя", required=True),
|
||||
image: str=Option("image", description="Укажите ссылку на фото или гиф файл, который будет отправляться вместе с сообщением о прибытии!", required=True),
|
||||
text: str=Option("text", description="Укажите текст, который должен присылаться вместе с сообщением о прибытии пользователя", required=True),
|
||||
):
|
||||
if not url(image):
|
||||
url = None
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
data["guilds"][f"{inter.guild.id}"]["guest_room"] = guest_room.id
|
||||
data["guilds"][f"{inter.guild.id}"]["image_url"] = f"{image}"
|
||||
data["guilds"][f"{inter.guild.id}"]["guest_text"] = f"{text}"
|
||||
if "server" not in data:
|
||||
data["guilds"][f"{inter.guild.id}"]["server"] = "None"
|
||||
path.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
|
||||
|
||||
@settings.sub_command(
|
||||
name=Localized('autobrench', key='AUTOBRENCH_NAME'),
|
||||
description=Localized("Automatic creation of branches in the channels", key="AUTOBRENCH_DESC")
|
||||
)
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def autobrench(inter: disnake.ApplicationCommandInteraction, channel: disnake.TextChannel):
|
||||
path = Path("guilds/guilds.json")
|
||||
jsonData = json.loads(path.read_text(encoding="utf-8"))
|
||||
if f"autobrench" not in jsonData["guilds"][f"{inter.guild.id}"]:
|
||||
jsonData["guilds"][f"{inter.guild.id}"]["autobrench"] = {}
|
||||
path.write_text(json.dumps(jsonData, indent=4), encoding="utf-8", newline="\n")
|
||||
jsonData = json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
jsonData["guilds"][f"{inter.guild.id}"]["autobrench"][f"{channel.id}"] = channel.id
|
||||
path.write_text(json.dumps(jsonData, indent=4), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message("Автоматическое создание веток настроено!", ephemeral=True)
|
||||
|
||||
@settings.sub_command(
|
||||
name=Localized("autoreaction", key="AUTOREACTION_NAME"),
|
||||
description=Localized("Autoreaction setting up", key="AUTOREACTION_DESC")
|
||||
)
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def autoreaction(inter: disnake.ApplicationCommandInteraction, channel: disnake.TextChannel, reaction1: disnake.Emoji, reaction2: disnake.Emoji=Option("reaction2")):
|
||||
path = Path("guilds/guilds.json")
|
||||
jsonData = json.loads(path.read_text(encoding="utf-8"))
|
||||
if f"autoreaction" not in jsonData["guilds"][f"{inter.guild.id}"]:
|
||||
jsonData["guilds"][f"{inter.guild.id}"]["autoreaction"] = {}
|
||||
path.write_text(json.dumps(jsonData, indent=4), encoding="utf-8", newline="\n")
|
||||
jsonData = json.loads(path.read_text(encoding="utf-8"))
|
||||
try:
|
||||
try:
|
||||
second_react = reaction2.id
|
||||
except:
|
||||
second_react = "None"
|
||||
jsonData["guilds"][f"{inter.guild.id}"]["autoreaction"][f"{channel.id}"] = {
|
||||
"reaction1": reaction1.id,
|
||||
"reaction2": second_react
|
||||
}
|
||||
path.write_text(json.dumps(jsonData, indent=4), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message("Автореакция установлена", ephemeral=True)
|
||||
except Exception as e:
|
||||
await inter.response.send_message(f"Эмодзи не найдено. Попробуйте использовать эмодзи с этого сервера", ephemeral=True)
|
||||
|
||||
|
||||
|
||||
@settings.sub_command(
|
||||
name="auth",
|
||||
description=Localized("User authentication, if it is in the server database", key="AUTH_DESC")
|
||||
)
|
||||
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def authUser(inter, gived_role: disnake.Role, token_id: str, card_id: str):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
data["guilds"][f"{inter.guild.id}"]["server"] = {
|
||||
"role": f"{gived_role.id}",
|
||||
"token": token_id,
|
||||
"card": card_id
|
||||
}
|
||||
path.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message('Готово!', ephemeral=True)
|
||||
|
||||
@settings.sub_command(
|
||||
name=Localized("autovoice", key="AUTOVOICE_NAME"),
|
||||
description="Automatic creation of voice channels (if the user connects to [+] create)"
|
||||
)
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def autovoice(inter, answer: str = commands.Param(choices=[
|
||||
disnake.OptionChoice(Localized("Turn ON", key="AUTOVOICE_ON"), "on"),
|
||||
disnake.OptionChoice(Localized("Turn OFF", key="AUTOVOICE_OFF"), "off"),
|
||||
]
|
||||
)):
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if answer == "on": answer = True
|
||||
else: answer = False
|
||||
data["guilds"][f"{inter.guild.id}"]["autovoice"] = f"{answer}"
|
||||
path.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message('Готово!', ephemeral=True)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(multiGuildSettings(bot))
|
||||
36
cogs/saveChannels.py
Normal file
36
cogs/saveChannels.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from disnake.ext import commands
|
||||
import disnake
|
||||
import chat_exporter
|
||||
from typing import Optional
|
||||
import io
|
||||
class saveChannel(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.slash_command(name=disnake.Localized('save-channel', key='SAVECHANNEL_NAME'),
|
||||
description=disnake.Localized('Saves channel data, and later sends them to a separate channel', key="SAVECHANNEL_DESC"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def save_channel(self, inter, chat: Optional[disnake.TextChannel]):
|
||||
if type(chat) == disnake.TextChannel:
|
||||
channel = chat
|
||||
else:
|
||||
channel = inter.channel
|
||||
|
||||
transcript = await chat_exporter.export(
|
||||
channel,
|
||||
bot=self.bot,
|
||||
)
|
||||
if transcript is None:
|
||||
return
|
||||
|
||||
transcript_file = disnake.File(
|
||||
io.BytesIO(transcript.encode()),
|
||||
filename=f"transcript-{inter.channel.name}.html",
|
||||
)
|
||||
|
||||
await inter.send(file=transcript_file)
|
||||
await inter.response.send_message("Готово!", ephemeral=True)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(saveChannel(bot))
|
||||
|
||||
87
cogs/ticket.py
Normal file
87
cogs/ticket.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from disnake.ext import commands
|
||||
from disnake import *
|
||||
from handlers import *
|
||||
from log import *
|
||||
import json
|
||||
from dislash import Option
|
||||
import disnake
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class ticket(commands.Cog):
|
||||
def __init__(self,bot):
|
||||
self.bot = bot
|
||||
rootLogger.info(f"Модуль {self.__class__.__name__} подключен!")
|
||||
|
||||
|
||||
|
||||
@commands.slash_command(
|
||||
name=Localized("ticket", key="TICKET_NAME"),
|
||||
description=Localized("Creating a tick for your server! (With buttons)", key="TICKET_DESC"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def createTicket(inter,
|
||||
ticket_name: str,
|
||||
ticket_description: str,
|
||||
channel: disnake.TextChannel,
|
||||
first_button_name: str,
|
||||
first_button_role: disnake.Role,
|
||||
channel_for_transcript: disnake.TextChannel,
|
||||
second_button_name: str=Option("second_button_name", description="Укажите название второй кнопки"),
|
||||
second_button_role: disnake.Role=Option("second_button_name", description="Укажите роль для второй кнопки"),
|
||||
third_button_name: str=Option("third_button_name", description="Укажите название третьей кнопки"),
|
||||
third_button_role: disnake.Role = Option("third_button_name", type=disnake.Role, description="Укажите роль для третьей кнопки") ):
|
||||
"""
|
||||
Give several cookies to a user
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticket_description: Description in create_ticket message
|
||||
channel: Specify the channel through which the message will be sent to create tickets
|
||||
first_button_name: First name of the button
|
||||
first_button_role: The first role that will be pinged when the ticket is opened,
|
||||
channel_for_transacript: The channel, where the message with transcript will be sent
|
||||
"""
|
||||
embed = disnake.Embed(title="**Ticket**", description=ticket_description, colour=disnake.Color.blue())
|
||||
embed.set_image('https://media.discordapp.net/attachments/876280751488909332/979778066417070151/Frame_280.png?width=1440&height=4')
|
||||
embed.set_footer(text='Aoyo ticket system by YaFlay',)
|
||||
buttons = disnake.ui.View()
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id="firstTicket", label=first_button_name))
|
||||
msg = await channel.send(embed=embed, view=buttons)
|
||||
try: category = channel_for_transcript.category.id
|
||||
except Exception: category = channel.category.id
|
||||
|
||||
try:
|
||||
sec_role = second_button_role.id
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id="secondTicket", label=second_button_name))
|
||||
except Exception: sec_role = "None"
|
||||
|
||||
try:
|
||||
third_role = third_button_role.id
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.green, custom_id="thirdTicket", label=third_button_name))
|
||||
except Exception: third_role = "None"
|
||||
|
||||
writedData={
|
||||
"channel": f"{channel_for_transcript.id}",
|
||||
"category": f"{category}",
|
||||
"message_id": f"{msg.id}",
|
||||
"guild": f"{inter.guild_id}",
|
||||
"first_role": f"{first_button_role.id}",
|
||||
"second_role": f"{sec_role}",
|
||||
"third_role": f"{third_role}"
|
||||
|
||||
}
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if f"{inter.guild.id}" not in data["guilds"]:
|
||||
await inter.response.send_message("Вы не настроили сервер! сделайте это прямо сейчас при помощи команды /settings setup!")
|
||||
return
|
||||
elif "ticket" not in data["guilds"][f"{inter.guild_id}"]:
|
||||
data["guilds"][f"{inter.guild_id}"]["ticket"] = {}
|
||||
data["guilds"][f"{inter.guild_id}"]["ticket"][f"{channel.id}"] = {}
|
||||
|
||||
data["guilds"][f"{inter.guild_id}"]["ticket"][f"{channel.id}"][f"{msg.id}"] = (writedData)
|
||||
path.write_text(json.dumps(data, indent=3), encoding="utf-8", newline="\n")
|
||||
await inter.response.send_message('Готово!', ephemeral=True)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(ticket(bot))
|
||||
157
cogs/usersCommand.py
Normal file
157
cogs/usersCommand.py
Normal file
@@ -0,0 +1,157 @@
|
||||
from disnake.ext import commands
|
||||
import disnake
|
||||
from handlers import *
|
||||
from log import *
|
||||
import datetime
|
||||
import json
|
||||
import asyncio
|
||||
|
||||
|
||||
class usersCommand(commands.Cog):
|
||||
def __init__(self,bot):
|
||||
self.bot = bot
|
||||
rootLogger.info("Модуль {} подключен!".format(self.__class__.__name__))
|
||||
|
||||
@commands.user_command(name=disnake.Localized('Get avatar', key="GET_AVATAR"))
|
||||
async def getAvatar(self, inter: disnake.ApplicationCommandInteraction, user: disnake.User):
|
||||
embed = disnake.Embed(description=f"Аватарка пользователя {user.mention}")
|
||||
embed.set_image(user.avatar.url)
|
||||
await inter.response.send_message(inter.author.mention, embed=embed, ephemeral=True)
|
||||
|
||||
@commands.message_command(name=disnake.Localized("Report", key="REPORT"))
|
||||
async def moderationReport(self, inter: disnake.ApplicationCommandInteraction, message: disnake.Message):
|
||||
await inter.response.send_modal(
|
||||
title="Репорты",
|
||||
custom_id="reportModal",
|
||||
components=[
|
||||
disnake.ui.TextInput(
|
||||
label="Комментарий к репорту",
|
||||
placeholder='Меня оскорбили',
|
||||
custom_id='comment',
|
||||
style=disnake.TextInputStyle.short
|
||||
|
||||
)
|
||||
],)
|
||||
try:
|
||||
def check(m):
|
||||
return m.author == inter.author and m.channel == inter.channel
|
||||
modal_inter: disnake.ModalInteraction = await self.bot.wait_for(
|
||||
event="modal_submit",
|
||||
check=check,
|
||||
timeout=30.0,
|
||||
)
|
||||
valueFromFor = modal_inter.text_values['comment']
|
||||
embed = disnake.Embed(
|
||||
title=f"Подали репорт!",
|
||||
description=f"Ссылка на сообщение: [Тык](https://discord.com/channels/{message.guild.id}/{message.channel.id}/{message.id})\nАвтор сообщения: {message.author.name}\nАвтор репорта: {inter.author.name}\nСообщение, на которое подали жалобу: {message.content}\nПричина жалобы: {valueFromFor}",
|
||||
color=0x00ff00,
|
||||
timestamp=datetime.datetime.now()
|
||||
)
|
||||
embed.set_image('https://media.discordapp.net/attachments/876280751488909332/979778066417070151/Frame_280.png?width=1440&height=4')
|
||||
embed.set_thumbnail(url=message.author.avatar)
|
||||
embed.set_footer(text=f"{inter.author.id}")
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
button = disnake.ui.View()
|
||||
button.add_item(disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id="reportAccept", label="Принять"))
|
||||
button.add_item(disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id="reportCreateTicket", label="Создать тикет"))
|
||||
button.add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id="deleteReport", label="Удалить репорт"))
|
||||
await self.bot.get_channel(int(data["guilds"][f"{message.guild.id}"]["report_channel"])).send(embed=embed, view=button)
|
||||
await modal_inter.response.send_message("Вы удачно отправили репорт! Я отправил сообщение модерации.", ephemeral=True)
|
||||
return
|
||||
except asyncio.TimeoutError:
|
||||
return
|
||||
|
||||
@commands.message_command(name=disnake.Localized("Change Field", key="CHANGEFIELD"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def change_field(self, inter: disnake.ApplicationCommandInteraction, message: disnake.Message):
|
||||
await inter.response.send_modal(
|
||||
title="Смена строки",
|
||||
custom_id="changeField",
|
||||
components=[
|
||||
disnake.ui.TextInput(
|
||||
label="Номер строки(Если их одна, то напишите 0)",
|
||||
placeholder='1',
|
||||
custom_id='numberField',
|
||||
style=disnake.TextInputStyle.short,
|
||||
max_length=1,
|
||||
|
||||
),
|
||||
disnake.ui.TextInput(
|
||||
label="Новое значение",
|
||||
placeholder='Меня зовут Кира Йошикаге',
|
||||
custom_id='newField',
|
||||
style=disnake.TextInputStyle.short,
|
||||
),
|
||||
],
|
||||
)
|
||||
try:
|
||||
def check(m):
|
||||
return m.author == inter.author and m.channel == inter.channel
|
||||
modal_inter: disnake.ModalInteraction = await self.bot.wait_for(
|
||||
event="modal_submit",
|
||||
check=check,
|
||||
timeout=30.0,
|
||||
)
|
||||
await modal_inter.response.send_message('Готово!', ephemeral=True)
|
||||
numberOfField = int(modal_inter.text_values['numberField']) if int(modal_inter.text_values['numberField']) == 0 else int(modal_inter.text_values['numberField']) - 1
|
||||
print(numberOfField)
|
||||
newField = modal_inter.text_values['newField']
|
||||
embed = message.embeds[0]
|
||||
name = embed.fields[numberOfField].name
|
||||
embed.remove_field(numberOfField)
|
||||
embed.add_field(name=name, value=newField)
|
||||
|
||||
await message.edit(embed=embed)
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
return
|
||||
|
||||
|
||||
@commands.slash_command(name=disnake.Localized('issue-role', key='ISSUE_ROLE_NAME'), description=disnake.Localized('Roaling by pressing the button', key="ISSUE_ROLE_DESC"))
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def issueRole(self, inter, role1: disnake.Role, role2: disnake.Role, role3: disnake.Role):
|
||||
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding='utf-8'))
|
||||
embed = disnake.Embed(title='Выдача ролей', description=f'{role1.mention}\n{role2.mention}\n{role3.mention}', color=0x00ff00)
|
||||
embed.set_image('https://media.discordapp.net/attachments/876280751488909332/979778066417070151/Frame_280.png?width=1440&height=4')
|
||||
channel = bot.get_channel(inter.channel.id)
|
||||
message_id = await channel.send(embed=embed,
|
||||
components=[
|
||||
disnake.ui.Button(label=role1.name, style=disnake.ButtonStyle.secondary, custom_id="role1"),
|
||||
disnake.ui.Button(label=role2.name, style=disnake.ButtonStyle.secondary, custom_id="role2"),
|
||||
disnake.ui.Button(label=role3.name, style=disnake.ButtonStyle.secondary, custom_id="role3"),
|
||||
],
|
||||
)
|
||||
data["guilds"][f"{inter.guild.id}"]["issues"] = {
|
||||
f"{message_id.id}":{
|
||||
"role1": role1.id,
|
||||
"role2": role2.id,
|
||||
"role3": role3.id,
|
||||
}}
|
||||
path.write_text(json.dumps(data, indent=7), encoding='utf-8', newline='\n')
|
||||
await inter.response.send_message('Готово!', ephemeral=True)
|
||||
|
||||
@commands.slash_command(
|
||||
name='help',
|
||||
description='Показать список команд')
|
||||
async def help(inter):
|
||||
embed = disnake.Embed(title="**Aoyo help**", color=0x00ff00)
|
||||
embed.add_field(name="**!help**", value="Показать список команд", inline=False)
|
||||
embed.add_field(name="!clear [кол-во]", value="Удаляет сообщения", inline=False)
|
||||
embed.add_field(name="**/mute [пользователь] [время(1m, 1s)] [причина]**", value="Выдать мут", inline=False)
|
||||
embed.add_field(name="**/unmute [пользователь]**", value="Размут пользователя", inline=False)
|
||||
embed.add_field(name="**/changenick [пользователь] [ник]**", value="Изменить ник пользователя", inline=False)
|
||||
embed.add_field(name="**/embed [название] [текст]**", value="Создать embed сообщение", inline=False)
|
||||
embed.add_field(name="**/permmute [пользователь] [причина]**", value="Выдать мут навсегда", inline=False)
|
||||
embed.add_field(name="**/settings setup [роль мута] [канал для мута] [модератор роль] [роль для нынезашедших] [канал для транскрипций тикета]**", value="Настройки сервера", inline=False)
|
||||
embed.add_field(name="/ticket [название тикета] [описание тикета] [канал для тикета] [название первой кнопки] [пингующая роль первой кнопки] [и т.д.]", value="Создать тикет", inline=False)
|
||||
embed.add_field(name="/settings autoreaction [канал] [реакция] [реакция]", value="Создать автореакцию", inline=False)
|
||||
embed.add_field(name="/settings autobrench [канал]", value="Автосоздание веток в этом канале", inline=False)
|
||||
embed.add_field(name="/deletechannel", value="Созвать собрание администрации для удаления канала", inline=False)
|
||||
embed.add_field(name="/enableslowmode [время(1m, 1s)]", value="Включить медленный режим", inline=False)
|
||||
|
||||
await inter.response.send_message(embed=embed, ephemeral=True)
|
||||
def setup(bot):
|
||||
bot.add_cog(usersCommand(bot))
|
||||
207
cogs/voiceBot.py
Normal file
207
cogs/voiceBot.py
Normal file
@@ -0,0 +1,207 @@
|
||||
import disnake
|
||||
import yt_dlp # type: ignore
|
||||
from disnake.ext import commands, tasks
|
||||
import asyncio
|
||||
from typing import Any, Dict, Optional
|
||||
# Suppress noise about console usage from errors
|
||||
yt_dlp.utils.bug_reports_message = lambda: ""
|
||||
from yandex_music import ClientAsync, Client
|
||||
import ytmusicapi
|
||||
from handlers import logger
|
||||
from pathlib import Path
|
||||
import json
|
||||
import os
|
||||
|
||||
type_to_name = {
|
||||
'track': 'трек',
|
||||
'artist': 'исполнитель',
|
||||
'album': 'альбом',
|
||||
'playlist': 'плейлист',
|
||||
'video': 'видео',
|
||||
'user': 'пользователь',
|
||||
'podcast': 'подкаст',
|
||||
'podcast_episode': 'эпизод подкаста',
|
||||
}
|
||||
yt = ytmusicapi.YTMusic()
|
||||
ffmpeg_options = {'options': '-vn', 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5'}
|
||||
|
||||
ytdl = yt_dlp.YoutubeDL({'outtmpl': '%(id)s.%(ext)s'})
|
||||
|
||||
class YTDLSource(disnake.PCMVolumeTransformer):
|
||||
def __init__(self, source: disnake.AudioSource, *, data: Dict[str, Any], volume: float = 0.125):
|
||||
super().__init__(source, volume)
|
||||
|
||||
self.title = data.get("title")
|
||||
self.author = data.get("author")
|
||||
self.source = data.get("source")
|
||||
self.id = data.get("unicalID")
|
||||
self.thumbnails: str = data.get("icon")
|
||||
self.data = data
|
||||
|
||||
@classmethod
|
||||
async def from_url(
|
||||
cls, url, *, loop: Optional[asyncio.AbstractEventLoop] = None, stream: bool = True
|
||||
):
|
||||
player = None
|
||||
if not "http" in url:
|
||||
try:
|
||||
url = f"https://youtube.com/watch?v={yt.search(url)[0]['videoId']}"
|
||||
|
||||
except Exception:
|
||||
env = os.environ
|
||||
client = await ClientAsync(env.get("YANDEX_TOKEN")).init()
|
||||
func = (await client.search(url, nocorrect=False)).best
|
||||
artists = str(func.result.artists_name()).replace("'", '').replace("[", '').replace("]", '')
|
||||
logger.info(f"[yandex] Downloading {func.result.title}")
|
||||
# func.result.download(f"music.mp3")
|
||||
logger.info(f"[yandex] Downloaded...")
|
||||
logger.info(f"[yandex] Openning ....")
|
||||
|
||||
try:
|
||||
player = cls(disnake.FFmpegPCMAudio(await (await func.result.get_download_info_async())[0].get_direct_link_async(), **ffmpeg_options), data={'title': func.result.title, 'author': artists, 'source': "YandexMusic", 'fileName': f"{func.result.title}", 'type': "mp3", 'unicalID': f"https://music.yandex.ru/track/{func.result.id}", "icon": func.result.get_og_image_url()})
|
||||
except Exception:
|
||||
player = cls(disnake.FFmpegPCMAudio(f"music.mp3", **ffmpeg_options), data={'title': func.result.title, 'author': artists, 'source': "YandexMusic", 'fileName': f"{func.result.title}", 'type': "mp3", 'unicalID': f"https://music.yandex.ru/track/{func.result.id}", "icon": func.result.get_og_image_url()})
|
||||
logger.info(f"[yandex] Playing {func.result.title}")
|
||||
if not player:
|
||||
loop = loop or asyncio.get_event_loop()
|
||||
data: Any = await loop.run_in_executor(
|
||||
None, lambda: ytdl.extract_info(url, download=False)
|
||||
)
|
||||
filename = data["formats"][5]["url"] if stream else ytdl.prepare_filename(data)
|
||||
data["author"] = data["channel"]
|
||||
data["source"] = "YouTube"
|
||||
data["type"] = data["formats"][5]["audio_ext"]
|
||||
data["unicalID"] = url
|
||||
data["icon"] = data["thumbnails"][38]["url"]
|
||||
data["fileName"] = filename
|
||||
title = data.get("title")
|
||||
audio_type = data["type"]
|
||||
logger.info(f"[YouTube] Playing {title}")
|
||||
logger.info(f"[Youtube] Audio type {audio_type}")
|
||||
player = cls(disnake.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
|
||||
return player
|
||||
|
||||
|
||||
|
||||
|
||||
class Music(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.queue = {"a": "a"}
|
||||
|
||||
def __channel(self, inter) -> disnake.VoiceProtocol | None:
|
||||
for voiceProtocol in self.bot.voice_clients:
|
||||
if voiceProtocol.guild == inter.guild:
|
||||
return voiceProtocol
|
||||
# @tasks.loop()
|
||||
# async def on_Voice_state_loop(self):
|
||||
# voice_state = self.bot.voice_clients
|
||||
|
||||
|
||||
@commands.slash_command()
|
||||
async def join(self, inter: disnake.ApplicationCommandInteraction, channel: Optional[disnake.VoiceChannel] = None):
|
||||
"""Joins a voice channel"""
|
||||
channel = inter.author.voice.channel if not channel else channel
|
||||
if self.__channel(inter): await self.__channel(inter).disconnect()
|
||||
await channel.connect()
|
||||
await inter.response.send_message(f"Подключился к каналу {channel.mention}", ephemeral=True)
|
||||
|
||||
# @commands.slash_command()
|
||||
# async def queue(self, inter, *args): pass
|
||||
|
||||
# @commands.slash_command(name="queue")
|
||||
# async def add_to_queue(self, inter: disnake.ApplicationCommandInteraction, prompt_to_queue: str):
|
||||
# try:
|
||||
# await inter.response.defer()
|
||||
# player = await YTDLSource.from_url(prompt_to_queue, loop=self.bot.loop, stream=True)
|
||||
# try:
|
||||
# if len(self.queue[inter.guild.id]) == 0:
|
||||
# if self.__channel(inter): await self.__channel(inter).disconnect()
|
||||
# self.start_playing(await self.ensure_voice(inter), player, inter.guild)
|
||||
# await inter.send(f':mag_right: **Searching for** ``' + prompt_to_queue + '``\n<:youtube:763374159567781890> **Now Playing:** ``{}'.format(player.title) + "``")
|
||||
# else:
|
||||
# self.queue[len(self.queue[inter.guild.id])] = player
|
||||
# await inter.send(f':mag_right: **Searching for** ``' + prompt_to_queue + '``\n<:youtube:763374159567781890> **Added to queue:** ``{}'.format(player.title) + "``")
|
||||
# except KeyError:
|
||||
# self.queue[inter.guild.id] = []
|
||||
# if self.__channel(inter): await self.__channel(inter).disconnect()
|
||||
# self.start_playing(await self.ensure_voice(inter), player, inter.guild)
|
||||
# await inter.send(f':mag_right: **Searching for** ``' + prompt_to_queue + '``\n<:youtube:763374159567781890> **Now Playing:** ``{}'.format(player.title) + "``")
|
||||
|
||||
|
||||
# except Exception as e:
|
||||
|
||||
# await inter.send(f"Somenthing went wrong - please try again later! ||{e}||")
|
||||
|
||||
# def start_playing(self, voice_client, player, guild:disnake.Guild):
|
||||
# self.queue[guild.id].append(player)
|
||||
|
||||
|
||||
# for i in self.queue[guild.id]:
|
||||
# try:
|
||||
# voice_client.play(i, after=lambda e: print('Player error: %s' % e) if e else None)
|
||||
|
||||
# except:
|
||||
# pass
|
||||
|
||||
|
||||
|
||||
@commands.slash_command()
|
||||
async def play(self, inter: disnake.ApplicationCommandInteraction, prompt: str):
|
||||
"""Plays from a url (almost anything youtube_dl supports)"""
|
||||
if self.__channel(inter): await self.__channel(inter).disconnect()
|
||||
|
||||
voiceState: disnake.VoiceClient = await self.ensure_voice(inter)
|
||||
|
||||
await inter.response.defer(with_message=True)
|
||||
player = await YTDLSource.from_url(prompt, loop=self.bot.loop, stream=True)
|
||||
embed = disnake.Embed(title="Вопроизведение музыки.", description=f"**Трек**: {player.title}\n **Автор**: {player.author}\n **Ссылка**: [Тык]({player.id})").set_footer(text=f"Источник: {player.source}").set_thumbnail(url=player.thumbnails)
|
||||
await inter.send(embed=embed)
|
||||
voiceState.play(
|
||||
player, after=lambda e: logger.error(f"Error: {e}") if e else None
|
||||
)
|
||||
|
||||
@commands.slash_command()
|
||||
async def leave(self, inter: disnake.ApplicationCommandInteraction):
|
||||
"""Stops and disconnects the bot from voice"""
|
||||
await self.__channel(inter).disconnect()
|
||||
await inter.response.send_message("Бот вышел из канала", ephemeral=True)
|
||||
|
||||
@commands.slash_command()
|
||||
async def stop(self, inter: disnake.ApplicationCommandInteraction):
|
||||
"""Paused music"""
|
||||
await self.ensure_voice(inter)
|
||||
await inter.response.send_message("Бот остановил воспроизведение", ephemeral=True)
|
||||
|
||||
@commands.slash_command()
|
||||
async def pause(self, inter: disnake.ApplicationCommandInteraction):
|
||||
"""Paused music"""
|
||||
await self.ensure_voice(inter, 'pause')
|
||||
await inter.response.send_message("Бот остановил воспроизведение", ephemeral=True)
|
||||
|
||||
@commands.slash_command()
|
||||
async def resume(self, inter: disnake.ApplicationCommandInteraction):
|
||||
"""Paused music"""
|
||||
await self.ensure_voice(inter, 'resume')
|
||||
await inter.response.send_message("Бот продолжил воспроизведение воспроизведение", ephemeral=True)
|
||||
|
||||
|
||||
async def ensure_voice(self, inter, types:str = None):
|
||||
if self.__channel(inter) == None:
|
||||
if inter.author.voice:
|
||||
return await inter.author.voice.channel.connect()
|
||||
else:
|
||||
await inter.send("You are not connected to a voice channel.", ephemeral=True)
|
||||
raise commands.CommandError("Author not connected to a voice channel.")
|
||||
elif types == "pause" and self.__channel(inter).is_playing():
|
||||
self.__channel(inter).pause()
|
||||
elif types == "resume" and not self.__channel(inter).is_playing():
|
||||
self.__channel(inter).resume()
|
||||
elif self.__channel(inter).is_playing():
|
||||
self.__channel(inter).stop()
|
||||
|
||||
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Music(bot))
|
||||
81
cogs/voiceChannels.py
Normal file
81
cogs/voiceChannels.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from disnake.ext import *
|
||||
import disnake
|
||||
from pathlib import Path
|
||||
from handlers import *
|
||||
import json
|
||||
from log import rootLogger
|
||||
|
||||
voiceChannelData = Path("tempFiles/voiceTempFile.json")
|
||||
voiceChannelName = Path("tempFiles/voiceName.json")
|
||||
class audioChannelAutomatization(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
rootLogger.info(f'Модуль {self.__class__.__name__} включен!')
|
||||
|
||||
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_voice_state_update(member, before, after):
|
||||
if after.channel and after.channel != before.channel and after.channel.name in ['[+] СОЗДАТЬ', '[+]СОЗДАТЬ']:
|
||||
guild = bot.get_guild(member.guild.id)
|
||||
|
||||
category = disnake.utils.get(guild.categories, id=after.channel.category.id)
|
||||
|
||||
data = json.loads(voiceChannelName.read_text(encoding="utf-8"))
|
||||
|
||||
if f"{member.id}" in data:
|
||||
channel = await guild.create_voice_channel(name=f'{data[f"{member.id}"]["chat_name"]}', category=category)
|
||||
else:
|
||||
channel = await guild.create_voice_channel(name=f'{member.name}`s voice channel', category=category)
|
||||
await member.edit(voice_channel=channel)
|
||||
data[f"{member.id}"]["channel_id"] = f"{channel.id}"
|
||||
voiceChannelName.write_text(json.dumps(data, indent=7), "utf-8", newline='\n')
|
||||
embeded = disnake.Embed(title="Пользователь присоединился к каналу", description=f"Пользователь: {member.mention}\n Канал: {after.channel.name}",timestamp=datetime.datetime.now(), color=0x00ff00)
|
||||
embed = disnake.Embed(title = '**Управление приватными комнатами**',
|
||||
description="""Вы можете изменить конфигурацию своей комнаты с помощью кнопок ниже.
|
||||
**Переименовать приватную комнату:** ✏️
|
||||
**Задать лимит участников приватной комнаты:**👥
|
||||
**Закрыть/Открыть приватную комнату:**🔒
|
||||
**Скрыть/Открыть приватную комнату:**👀
|
||||
**Удалить канал(только для создателей канала):** \"Удалить канал\"""", colour=disnake.Colour.from_rgb(47, 49, 54))
|
||||
buttons = disnake.ui.View()
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id='renamePrivateRoom', emoji='✏'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id='setUsersLimit', emoji='👥'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id='closePrivateRoom', emoji=f'🔒'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id='hidePrivateRoom', emoji=f'👀'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.secondary, custom_id='kickUser', label='Кикнуть пользователя'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id='deleteChannel', label='Удалить канал'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.danger, custom_id='giveOwner', label='Передать права на канал'))
|
||||
buttons.add_item(disnake.ui.Button(style=disnake.ButtonStyle.success, custom_id='takeOwner', label='Забрать права на канал'))
|
||||
await bot.get_guild(member.guild.id).get_channel(channel.id).send(embed=embed, view=buttons)
|
||||
writeData = {
|
||||
'chat_name': f'{after.channel.name}',
|
||||
'channel_owner': f'{member.id}',
|
||||
'chat_id': f'{after.channel.id}',
|
||||
}
|
||||
data = json.loads(voiceChannelData.read_text(encoding="utf-8"))
|
||||
data["voice_channels"][f'{after.channel.id}'] = writeData
|
||||
voiceChannelData.write_text(json.dumps(data, indent=7), encoding="utf-8", newline="\n")
|
||||
|
||||
|
||||
elif before.channel and after.channel != before.channel:
|
||||
embeded = disnake.Embed(title="Пользователь покинул канал.", description=f"Пользователь: {member.mention}\n Канал: {before.channel.name}",timestamp=datetime.datetime.now(), color=disnake.Colour.from_rgb(186, 0, 6))
|
||||
guild = bot.get_guild(member.guild.id)
|
||||
data = json.loads(voiceChannelName.read_text(encoding="utf-8"))
|
||||
for item in data:
|
||||
if data[item]['channel_id'] == str(before.channel.id):
|
||||
if before.channel.name == f'{member.name}`s voice channel' or before.channel.name == data[item]["chat_name"] and not len(before.channel.members):
|
||||
try:
|
||||
await before.channel.delete()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
else: pass
|
||||
path = Path("guilds/guilds.json")
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if data["guilds"][f"{member.guild.id}"]["logs"]:
|
||||
embeded.set_thumbnail(url=member.avatar)
|
||||
await bot.get_channel(data["guilds"][f"{member.guild.id}"]["logs"]).send(embed=embeded)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(audioChannelAutomatization(bot))
|
||||
6
guilds/guilds.json
Normal file
6
guilds/guilds.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"guilds":{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
91
handlers.py
Normal file
91
handlers.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import os, datetime, disnake, sys, json
|
||||
from disnake.ext import commands
|
||||
from asyncio import sleep
|
||||
from log import rootLogger
|
||||
from pathlib import Path
|
||||
from os import environ
|
||||
import psycopg2
|
||||
|
||||
def takeSettings(guild_id, data):
|
||||
path = Path("guilds/guilds.json")
|
||||
readedData = json.loads(path.read_text(encoding="utf-8"))
|
||||
pon = readedData["guilds"][f"{guild_id}"][f"{data}"]
|
||||
return pon
|
||||
|
||||
def execute(command:str, isNeedToGiveData: bool = False):
|
||||
with psycopg2.connect(
|
||||
environ.get("PSQL_HOST"),
|
||||
dbname=environ.get("PSQL_DBNAME"),
|
||||
port=environ.get("PSQL_PORT", "5432"),
|
||||
user=environ.get("PSQL_USER"),
|
||||
password=environ.get("PSQL_PASSWORD")
|
||||
) as conn:
|
||||
cur = conn.cursor()
|
||||
cur.execute(command)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
if isNeedToGiveData: return cur.fetchone()
|
||||
else: return
|
||||
|
||||
|
||||
TOKEN = environ.get("TOKEN")
|
||||
api_token = environ.get("API_TOKEN")
|
||||
api_id = environ.get("API_ID")
|
||||
|
||||
|
||||
|
||||
main_path = __file__.replace(os.path.basename(__file__), "")
|
||||
bot = commands.Bot(command_prefix="/", intents=disnake.Intents().all())
|
||||
bot.remove_command("help")
|
||||
|
||||
now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M")
|
||||
|
||||
@bot.listen()
|
||||
async def on_ready():
|
||||
status = [disnake.Status.online, disnake.Status.idle, disnake.Status.dnd]
|
||||
rootLogger.warning(f"{bot.user} is online and connected to Discord.")
|
||||
disnakeGameStatus = disnake.Game(name="Only slash commands! Author github: github.com/yawaflua", type=4)
|
||||
for filename in os.listdir(f"{main_path}/cogs"):
|
||||
if filename.endswith(".py"):
|
||||
namefile = filename.replace(".py", '')
|
||||
bot.load_extension(f"cogs.{namefile}")
|
||||
i = 0
|
||||
while True:
|
||||
await bot.change_presence(status=status[i], activity=disnakeGameStatus)
|
||||
if i >= 2: i = 0
|
||||
i = i+1
|
||||
|
||||
await sleep(30)
|
||||
|
||||
|
||||
@bot.command(is_owner=True, pass_context=True, alias="reload")
|
||||
async def reload(ctx):
|
||||
for filename in os.listdir(f"{main_path}/cogs"):
|
||||
if filename.endswith(".py"):
|
||||
namefile = filename.replace(".py", '')
|
||||
bot.reload_extension(f"cogs.{namefile}")
|
||||
await ctx.message.delete()
|
||||
|
||||
@bot.command( pass_context = True, alias="clear")
|
||||
@commands.has_permissions(manage_messages=True)
|
||||
async def clear( ctx, amount = 1 ):
|
||||
|
||||
await ctx.channel.purge( limit = 1 )
|
||||
await ctx.channel.purge( limit = amount )
|
||||
|
||||
@bot.command(is_owner=True, alias='leave')
|
||||
async def leave(ctx, arg):
|
||||
print(arg)
|
||||
await bot.get_guild(int(arg)).leave()
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
bot.run(TOKEN)
|
||||
except ConnectionError as e:
|
||||
rootLogger.error(f"Time: {now}, Internet exception: {e}. Closing the process....")
|
||||
sys.exit()
|
||||
except Exception as e:
|
||||
rootLogger.error(f"Time: {now} Exception: {e}. Writing in file...")
|
||||
with open("logs/last_error.log", "a") as file:
|
||||
file.write(e)
|
||||
file.close()
|
||||
48
localization/ru.json
Normal file
48
localization/ru.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
|
||||
"CREATE_MODAL_NAME": "создание-заявок",
|
||||
"CREATE_MODAL_DESC":"Создание собственных анкет(Модалов)",
|
||||
|
||||
"CLEAR_NAME": "очистить",
|
||||
"CLEAR_DESC": "Очищает сообщения в чате",
|
||||
"CREATE_EMBED_DESC": "Создание Embed сообщения",
|
||||
"MUTE_NAME": "мут",
|
||||
"APP_MUTE_NAME": "Замутить",
|
||||
"MUTE_DESC":"Замутить пользователя",
|
||||
"ENABLEWLOWMODE_NAME": "включить-медленный-режим",
|
||||
"ENABLEWLOWMODE_DESC": "Включает слоумод в канале",
|
||||
"UNMUTE_NAME": "размут",
|
||||
"UNMUTE_DESC": "Размутить пользователя",
|
||||
"CHANGENICK_NAME": "сменить-ник",
|
||||
"CHANGENICK_DESC": "Смена ника выбранному пользователю(после 3 раз мут)",
|
||||
|
||||
"SETTINGS": "настройки",
|
||||
"SETUP_NAME": "базовая-настройка",
|
||||
"SETUP_DESC": "Базовая настройка бота для этого сервера.",
|
||||
"GUESTROOM_NAME": "оповещение-о-входе",
|
||||
"GUESTROOM_DESC": "Настройка оповещения о входе / выходе игрока на / с сервер(а)",
|
||||
"AUTOBRENCH_NAME": "автоматическое-создание-веток",
|
||||
"AUTOBRENCH_DESC": "Настройка автоматического создания веток в определенном канале",
|
||||
"AUTOREACTION_NAME": "автореакции",
|
||||
"AUTOREACTION_DESC": "Настройка автоматических реакций в канале",
|
||||
"AUTH_DESC": "Аутентификация пользователя, если тот есть в базе данных сервера",
|
||||
"AUTOVOICE_NAME": "приватки",
|
||||
"AUTOVOICE_DESC": "Автоматическое создание голосовых каналов(Если пользователь подключается к [+] СОЗДАТЬ)",
|
||||
"AUTOVOICE_ON": "Включить приватки",
|
||||
"AUTOVOICE_OFF": "Выключить приватки",
|
||||
|
||||
"SAVECHANNEL_NAME": "сохранить-канал",
|
||||
"SAVECHANNEL_DESC": "Сохраняет канал и отправляет его как файл",
|
||||
|
||||
"TICKET_NAME": "создание-тикетов",
|
||||
"TICKET_DESC": "Создает сообщение для открытия тикетов(До 3 кнопок)",
|
||||
|
||||
"GET_AVATAR": "Получить аватарку",
|
||||
"REPORT": "Кинуть репорт",
|
||||
"CHANGEFIELD": "Сменить Field",
|
||||
"ISSUE_ROLE_NAME": "выдача-ролей",
|
||||
"ISSUE_ROLE_DESC": "Выдача ролей по нажатию на кнопку"
|
||||
|
||||
|
||||
}
|
||||
|
||||
31
log.py
Normal file
31
log.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
|
||||
main_path = __file__.replace(os.path.basename(__file__), '')
|
||||
|
||||
formatter = "[%(asctime)s] %(message)s"
|
||||
logFormatter = logging.Formatter(formatter)
|
||||
logging.basicConfig(format=formatter)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
global rootLogger
|
||||
|
||||
|
||||
fileHandler = logging.FileHandler("{0}/{1}.txt".format(f'{main_path}/logs', 'DISCORD_LOG'))
|
||||
fileHandler.setFormatter(logFormatter)
|
||||
|
||||
if os.path.getsize(f'{main_path}/logs/DISCORD_LOG.txt') >= 52428800:
|
||||
fileHandler.close()
|
||||
a = random.random()
|
||||
os.rename(f'{main_path}/logs/DISCORD_LOG.txt', f'DISCORD_LOG_{a}.txt')
|
||||
with open(f'{main_path}/logs/DISCORD_LOG.txt', 'w+') as file:
|
||||
file.write('Cleaning up logs!')
|
||||
file.close()
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
consoleHandler = logging.StreamHandler()
|
||||
consoleHandler.setFormatter(logFormatter)
|
||||
rootLogger = logging.getLogger()
|
||||
rootLogger.addHandler(fileHandler)
|
||||
# rootLogger.addHandler(consoleHandler)
|
||||
|
||||
17
requirements.txt
Normal file
17
requirements.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
aiogram==2.25.1
|
||||
aiohttp==3.8.4
|
||||
chat_exporter==2.6.1
|
||||
config==0.5.1
|
||||
dislash.py==1.4.9
|
||||
disnake==2.9.0
|
||||
Django==4.2.3
|
||||
mojang==0.2.0
|
||||
Pillow==9.5.0
|
||||
Pillow==10.0.0
|
||||
psycopg2_binary==2.9.6
|
||||
Py_SPW==1.4.4
|
||||
Requests==2.31.0
|
||||
validators==0.20.0
|
||||
yandex_music==2.1.1
|
||||
yt_dlp==2023.3.4
|
||||
ytmusicapi==1.1.0
|
||||
1
tempFiles/__init__.py
Normal file
1
tempFiles/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# just ignore this
|
||||
5
tempFiles/ticket.json
Normal file
5
tempFiles/ticket.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ticket": {
|
||||
|
||||
}
|
||||
}
|
||||
3
tempFiles/voiceName.json
Normal file
3
tempFiles/voiceName.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
3
tempFiles/voiceTempFile.json
Normal file
3
tempFiles/voiceTempFile.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
6
tickets/tickets.json
Normal file
6
tickets/tickets.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"tickets":{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
2
users/users.json
Normal file
2
users/users.json
Normal file
@@ -0,0 +1,2 @@
|
||||
{}
|
||||
|
||||
Reference in New Issue
Block a user