Compare commits

...

68 Commits
v1.4 ... main

Author SHA1 Message Date
Profitroll 5c5a620d65 Merge pull request 'Update dependency py-cord to v2.5.0' (#8) from renovate/py-cord-2.x into main
Reviewed-on: #8
2024-03-02 17:44:44 +02:00
Renovate 1c05efa0f4 Update dependency py-cord to v2.5.0 2024-03-02 11:01:22 +02:00
Profitroll f5de2457ba Merge pull request 'Update dependency ujson to v5.9.0' (#7) from renovate/ujson-5.x into main
Reviewed-on: #7
2023-12-12 01:28:19 +02:00
Renovate 8cec182435 Update dependency ujson to v5.9.0 2023-12-11 01:34:57 +02:00
Profitroll ad0ab65c5d Fixed http 2023-08-26 00:00:44 +03:00
Profitroll 0029cdaa30 Replaced Crowdin with Weblate 2023-08-25 23:59:50 +03:00
Profitroll e94883f6ad Merge pull request 'Update dependency ujson to v5.8.0' (#6) from renovate/ujson-5.x into main
Reviewed-on: #6
2023-08-07 14:13:08 +03:00
Renovate 465838a196 Update dependency ujson to v5.8.0 2023-08-07 14:10:43 +03:00
Profitroll a059fb0518 Merge pull request 'Update dependency requests to v2.31.0' (#5) from renovate/requests-2.x into main
Reviewed-on: #5
2023-05-22 19:39:04 +03:00
Renovate c4ee74753b Update dependency requests to v2.31.0 2023-05-22 18:40:49 +03:00
Profitroll 492edc242f Merge pull request 'Update dependency requests to v2.30.0' (#4) from renovate/requests-2.x into main
Reviewed-on: #4
2023-05-08 11:50:52 +03:00
Renovate 66c0ad7ee8 Update dependency requests to v2.30.0 2023-05-08 11:46:39 +03:00
Profitroll c1ee1b50ab Added config check and updated version to 2.3 2023-05-07 16:39:48 +02:00
Profitroll 7a379cf97e Updated ignore 2023-05-07 16:38:46 +02:00
Profitroll 388e27fdff config.json is now config_example.json 2023-05-07 16:38:17 +02:00
Profitroll 65a0e1097e Updated version to 2.2 2023-05-07 16:24:09 +02:00
Profitroll 3fe67e18b0 Channel will terminate when the last user quit 2023-05-07 16:23:16 +02:00
Profitroll 91eecb4b0b Fixed channels logic 2023-05-02 16:13:11 +02:00
Profitroll 740c6a1464 Updated version to 2.1 2023-05-02 16:10:32 +02:00
Profitroll 3ca44dcd2d Updated version to 2.0 2023-05-02 15:10:29 +02:00
Profitroll 301439f144 Fixed bot trigger on deafen and mute 2023-05-02 15:09:23 +02:00
Profitroll 3435d59d96 Merge pull request 'Update dependency requests to v2.29.0' (#3) from renovate/requests-2.x into main
Reviewed-on: #3
2023-04-26 23:49:52 +03:00
Renovate d560bce8c6 Update dependency requests to v2.29.0 2023-04-26 18:48:15 +03:00
Profitroll 528604b6b4 Made a few dependencies strict 2023-04-23 10:35:27 +02:00
Profitroll 76c7812284 Renamed Renovate config 2023-04-20 13:38:00 +02:00
Profitroll 8e48334cea Merge pull request 'Configure Renovate' (#1) from renovate/configure into main
Reviewed-on: #1
2023-04-20 14:37:19 +03:00
Renovate bc9cebbec6 Add renovate.json 2023-04-20 14:13:46 +03:00
Profitroll a178aa2af9 Merge branch 'main' of https://git.profitroll.eu/profitroll/YusarinBot 2023-04-19 14:27:12 +02:00
Profitroll fb3e291d77 Sorted imports and removed unused ones 2023-04-19 14:23:41 +02:00
Profitroll 75c1889477 Formatted everything with black 2023-04-19 14:21:39 +02:00
Profitroll 5329b4c727 Bump pycord to 2.4.1 2023-04-19 14:16:32 +02:00
Profitroll 0f3a6121d6 Fixed black badge link 2023-03-22 21:30:45 +01:00
Profitroll 7f1f86ca03 Fixed update checker behavior 2023-03-22 21:26:05 +01:00
Profitroll c600747848 Bump py-cord to 2.4.1 2023-03-22 21:09:58 +01:00
Profitroll a2bd55dcdf Updated version to 1.9 2023-03-22 21:09:32 +01:00
Profitroll 98ac531a36 Changed version API requests 2023-03-22 21:09:09 +01:00
Profitroll af24a055b6 Updated header 2023-03-22 21:05:46 +01:00
Profitroll 97fe10bb96 Formatted with black 2023-03-22 20:59:50 +01:00
Profitroll bad83b0266 Added gitignore 2023-03-22 20:56:01 +01:00
Profitroll 97d05866e2 Updated default config link 2023-01-18 11:23:28 +02:00
Profitroll e56268543c Migrated to cogs 2023-01-17 15:50:47 +01:00
Profitroll be9ed44614 Updated readme 2023-01-17 15:26:43 +01:00
Profitroll eec975ce36 Added notice about linux dependencies 2023-01-17 15:24:34 +01:00
Profitroll 512517f76e Fixed imports 2023-01-17 15:21:26 +01:00
Profitroll af29a7ced6 Added one more optional dependency 2023-01-17 15:14:10 +01:00
Profitroll 9b8d389031 Updated README 2023-01-17 15:10:04 +01:00
Profitroll 0f7a860dad Updated requirements 2023-01-17 15:06:51 +01:00
Profitroll a3a0aaa72b Tasty refactor 2023-01-17 15:05:39 +01:00
Profitroll 78239c7e5d Update 1.7 2022-08-03 11:22:06 +03:00
Profitroll 79fb14b1bc Update 1.7 2022-08-03 10:19:17 +02:00
Profitroll 0379d99e69 Update 1.7 2022-08-03 10:11:40 +02:00
Profitroll 462f4c7a09 Update 1.7 2022-08-03 10:11:04 +02:00
Profitroll 078eac1446 Updated version check path 2022-07-22 10:54:57 +03:00
Profitroll 6334002068 Updated repo badges 2022-07-20 22:29:39 +03:00
Profitroll ffa3babb45 Some minor locale changes 2022-07-20 14:14:58 +03:00
Profitroll fba819ce29 Update 'locale/uk.json' 2022-07-20 14:14:04 +03:00
Profitroll 7ccb674b9f Update 'locale/uk.json' 2022-07-20 14:06:53 +03:00
Profitroll b6e9f5089c Changed some small things 2022-07-20 14:06:36 +03:00
Profitroll 85480c7658 Added "localized" badge 2022-07-20 00:25:10 +03:00
Profitroll 78a845a99b Update 1.6 2022-07-15 22:28:01 +02:00
Profitroll 9b138781a6
Update 1.5 2022-05-10 01:36:48 +02:00
Profitroll 83431d7371
Update 1.5 2022-05-10 01:26:15 +02:00
Profitroll 3ec769d017
Updated invite link 2022-05-10 01:22:43 +02:00
Profitroll be209de3e0 Small locale fix 2022-05-08 23:30:40 +02:00
Profitroll c06031e893 Update 1.5 2022-05-08 23:09:19 +02:00
Profitroll 4254570efc Studio policy update 2022-02-22 03:27:33 +02:00
Profitroll 62c7a70aec
Also small fix. 2022-02-21 03:15:34 +02:00
Profitroll 95d95b1014
Small fix 2022-02-21 02:05:52 +02:00
15 changed files with 1047 additions and 666 deletions

173
.gitignore vendored Normal file
View File

@ -0,0 +1,173 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# ---> VisualStudioCode
.vscode/*
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
# Project
venv
venv_linux
venv_windows
config.json

6
.renovaterc Normal file
View File

@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

View File

@ -1,32 +1,57 @@
# YusarinBot
<h1 align="center">YusarinBot</h1>
Simple, clear, easy, reliable.
A specially designed bot for creating private voice channels at your servers.
<p align="center">
<a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html">
<img alt="License: GPL v2" src="https://img.shields.io/badge/License-GPL_v2-blue.svg">
</a>
<a href="https://weblate.end-play.xyz/engage/yusarinbot/">
<img src="https://weblate.end-play.xyz/widget/yusarinbot/svg-badge.svg" alt="Translation status" />
</a>
<a href="https://git.end-play.xyz/profitroll/YusarinBot">
<img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg">
</a>
<a href="https://discord.com/invite/2zpzErtnNT">
<img alt="Discord" src="https://img.shields.io/discord/940760922346123284">
</a>
</p>
Simple, easy to set up, yet reliable.
A specially designed bot for creating private voice channels on your Discord servers.
Installation instructions are listed below. Please, make sure you have installed dependencies before opening issue here.
> Since version 1.5 only slash commands are supported. If you'd like to use old-fashioned commands and commands prefix feature consider installing [1.4 version](https://git.end-play.xyz/profitroll/YusarinBot/releases/tag/v1.4) which is the last one compatible with those.
## Installation (Short)
1. `git clone https://github.com/profitrollgame/YusarinBot`
1. `git clone https://git.end-play.xyz/profitroll/YusarinBot`
2. `cd YusarinBot`
3. `pip install -r requirements.txt`
4. `nano config.json`
5. `python yusarin.py`
4. `cp config_example.json config.json`
5. `nano config.json`
6. `python yusarin.py`
## Installation (Detailed)
1. Download and install Python 3 (3.6+ should be fine)
2. Download bot's release: https://github.com/profitrollgame/YusarinBot/releases/latest
1. Download and install Python 3.8+
2. Download bot's release: <https://git.end-play.xyz/profitroll/YusarinBot/releases/latest>
3. Unpack your archive to folder. Name it YusarinBot for example
4. Change working directory using `cd YusarinBot` or `cd FolderYouHaveCreated`
5. Run `pip install -r requirements.txt` to install dependencies
6. Create new Discord application at https://discord.com/developers/applications
7. You can rename it however you want, set needed descriptions etc
8. Go to "Bot" tab and enable application as bot
9. Copy token of your bot
10. Open file `config.json` with your favorite text editor and paste your token as value of "bot_token" key
11. Copy your own Discord ID and paste it as value of "owner" key (How to get ID: https://support.playhive.com/discord-user-id/)
12. Bot is ready! Run it using `python yusarin.py`
5. If you're using Linux system - install [dependencies for Pycord](https://docs.pycord.dev/en/stable/installing.html#installing)
6. Run `pip install -r requirements.txt` to install dependencies
7. [Optionally] run `pip install -r requirements-optional.txt` to install optional dependencies
8. Create new Discord application at <https://discord.com/developers/applications>
9. You can rename it however you want, set needed descriptions etc
10. Go to "Bot" tab and enable application as bot
11. Copy token of your bot
12. Copy `config_example.json` to `config.json`
13. Open file `config.json` with your favorite text editor and paste your token as value of "bot_token" key
14. Copy your own Discord ID and paste it as value of "owner" key (How to get ID: <https://support.playhive.com/discord-user-id/>)
15. Bot is ready! Run it using `python yusarin.py`
## Config explanation
Default configuration file is [available here](https://github.com/profitrollgame/YusarinBot/blob/main/config.json)
Default configuration file is [available here](https://git.profitroll.eu/profitroll/YusarinBot/src/branch/main/config.json)
- "debug" - Option that enables more detailed log messages [Boolean]
- "owner" - Discord ID of user who will be able to execute admin commands (`$shutdown` for example) [Integer]
- "bot_name" - Name of your bot. Is not used anywhere yet [String]
@ -38,6 +63,7 @@ Default configuration file is [available here](https://github.com/profitrollgame
- "color_ok" - HTML color used on command success embed [String]
- "color_warn" - HTML color used in all warning embeds [String]
- "color_error" - HTML color used on command error embed [String]
- "enable_nomic" - Option that allows you to create additional text channel for "nomic" purposes [Boolean]
- "bot_site" - http or https link that will be used in help message header [String]
- "bot_icon" - http or https link that will be used in help message header's icon [String]
- "check_for_updates" - Option that defines whether bot should check for a new version available [Boolean]
@ -45,5 +71,7 @@ Default configuration file is [available here](https://github.com/profitrollgame
- "auto_clear_timer" - Option that defines how often "auto_clear_trash" will do its job [Integer]
## Extra
1. Bot doesn't have any self updaters **yet**
2. You can add public version of the bot to your Discord server using this link: https://discord.com/api/oauth2/authorize?client_id=937839388853944390&permissions=318769168&scope=bot
2. You can add public version of the bot to your Discord server using this link: <https://www.end-play.xyz/yusarin/invite>
3. If you have questions/suggestions - just join our [Discord Support Server](https://discord.com/invite/2zpzErtnNT)

91
cogs/cogCategory.py Normal file
View File

@ -0,0 +1,91 @@
from discord import ApplicationContext, CategoryChannel, Option, SlashCommandGroup
from discord.ext import commands
from functions import (
getMsg,
guildConfGet,
guildConfReset,
guildConfSet,
loadJson,
makeEmbed,
strToColor,
)
# =========================================================================================================================
class CogCategory(commands.Cog):
def __init__(self, client):
self.client = client
category = SlashCommandGroup(
"category", "Commands related to parent channels category"
)
@category.command(
name="set",
description="Select the voice channel that will be parent to private ones",
)
async def category_set(self, ctx: ApplicationContext, category: Option(CategoryChannel, "Parent Channel Category")): # type: ignore
config = loadJson("config.json")
if ctx.guild is not None:
guildConfSet(ctx.guild, "category", category.id)
await ctx.respond(
embed=makeEmbed(
title=getMsg("set_category_title", ctx.guild),
description=getMsg("set_category_description", ctx.guild).format(
category.name
),
color=strToColor(config["color_ok"]),
)
)
if guildConfGet(ctx.guild, "channel") is None:
await ctx.respond(
embed=makeEmbed(
title=getMsg("hint_none_channel_title", ctx.guild),
description=getMsg("hint_none_channel_description", ctx.guild),
color=strToColor(config["color_warn"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("dm_title", ctx.guild),
description=getMsg("dm_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
@category.command(
name="reset", description="Reset the currently selected parent channel category"
)
async def category_reset(self, ctx: ApplicationContext): # type: ignore
config = loadJson("config.json")
if ctx.guild is not None:
if guildConfGet(ctx.guild, "category") is not None:
guildConfReset(ctx.guild, "category")
await ctx.respond(
embed=makeEmbed(
title=getMsg("reset_category_title", ctx.guild),
description=getMsg("reset_category_description", ctx.guild),
color=strToColor(config["color_ok"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("hint_none_category_title", ctx.guild),
description=getMsg("hint_none_category_description", ctx.guild),
color=strToColor(config["color_warn"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("dm_title", ctx.guild),
description=getMsg("dm_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
# =========================================================================================================================

155
cogs/cogChannel.py Normal file
View File

@ -0,0 +1,155 @@
from discord import (
ApplicationContext,
Cog,
Member,
SlashCommandGroup,
VoiceChannel,
VoiceState,
option,
utils,
)
from discord.ext import commands
from discord.abc import GuildChannel
from functions import (
appendLog,
changeNomicPerms,
createUserVoice,
getMsg,
guildConfGet,
guildConfReset,
guildConfSet,
isUserVoice,
isVoiceOfUser,
loadJson,
makeEmbed,
removeUserVoice,
strToColor,
)
# =========================================================================================================================
class CogChannel(commands.Cog):
def __init__(self, client):
self.client = client
@commands.Cog.listener()
async def on_guild_channel_delete(self, channel: GuildChannel):
if isUserVoice(channel):
await removeUserVoice(channel)
@Cog.listener()
async def on_voice_state_update(
self, member: Member, before: VoiceState, after: VoiceState
):
config = loadJson("config.json")
vc_from = before.channel
vc_to = after.channel
# If user left vc
if before.channel is not None and len(before.channel.members) == 0:
if isUserVoice(vc_from):
if not isVoiceOfUser(vc_from, member):
if loadJson("config.json")["enable_nomic"]:
await changeNomicPerms("deny", vc_from, member)
await removeUserVoice(vc_from)
# If user joined vc
if after.channel is not None and after.channel.id == guildConfGet(
member.guild, "channel"
):
if isUserVoice(vc_to):
if loadJson("config.json")["enable_nomic"]:
await changeNomicPerms("allow", vc_to, member)
if vc_to.id == guildConfGet(vc_to.guild, "channel"):
if guildConfGet(vc_to.guild, "category") is not None:
voice_chan = await createUserVoice(
vc_to,
utils.get(
vc_to.guild.categories,
id=guildConfGet(vc_to.guild, "category"),
),
member,
)
try:
await member.move_to(voice_chan)
except:
await removeUserVoice(voice_chan)
else:
appendLog(
f"Category for guild {vc_to.guild} ({str(vc_to.guild.id)}) is not set",
guild=vc_to.guild,
)
channel = SlashCommandGroup("channel", "Commands related to parent voice channel")
@channel.command(
name="set",
description="Select the voice channel that will be parent to private ones",
)
@option("channel", description="Parent Voice Channel")
async def channel_set(self, ctx: ApplicationContext, channel: VoiceChannel):
config = loadJson("config.json")
if ctx.guild is not None:
guildConfSet(ctx.guild, "channel", channel.id)
await ctx.respond(
embed=makeEmbed(
title=getMsg("set_channel_title", ctx.guild),
description=getMsg("set_channel_description", ctx.guild).format(
channel.name
),
color=strToColor(config["color_ok"]),
)
)
if guildConfGet(ctx.guild, "category") is None:
await ctx.respond(
embed=makeEmbed(
title=getMsg("hint_none_category_title", ctx.guild),
description=getMsg("hint_none_category_description", ctx.guild),
color=strToColor(config["color_warn"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("dm_title", ctx.guild),
description=getMsg("dm_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
@channel.command(
name="reset", description="Reset the currently selected parent voice channel"
)
async def channel_reset(self, ctx: ApplicationContext):
config = loadJson("config.json")
if ctx.guild is not None:
if guildConfGet(ctx.guild, "channel") is not None:
guildConfReset(ctx.guild, "channel")
await ctx.respond(
embed=makeEmbed(
title=getMsg("reset_channel_title", ctx.guild),
description=getMsg("reset_channel_description", ctx.guild),
color=strToColor(config["color_ok"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("hint_none_channel_title", ctx.guild),
description=getMsg("hint_none_channel_description", ctx.guild),
color=strToColor(config["color_warn"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("dm_title", ctx.guild),
description=getMsg("dm_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
# =========================================================================================================================

105
cogs/cogLocale.py Normal file
View File

@ -0,0 +1,105 @@
from os import listdir
from discord import ApplicationContext, Option, SlashCommandGroup
from discord.ext import commands
from functions import (
appendLog,
getMsg,
guildConfGet,
guildConfReset,
guildConfSet,
loadJson,
makeEmbed,
strToColor,
)
# =========================================================================================================================
class CogLocale(commands.Cog):
def __init__(self, client):
self.client = client
locale = SlashCommandGroup("locale", "Commands related to bot's locale")
valid_locales = []
files_locales = listdir(f"locale/")
for entry in files_locales:
valid_locales.append(".".join(entry.split(".")[:-1]))
@locale.command(name="set", description="Set bot's messages language")
async def locale_set(self, ctx: ApplicationContext, language: Option(str, "One of the languages in list", choices=valid_locales)): # type: ignore
config = loadJson("config.json")
if ctx.guild is not None:
if language + ".json" in listdir(f"locale/"):
guildConfSet(ctx.guild, "locale", language)
appendLog(f"Server's locale is now set to {language}", ctx.guild)
await ctx.respond(
embed=makeEmbed(
title=getMsg("set_locale_title", ctx.guild),
description=getMsg("set_locale_description", ctx.guild).format(
getMsg("locale_name", ctx.guild)
),
color=strToColor(config["color_ok"]),
)
)
else:
valid_locales = []
files_locales = listdir(f"locale/")
for entry in files_locales:
valid_locales.append(entry.split(".")[:-1])
await ctx.respond(
embed=makeEmbed(
title=getMsg("error_locale_title", ctx.guild),
description=getMsg(
"error_locale_description", ctx.guild
).format(", ".join(valid_locales)),
color=strToColor(config["color_error"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("dm_title", ctx.guild),
description=getMsg("dm_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
@locale.command(name="reset", description="Reset the bot's language in this guild")
async def locale_reset(self, ctx: ApplicationContext): # type: ignore
config = loadJson("config.json")
if ctx.guild is not None:
if guildConfGet(ctx.guild, "locale") is not None:
guildConfReset(ctx.guild, "locale")
appendLog(f"Server's locale has been reset", ctx.guild)
await ctx.respond(
embed=makeEmbed(
title=getMsg("reset_locale_title", ctx.guild),
description=getMsg(
"reset_locale_description", ctx.guild
).format(getMsg("locale_name", ctx.guild)),
color=strToColor(config["color_ok"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("hint_none_locale_title", ctx.guild),
description=getMsg(
"hint_none_locale_description", ctx.guild
).format(getMsg("locale_name", ctx.guild)),
color=strToColor(config["color_warn"]),
)
)
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("dm_title", ctx.guild),
description=getMsg("dm_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
# =========================================================================================================================

53
cogs/cogUtility.py Normal file
View File

@ -0,0 +1,53 @@
from os import getpid, makedirs, system
from shutil import rmtree
from discord import ApplicationContext, Cog, Guild, slash_command
from discord.ext import commands
from functions import appendLog, getMsg, loadJson, makeEmbed, saveJson, strToColor
# =========================================================================================================================
class CogUtility(commands.Cog):
def __init__(self, client):
self.client = client
@Cog.listener()
async def on_guild_join(self, guild: Guild):
makedirs(f"guilds/{str(guild.id)}", exist_ok=True)
makedirs(f"guilds/{str(guild.id)}/channels", exist_ok=True)
saveJson({}, f"guilds/{str(guild.id)}/config.json")
appendLog(f"Joined guild '{guild}' with id {str(guild.id)}")
@Cog.listener()
async def on_guild_remove(self, guild: Guild):
try:
rmtree(f"guilds/{str(guild.id)}")
except:
pass
appendLog(f"Left guild '{guild}' with id {str(guild.id)}")
@slash_command(name="shutdown", description="Restart the bot")
async def shutdown(self, ctx: ApplicationContext):
config = loadJson("config.json")
if ctx.author.id == config["owner"]:
await ctx.respond(
embed=makeEmbed(
description=getMsg("shutdown", ctx.guild).format(ctx.author),
color=strToColor(config["color_default"]),
)
)
system(f"kill -9 {str(getpid())}")
else:
await ctx.respond(
embed=makeEmbed(
title=getMsg("admin_title", ctx.guild),
description=getMsg("admin_description", ctx.guild),
color=strToColor(config["color_error"]),
)
)
# =========================================================================================================================

View File

@ -10,6 +10,7 @@
"color_ok": "#226699",
"color_warn": "#FFCC4D",
"color_error": "#DD2E44",
"enable_nomic": false,
"bot_site": "https://www.end-play.xyz/yusarin",
"bot_icon": "https://www.end-play.xyz/yusarin/logo",
"check_for_updates": true,

View File

@ -1,13 +1,29 @@
import os
import sys
import json
import shutil
import discord
from datetime import datetime
from pathlib import Path
from gzip import open as gzipopen
from os import listdir, makedirs, path, remove, stat
from shutil import copyfileobj
from typing import Any, Literal, Union
path = Path(__file__).resolve().parent
from discord import (
ApplicationContext,
CategoryChannel,
Client,
Embed,
Guild,
Member,
Message,
PermissionOverwrite,
TextChannel,
VoiceChannel,
utils,
)
try:
from ujson import dumps, loads
except ImportError:
from json import dumps, loads
# path = Path(__file__).resolve().parent
log_size = 512
@ -17,40 +33,42 @@ log_size = 512
debug = False
try:
with open("config.json", 'r', encoding="utf-8") as json_file:
output = json.load(json_file)
with open("config.json", "r", encoding="utf-8") as json_file:
output = loads(json_file.read())
json_file.close()
debug = output["debug"]
except:
debug = debug
# Check latest log size
def checkSize():
global path
path = str(path)
try:
if not os.path.isdir(f"{path}/logs"):
os.mkdir(f"{path}/logs")
log = os.stat(path + '/logs/latest.log')
if not path.isdir("logs"):
makedirs("logs", exist_ok=True)
log = stat("logs/latest.log")
global log_size
if (log.st_size / 1024) > log_size:
with open(path + '/logs/latest.log', 'rb') as f_in:
with gzip.open(f'{path}/logs/{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz', 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
print(f'Copied {path}/logs/{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz')
open(path + '/logs/latest.log', 'w').close()
with open("logs/latest.log", "rb") as f_in:
with gzipopen(
f'logs/{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz', "wb"
) as f_out:
copyfileobj(f_in, f_out)
print(
f'Copied logs/{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz'
)
open("logs/latest.log", "w").close()
except FileNotFoundError:
print('Not found')
print("Not found")
pass
# Append string to log
def appendLog(message, guild=None, announce=True):
def appendLog(message: str, guild: Union[Guild, None] = None, announce=True) -> None:
global debug
global path
if guild == None:
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] {message}'
else:
@ -58,26 +76,28 @@ def appendLog(message, guild=None, announce=True):
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] [{guild} | {str(guild.id)}] {message}'
else:
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] [{guild}] {message}'
if announce:
print(message_formatted)
print(message_formatted, flush=True)
checkSize()
log = open(path + '/logs/latest.log', 'a')
log.write(f'{message_formatted}\n')
log = open("logs/latest.log", "a") # type: ignore
log.write(f"{message_formatted}\n")
log.close()
def saveJson(value, filename):
with open(filename, 'w', encoding="utf-8") as f:
json.dump(value, f, indent=4, ensure_ascii=False)
def saveJson(value: Any, filename: str) -> None:
with open(filename, "w", encoding="utf-8") as f:
f.write(dumps(value, indent=4, ensure_ascii=False))
f.close()
def loadJson(filename):
def loadJson(filename: str) -> Any:
global debug
try:
with open(filename, 'r', encoding="utf-8") as json_file:
output = json.load(json_file)
with open(filename, "r", encoding="utf-8") as json_file:
output = loads(json_file.read())
json_file.close()
except Exception as exp:
if debug:
@ -85,60 +105,68 @@ def loadJson(filename):
output = {}
return output
def colorToStr():
pass
def strToColor(string):
def strToColor(string: str) -> int:
return int(hex(int(string.replace("#", ""), 16)), 0)
def gotCommand(message):
def gotCommand(message: Message) -> None:
global debug
if debug:
appendLog(f"Command '{message.content}' from {message.author} ({str(message.author.id)})", message.guild)
appendLog(
f"Command '{message.content}' from {message.author} ({str(message.author.id)})",
message.guild,
)
else:
appendLog(f"Command '{message.content}' from {message.author}", message.guild)
def guildConfGet(guild, variable):
global path
def guildConfGet(guild: Guild, variable: str) -> Any:
global debug
try:
config = loadJson(f"{path}/guilds/{str(guild.id)}/config.json")
config = loadJson(f"guilds/{str(guild.id)}/config.json")
return config[variable]
except Exception as exp:
if debug:
appendLog(f"Could not get guild config key '{variable}' due to {exp}", guild)
appendLog(
f"Could not get guild config key '{variable}' due to {exp}", guild
)
return None
def guildConfSet(guild, variable, value):
global path
config = loadJson(f"{path}/guilds/{str(guild.id)}/config.json")
def guildConfSet(guild: Guild, variable: str, value: Any) -> None:
config = loadJson(f"guilds/{str(guild.id)}/config.json")
config[variable] = value
try:
saveJson(config, f"{path}/guilds/{str(guild.id)}/config.json")
saveJson(config, f"guilds/{str(guild.id)}/config.json")
except:
os.mkdir(f"{path}/guilds/{str(guild.id)}")
os.mkdir(f"{path}/guilds/{str(guild.id)}/channels")
saveJson(config, f"{path}/guilds/{str(guild.id)}/config.json")
makedirs(f"guilds/{str(guild.id)}", exist_ok=True)
makedirs(f"guilds/{str(guild.id)}/channels", exist_ok=True)
saveJson(config, f"guilds/{str(guild.id)}/config.json")
appendLog(f"Guild config key '{variable}' is now set to '{value}'", guild)
def guildConfReset(guild, variable):
global path
def guildConfReset(guild: Guild, variable: str) -> None:
try:
config = loadJson(f"{path}/guilds/{str(guild.id)}/config.json")
config = loadJson(f"guilds/{str(guild.id)}/config.json")
del config[variable]
try:
saveJson(config, f"{path}/guilds/{str(guild.id)}/config.json")
saveJson(config, f"guilds/{str(guild.id)}/config.json")
except:
os.mkdir(f"{path}/guilds/{str(guild.id)}")
os.mkdir(f"{path}/guilds/{str(guild.id)}/channels")
saveJson(config, f"{path}/guilds/{str(guild.id)}/config.json")
makedirs(f"guilds/{str(guild.id)}", exist_ok=True)
makedirs(f"guilds/{str(guild.id)}/channels", exist_ok=True)
saveJson(config, f"guilds/{str(guild.id)}/config.json")
appendLog(f"Guild config key '{variable}' has been reset", guild)
except Exception as exp:
appendLog(f"Could not reset guild config key '{variable}' due to {exp}", guild)
def guildLocaleGet(guild):
global path
config = loadJson(f"{path}/config.json")
def guildLocaleGet(guild: Guild) -> str:
config = loadJson(f"config.json")
try:
locale = guildConfGet(guild, "locale")
except:
@ -148,156 +176,232 @@ def guildLocaleGet(guild):
else:
return locale
def getMsg(string, guild=None):
global path
config = loadJson("config.json")
def getMsg(string: str, guild: Union[Guild, None] = None) -> str:
try:
locale = loadJson(f'{path}/locale/{guildLocaleGet(guild)}.json')
locale = loadJson(f"locale/{guildLocaleGet(guild)}.json")
return locale["messages"][string]
except Exception as exp:
appendLog(f"Could not get locale string named {string} due to exception {exp}", guild)
appendLog(
f"Could not get locale string named {string} due to exception {exp}", guild
)
return string
def makeEmbed(title="", description="", footer="", color=0xffffff):
embed=discord.Embed(title=title, description=description, color=color)
def makeEmbed(title="", description="", footer="", color=0xFFFFFF) -> Embed:
embed = Embed(title=title, description=description, color=color)
if footer is not None:
embed.set_footer(text=footer)
return embed
def channelExists(number, guild, type="Any"):
def channelExists(
number: int, guild: Guild, type: Literal["Any", "Text", "Voice"] = "Any"
) -> bool:
global debug
if number == None:
return False
try:
if type == "Voice":
selected_channel = discord.utils.get(guild.channels, id=number)
if isinstance(selected_channel, discord.VoiceChannel):
selected_channel = utils.get(guild.channels, id=number)
if isinstance(selected_channel, VoiceChannel):
return True
elif type == "Text":
selected_channel = discord.utils.get(guild.channels, id=number)
if isinstance(selected_channel, discord.TextChannel):
selected_channel = utils.get(guild.channels, id=number)
if isinstance(selected_channel, TextChannel):
return True
elif type == "Any":
selected_channel = discord.utils.get(guild.channels, id=number)
selected_channel = utils.get(guild.channels, id=number)
return True
except Exception as exp:
if debug:
appendLog(f"Channel ID {str(number)} is not a channel due to {exp}")
return False
def channelGetName(number, guild):
def channelGetName(number: int, guild: Guild):
global debug
try:
selected_channel = discord.utils.get(guild.channels, id=number)
selected_channel = utils.get(guild.channels, id=number)
return selected_channel.name
except Exception as exp:
if debug:
appendLog(f"Channel ID {str(number)} is not a channel due to {exp}")
return "Channel doesn't exist"
def isUserVoice(vc):
global path
def isUserVoice(vc: VoiceChannel) -> bool:
try:
channels_list = os.listdir(f"{path}/guilds/{str(vc.guild.id)}/channels/")
channels_list = listdir(f"guilds/{str(vc.guild.id)}/channels/")
if f"{str(vc.id)}.json" in channels_list:
return True
else:
return False
except:
return False
async def removeUserVoice(vc):
global path
async def removeUserVoice(vc: VoiceChannel) -> None:
global debug
channels_list = os.listdir(f"{path}/guilds/{str(vc.guild.id)}/channels/")
channels_list = listdir(f"guilds/{str(vc.guild.id)}/channels/")
if f"{vc.id}.json" in channels_list:
vc_file = f"{path}/guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
vc_conf = loadJson(vc_file)
needed_channel = utils.get(vc.guild.channels, id=vc.id)
if loadJson("config.json")["enable_nomic"]:
nomic_channel = utils.get(vc.guild.channels, id=vc_conf["nomic"])
remove(vc_file)
needed_channel = discord.utils.get(vc.guild.channels, id=vc.id)
nomic_channel = discord.utils.get(vc.guild.channels, id=vc_conf["nomic"])
os.remove(vc_file)
await needed_channel.delete()
if debug:
appendLog(f"Removed voice channel '{needed_channel}' ({str(needed_channel.id)}) of user with id {str(vc_conf['ownerid'])}", guild=vc.guild)
if needed_channel is None:
appendLog(
f"Removed voice channel '{needed_channel}' of user with id {str(vc_conf['ownerid'])}",
guild=vc.guild,
)
else:
appendLog(f"Removed voice channel '{needed_channel}' of user with id {str(vc_conf['ownerid'])}", guild=vc.guild)
await nomic_channel.delete()
if debug:
appendLog(f"Removed nomic channel {nomic_channel} ({str(nomic_channel.id)}) of channel with id {str(needed_channel.id)}", guild=vc.guild)
else:
appendLog(f"Removed nomic channel '{nomic_channel}' of channel with id {str(needed_channel.id)}", guild=vc.guild)
await needed_channel.delete()
if debug:
appendLog(
f"Removed voice channel '{needed_channel}' ({str(needed_channel.id)}) of user with id {str(vc_conf['ownerid'])}",
guild=vc.guild,
)
else:
appendLog(
f"Removed voice channel '{needed_channel}' of user with id {str(vc_conf['ownerid'])}",
guild=vc.guild,
)
if loadJson("config.json")["enable_nomic"]:
if nomic_channel is None:
appendLog(
f"Removed nomic channel '{nomic_channel}' of channel with id {str(needed_channel.id)}",
guild=vc.guild,
)
else:
await nomic_channel.delete()
if debug:
appendLog(
f"Removed nomic channel '{nomic_channel}' ({str(nomic_channel.id)}) of channel with id {str(needed_channel.id)}",
guild=vc.guild,
)
else:
appendLog(
f"Removed nomic channel '{nomic_channel}' of channel with id {str(needed_channel.id)}",
guild=vc.guild,
)
else:
return
async def createUserVoice(vc, category, member):
global path
async def createUserVoice(
vc: VoiceChannel, category: CategoryChannel, member: Member
) -> VoiceChannel:
global debug
chan = {}
overwrites_channel = {
vc.guild.default_role: discord.PermissionOverwrite(view_channel=True),
vc.guild.me: discord.PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True),
member: discord.PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True)
vc.guild.default_role: PermissionOverwrite(view_channel=True),
vc.guild.me: PermissionOverwrite(
read_messages=True, view_channel=True, manage_channels=True
),
member: PermissionOverwrite(
read_messages=True, view_channel=True, manage_channels=True
),
}
overwrites_nomic = {
vc.guild.default_role: discord.PermissionOverwrite(view_channel=False, read_messages=False),
vc.guild.me: discord.PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True),
member: discord.PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True)
vc.guild.default_role: PermissionOverwrite(
view_channel=False, read_messages=False
),
vc.guild.me: PermissionOverwrite(
read_messages=True, view_channel=True, manage_channels=True
),
member: PermissionOverwrite(
read_messages=True, view_channel=True, manage_channels=True
),
}
created_channel = await vc.guild.create_voice_channel(getMsg("name_voice", vc.guild).format(member.name), category=category, overwrites=overwrites_channel)
created_channel = await vc.guild.create_voice_channel(
getMsg("name_voice", vc.guild).format(member.name),
category=category,
overwrites=overwrites_channel,
)
if debug:
appendLog(f"Created voice channel '{created_channel}' ({str(created_channel.id)}) for user {member} ({str(member.id)})", guild=vc.guild)
appendLog(
f"Created voice channel '{created_channel}' ({str(created_channel.id)}) for user {member} ({str(member.id)})",
guild=vc.guild,
)
else:
appendLog(f"Created voice channel '{created_channel}' for user {member}", guild=vc.guild)
if not os.path.isdir(f"{path}/guilds/{str(created_channel.guild.id)}/channels"):
os.mkdir(f"{path}/guilds/{str(created_channel.guild.id)}/channels")
vc_file = f"{path}/guilds/{str(created_channel.guild.id)}/channels/{str(created_channel.id)}.json"
appendLog(
f"Created voice channel '{created_channel}' for user {member}",
guild=vc.guild,
)
if not path.isdir(f"guilds/{str(created_channel.guild.id)}/channels"):
makedirs(f"guilds/{str(created_channel.guild.id)}/channels", exist_ok=True)
vc_file = f"guilds/{str(created_channel.guild.id)}/channels/{str(created_channel.id)}.json"
chan["ownerid"] = member.id
saveJson(chan, vc_file)
nomic_channel = await vc.guild.create_text_channel(getMsg("name_nomic", vc.guild).format(created_channel.id), category=category, overwrites=overwrites_nomic, topic=getMsg("description_nomic", vc.guild).format(str(created_channel.id)))
if debug:
appendLog(f"Created nomic channel '{nomic_channel}' ({str(nomic_channel.id)}) for channel '{created_channel}' ({str(created_channel.id)})", guild=vc.guild)
else:
appendLog(f"Created nomic channel '{nomic_channel}' for channel '{created_channel}'", guild=vc.guild)
chan["nomic"] = nomic_channel.id
saveJson(chan, vc_file)
if loadJson("config.json")["enable_nomic"]:
nomic_channel = await vc.guild.create_text_channel(
getMsg("name_nomic", vc.guild).format(created_channel.id),
category=category,
overwrites=overwrites_nomic,
topic=getMsg("description_nomic", vc.guild).format(str(created_channel.id)),
)
if debug:
appendLog(
f"Created nomic channel '{nomic_channel}' ({str(nomic_channel.id)}) for channel '{created_channel}' ({str(created_channel.id)})",
guild=vc.guild,
)
else:
appendLog(
f"Created nomic channel '{nomic_channel}' for channel '{created_channel}'",
guild=vc.guild,
)
chan["nomic"] = nomic_channel.id
saveJson(chan, vc_file)
return created_channel
def isVoiceOfUser(vc, member):
global path
vc_file = f"{path}/guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
def isVoiceOfUser(vc: VoiceChannel, member: Member) -> bool:
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
vc_conf = loadJson(vc_file)
if vc_conf["ownerid"] == member.id:
return True
else:
return False
async def changeNomicPerms(mode, vc, member):
global path
vc_file = f"{path}/guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
vc_conf = loadJson(vc_file)
nomic_channel = discord.utils.get(vc.guild.channels, id=vc_conf["nomic"])
if mode == "deny":
await nomic_channel.set_permissions(member, view_channel=False)
else:
await nomic_channel.set_permissions(member, view_channel=True)
async def clearTrash(client):
global path
if not os.path.isdir(f"{path}/guilds/"):
os.mkdir(f"{path}/guilds")
guilds_list = os.listdir(f"{path}/guilds/")
async def changeNomicPerms(
mode: Literal["deny", "allow"], vc: VoiceChannel, member: Member
) -> None:
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
vc_conf = loadJson(vc_file)
if loadJson("config.json")["enable_nomic"]:
nomic_channel = utils.get(vc.guild.channels, id=vc_conf["nomic"])
if mode == "deny":
await nomic_channel.set_permissions(member, view_channel=False)
else:
await nomic_channel.set_permissions(member, view_channel=True)
async def clearTrash(client: Client):
if not path.isdir(f"guilds/"):
makedirs(f"guilds", exist_ok=True)
guilds_list = listdir(f"guilds/")
for guild in guilds_list:
guild_object = client.get_guild(int(guild))
if os.path.isdir(f"{path}/guilds/{guild}/channels"):
channels_list = os.listdir(f"{path}/guilds/{guild}/channels/")
if path.isdir(f"guilds/{guild}/channels"):
channels_list = listdir(f"guilds/{guild}/channels/")
for channel in channels_list:
channel_id = channel[:-5]
try:
selected_channel = discord.utils.get(guild_object.voice_channels, id=int(channel_id))
channel_owner = loadJson(f"{path}/guilds/{guild}/channels/{channel}")["ownerid"]
selected_channel = utils.get(
guild_object.voice_channels, id=int(channel_id)
)
channel_owner = loadJson(f"guilds/{guild}/channels/{channel}")[
"ownerid"
]
remove_channel = True
for member in selected_channel.members:
if member.id == channel_owner:
@ -305,79 +409,101 @@ async def clearTrash(client):
if remove_channel:
await removeUserVoice(selected_channel)
except:
os.remove(f"{path}/guilds/{guild}/channels/{channel_id}.json")
remove(f"guilds/{guild}/channels/{channel_id}.json")
#async def autoClearTrash(client):
# execute clearTrash every 120 seconds
def getHelpMessage(message, version, prefix=loadJson("config.json")["bot_prefix"]):
#channelExists(number, guild, type="Voice")
# async def autoClearTrash(client):
# execute clearTrash every 120 seconds
def getHelpMessage(ctx: ApplicationContext, version: float) -> Embed:
# channelExists(number, guild, type="Voice")
config = loadJson("config.json")
if message.guild is not None:
if channelExists(guildConfGet(message.guild, 'channel'), message.guild, type="Voice"):
desc_channel = getMsg("help_channel_set", guild=message.guild).format(channelGetName(guildConfGet(message.guild, 'channel'), message.guild))
else:
desc_channel = getMsg("help_channel_none", guild=message.guild)
if channelExists(guildConfGet(message.guild, 'category'), message.guild, type="Any"):
desc_category = getMsg("help_category_set", guild=message.guild).format(channelGetName(guildConfGet(message.guild, 'category'), message.guild))
else:
desc_category = getMsg("help_category_none", guild=message.guild)
desc_prefix = getMsg("help_prefix", guild=message.guild).format(prefix)
desc_locale = getMsg("help_locale", guild=message.guild).format(getMsg("locale_name", message.guild))
description = "\n".join([desc_prefix, desc_locale, desc_channel, desc_category])
if ctx.guild is not None:
if channelExists(guildConfGet(ctx.guild, "channel"), ctx.guild, type="Voice"):
desc_channel = getMsg("help_channel_set", guild=ctx.guild).format(
channelGetName(guildConfGet(ctx.guild, "channel"), ctx.guild)
)
else:
desc_channel = getMsg("help_channel_none", guild=ctx.guild)
embed=discord.Embed(title=getMsg("help_title", message.guild), description=description, color=strToColor(config["color_default"]))
if channelExists(guildConfGet(ctx.guild, "category"), ctx.guild, type="Any"):
desc_category = getMsg("help_category_set", guild=ctx.guild).format(
channelGetName(guildConfGet(ctx.guild, "category"), ctx.guild)
)
else:
desc_category = getMsg("help_category_none", guild=ctx.guild)
desc_locale = getMsg("help_locale", guild=ctx.guild).format(
getMsg("locale_name", ctx.guild)
)
description = "\n".join([desc_locale, desc_channel, desc_category])
embed = Embed(
title=getMsg("help_title", ctx.guild),
description=description,
color=strToColor(config["color_default"]),
)
else:
embed=discord.Embed(title=getMsg("help_title_dm", message.guild), color=strToColor(config["color_default"]))
embed.set_author(name=f'{config["bot_name"]} v{str(version)}', url=config["bot_site"], icon_url=config["bot_icon"])
if message.author.id == config["owner"]:
embed.add_field(name=f"{prefix}shutdown", value=getMsg("help_cmd_shutdown", message.guild), inline=False)
embed.add_field(name=f"{prefix}channel ID", value=getMsg("help_cmd_channel", message.guild), inline=False)
embed.add_field(name=f"{prefix}category ID", value=getMsg("help_cmd_category", message.guild), inline=False)
embed.add_field(name=f"{prefix}prefix SYMBOL", value=getMsg("help_cmd_prefix", message.guild), inline=False)
embed.add_field(name=f"{prefix}locale LOCALE", value=getMsg("help_cmd_locale", message.guild), inline=False)
if message.guild is None:
embed.set_footer(text=getMsg("help_server", message.guild))
embed = Embed(
title=getMsg("help_title_dm", ctx.guild),
color=strToColor(config["color_default"]),
)
embed.set_author(
name=f'{config["bot_name"]} v{str(version)}',
url=config["bot_site"],
icon_url=config["bot_icon"],
)
if ctx.author.id == config["owner"]:
embed.add_field(
name=f"/shutdown",
value=getMsg("help_cmd_shutdown", ctx.guild),
inline=False,
)
embed.add_field(
name=f"/channel set", value=getMsg("help_cmd_channel", ctx.guild), inline=False
)
embed.add_field(
name=f"/category set",
value=getMsg("help_cmd_category", ctx.guild),
inline=False,
)
embed.add_field(
name=f"/locale set", value=getMsg("help_cmd_locale", ctx.guild), inline=False
)
if ctx.guild is None:
embed.set_footer(text=getMsg("help_server", ctx.guild))
else:
embed.set_footer(text=getMsg("help_notice_id", message.guild))
embed.set_footer(text=getMsg("help_notice_id", ctx.guild))
return embed
async def guildConfigured(guild):
async def guildConfigured(guild: Guild) -> str:
output = {}
config = loadJson("config.json")
for kind in ["channel", "category", "prefix"]:
for kind in ["channel", "category"]:
if guildConfGet(guild, kind) is not None:
try:
if kind == "channel":
guild_object = discord.utils.get(guild.channels, id=guildConfGet(guild, kind))
output[kind] = getMsg("configured_"+kind, guild).format(guild_object.name)
elif kind == "category":
guild_object = discord.utils.get(guild.categories, id=guildConfGet(guild, kind))
output[kind] = getMsg("configured_"+kind, guild).format(guild_object.name)
elif kind == "prefix":
output[kind] = getMsg("info_prefix", guild).format(guildConfGet(guild, kind))
guild_object = utils.get(guild.categories, id=guildConfGet(guild, kind))
output[kind] = getMsg("configured_" + kind, guild).format(
guild_object.name
)
except Exception as exp:
if kind == "prefix":
output[kind] = getMsg("info_prefix", guild).format(config["bot_prefix"])
else:
output[kind] = getMsg("unconfigured_"+kind, guild)
output[kind] = getMsg("unconfigured_" + kind, guild)
else:
if kind == "prefix":
output[kind] = getMsg("info_prefix", guild).format(config["bot_prefix"])
else:
output[kind] = getMsg("unconfigured_"+kind, guild)
output[kind] = getMsg("unconfigured_" + kind, guild)
return getMsg("server_config", guild).format(output["prefix"], getMsg("info_locale", guild).format(getMsg("locale_name", guild)), output["channel"], output["category"])
return getMsg("server_config", guild).format(
getMsg("info_locale", guild).format(getMsg("locale_name", guild)),
output["channel"],
output["category"],
)

View File

@ -9,40 +9,31 @@
"set_channel_description": "Voice channel `{0}` has been set as a parent.",
"set_category_title": "☑ Parent category set",
"set_category_description": "Category `{0}` has been set as the parent category.",
"set_prefix_title": "☑ Command prefix set",
"set_prefix_description": "On this server, all commands are now prefixed with `{0}`",
"set_locale_title": "☑ Bot language set",
"set_locale_description": "This server is now using `{0}`",
"reset_channel_title": "☑ Parent channel reset",
"reset_channel_description": "Use `{0}channel CHANNELID` to select a new channel",
"reset_channel_description": "Use `/channel set` to select a new channel",
"reset_category_title": "☑ Parent category reset",
"reset_category_description": "Use `{0}category ID-CATEGORY` to select a new category",
"reset_prefix_title": "☑ Command Prefix Reset",
"reset_prefix_description": "The default prefix `{0}` is now used.\nUse `{1}prefix CHAR` to select a new one",
"reset_category_description": "Use `/category set` to select a new category",
"reset_locale_title": "☑ Bot language reset",
"reset_locale_description": "The default locale `{0}` is now used.\nUse `{1}locale LANGUAGE` to select a different one",
"reset_locale_description": "The default locale `{0}` is now used.\nUse `/locale set` to select a different one",
"error_channel_title": "🚫 Error installing channel",
"error_channel_description": "Correct Usage: `{0}channel CHANNELID`",
"error_channel_description": "Correct Usage: `/channel set`",
"error_category_title": "🚫 Error setting category",
"error_category_description": "Correct Usage: `{0}category CATEGORY-ID`",
"error_prefix_title": "🚫 Error setting prefix",
"error_prefix_description": "Correct Usage: `{0}prefix SYMBOL`",
"error_category_description": "Correct Usage: `/category set`",
"error_locale_title": "🚫 Error installing language",
"error_locale_description": "Correct Usage: `{0}locale LANGUAGE`\nAvailable languages: {1}",
"error_locale_description": "Correct Usage: `/locale set`\nAvailable languages: {1}",
"hint_none_channel_title": "⚠ No parent channel set",
"hint_none_channel_description": "For the bot to work properly, you need to set the parent channel, by entering which the user can create his own private voice channel. Set the parent channel with the command `{0}channel CHANNEL-ID`",
"hint_none_channel_description": "For the bot to work properly, you need to set the parent channel, by entering which the user can create his own private voice channel. Set the parent channel with the command `/channel set`",
"hint_none_category_title": "⚠ No parent category set",
"hint_none_category_description": "For the bot to work properly, you need to set a parent category, within which a private channel will be created for the user. Set the parent category with the command `{0}category ID-CATEGORY`",
"hint_none_prefix_title": "⚠ No prefix set",
"hint_none_prefix_description": "This server uses the default `{0}`.\nTo change it use `{1}prefix CHAR`",
"hint_none_category_description": "For the bot to work properly, you need to set a parent category, within which a private channel will be created for the user. Set the parent category with the command `/category set`",
"hint_none_locale_title": "⚠ Bot language not set",
"hint_none_locale_description": "This server uses default `{0}`.\nTo change it use `{1}locale LANGUAGE`",
"hint_none_locale_description": "This server uses default `{0}`.\nTo change it use `/locale set`",
"error_text_channel_title": "🚫 Error installing channel",
"error_text_channel_description": "The selected channel must be a voice channel.",
"help_title": "Server Information",
"help_title_dm": "Bot Commands",
"help_server": "Commands must be run on the server",
"help_prefix": " Command prefix: `{0}`",
"help_locale": " Server bot language: `{0}`",
"help_channel_set": "☑ Parent channel: `{0}`",
"help_channel_none": "⚠ Parent channel not installed",
@ -51,13 +42,14 @@
"help_cmd_shutdown": "Shut the bot down",
"help_cmd_channel": "Set parent channel\nMust be a voice channel",
"help_cmd_category": "Set parent category",
"help_cmd_prefix": "Set command prefix",
"help_cmd_locale": "Change bot language on server",
"help_notice_id": "Note that channel name ≠ channel ID",
"help_notice_id_category": "Note that category name ≠ category ID",
"forbidden_title": "🚫 Access Denied",
"forbidden_description": "You must have **Administrator** right to set up private channels",
"dm_title": "🚫 Execution error",
"dm_description": "Commands can only be executed while on the server"
"dm_description": "Commands can only be executed while on the server",
"admin_title": "🚫 Permission denied",
"admin_description": "You must be bot owner to perform this"
}
}

View File

@ -1,63 +0,0 @@
{
"messages": {
"shutdown": "**{0}** Выключаюсь...",
"locale_name": "Русский",
"name_voice": "Канал {0}",
"name_nomic": "без-микро-{0}",
"description_nomic": "Текстовый канал для коммуникации без микрофона\nID голосовой комнаты: {0}",
"set_channel_title": "☑ Родительский канал установлен",
"set_channel_description": "Голосовой канал `{0}` был установлен как родительский.",
"set_category_title": "☑ Родительская категория установлена",
"set_category_description": "Категория `{0}` была установлена как родительская.",
"set_prefix_title": "☑ Префикс команд установлен",
"set_prefix_description": "На этом сервере префикс всех команд теперь `{0}`",
"set_locale_title": "☑ Язык бота установлен",
"set_locale_description": "На этом сервере теперь используется `{0}`",
"reset_channel_title": "☑ Родительский канал сброшен",
"reset_channel_description": "Для выбора нового канала используйте `{0}channel ID-КАНАЛА`",
"reset_category_title": "☑ Родительская категория сброшена",
"reset_category_description": "Для выбора новой категории используйте `{0}category ID-КАТЕГОРИИ`",
"reset_prefix_title": "☑ Префикс команд сброшен",
"reset_prefix_description": "Теперь используется стандартный префикс `{0}`.\nДля выбора нового используйте `{1}prefix СИМВОЛ`",
"reset_locale_title": "☑ Язык бота сброшен",
"reset_locale_description": "Теперь используется стандартный язык `{0}`.\nДля выбора другого используйте `{1}locale ЯЗЫК`",
"error_channel_title": "🚫 Ошибка установки канала",
"error_channel_description": "Правильное использование: `{0}channel ID-КАНАЛА`",
"error_category_title": "🚫 Ошибка установки категории",
"error_category_description": "Правильное использование: `{0}category ID-КАТЕГОРИИ`",
"error_prefix_title": "🚫 Ошибка установки префикса",
"error_prefix_description": "Правильное использование: `{0}prefix СИМВОЛ`",
"error_locale_title": "🚫 Ошибка установки языка",
"error_locale_description": "Правильное использование: `{0}locale ЯЗЫК`\nДоступные языки: {1}",
"hint_none_channel_title": "⚠ Родительский канал не задан",
"hint_none_channel_description": "Для правильной работы бота необходимо задать родительский канал, входя в который пользователь сможет создать свой приватный голосовой канал. Установите родительский канал командой `{0}channel ID-КАНАЛА`",
"hint_none_category_title": "⚠ Родительская категория не задана",
"hint_none_category_description": "Для правильной работы бота необходимо задать родительскую категорию, внутри которой для пользователя будет создан его приватный канал. Установите родительскую категорию командой `{0}category ID-КАТЕГОРИИ`",
"hint_none_prefix_title": "⚠ Префикс не задан",
"hint_none_prefix_description": "На этом сервере используется стандартный `{0}`.\nЧтобы сменить его используйте `{1}prefix СИМВОЛ`",
"hint_none_locale_title": "⚠ Язык бота не задан",
"hint_none_locale_description": "На этом сервере используется стандартный `{0}`.\nЧтобы сменить его используйте `{1}locale ЯЗЫК`",
"error_text_channel_title": "🚫 Ошибка установки канала",
"error_text_channel_description": "Выбранный канал должен быть голосовым.",
"help_title": "Информация о сервере",
"help_title_dm": "Команды бота",
"help_server": "Команды должны выполняться на сервере",
"help_prefix": " Префикс команд: `{0}`",
"help_locale": " Язык бота на сервере: `{0}`",
"help_channel_set": "☑ Родительский канал: `{0}`",
"help_channel_none": "⚠ Родительский канал не установлен",
"help_category_set": "☑ Родительская категория: `{0}`",
"help_category_none": "⚠ Родительская категория не установлена",
"help_cmd_shutdown": "Выключить бота",
"help_cmd_channel": "Установить родительский канал\nКанал должен быть голосовым",
"help_cmd_category": "Установить родительскую категорию",
"help_cmd_prefix": "Установить префикс команд",
"help_cmd_locale": "Сменить язык бота на сервере",
"help_notice_id": "Обратите внимание, что имя канала ≠ ID канала",
"help_notice_id_category": "Обратите внимание, что имя категории ≠ ID категории",
"forbidden_title": "🚫 Отказано в доступе",
"forbidden_description": "Для настройки приватных каналов нужно иметь право **Администратор**",
"dm_title": "🚫 Ошибка исполнения",
"dm_description": "Команды можно исполнять только находясь на сервере"
}
}

View File

@ -4,60 +4,52 @@
"locale_name": "Українська",
"name_voice": "Канал {0}",
"name_nomic": "без-мікро-{0}",
"description_nomic": "Текстовий канал для комунікації без мікрофона\nID голосової кімнати: {0}",
"description_nomic": "Текстовий канал для комунікації без мікрофона\\nID голосової кімнати: {0}",
"set_channel_title": "☑ Твірний канал встановлено",
"set_channel_description": "Голосовий канал `{0}` був встановлений як твірний.",
"set_category_title": "☑ Твірну категорію встановлено",
"set_category_description": "Категорія `{0}` була встановлена ​​як твірна.",
"set_prefix_title": "☑ Префікс команд встановлено",
"set_prefix_description": "На цьому сервері префікс усіх команд тепер `{0}`",
"set_category_description": "Категорія `{0}` була встановлена як твірна.",
"set_locale_title": "☑ Мова бота встановлена",
"set_locale_description": "На цьому сервері тепер використовується `{0}`",
"reset_channel_title": "☑ Твірний канал скинутий",
"reset_channel_description": "Для вибору нового каналу використовуйте `{0}channel ID-КАНАЛу`",
"reset_category_title": "☑ Твірна категорія скинута",
"reset_category_description": "Для вибору нової категорії використовуйте `{0}category ID-КАТЕГОРІЇ`",
"reset_prefix_title": "☑ Префікс команд скинутий",
"reset_prefix_description": "Тепер використовується стандартний префікс `{0}`.\nДля вибору нового використовуйте `{1}prefix СИМВОЛ`",
"reset_channel_description": "Для вибору нового каналу використовуйте `/channel set`",
"reset_category_title": "☑ Твірну категорію скинуто",
"reset_category_description": "Використовуйте `/category set` для вибору нової категорії",
"reset_locale_title": "☑ Мова бота скинута",
"reset_locale_description": "Тепер використовується стандартна мова `{0}`.\nДля вибору іншого використовуйте `{1}locale МОВА`",
"error_channel_title": "🚫 Помилка установки каналу",
"error_channel_description": "Правильне використання: `{0}channel ID-КАНАЛу`",
"error_category_title": "🚫 Помилка установки категорії",
"error_category_description": "Правильне використання: `{0}category ID-КАТЕГОРІЇ`",
"error_prefix_title": "🚫 Помилка встановлення префіксу",
"error_prefix_description": "Правильне використання: `{0}prefix СИМВОЛ`",
"reset_locale_description": "Тепер використовується стандартна мова `{0}`.\\nДля вибору іншого використовуйте `/locale set`",
"error_channel_title": "🚫 Помилка встановлення каналу",
"error_channel_description": "Правильне використання: `/channel set`",
"error_category_title": "🚫 Помилка налаштування категорії",
"error_category_description": "Правильне використання: `/category set`",
"error_locale_title": "🚫 Помилка встановлення мови",
"error_locale_description": "Правильне використання: `{0}locale МОВА`\nДоступні мови: {1}",
"error_locale_description": "Правильне використання: `/locale set`\\nДоступні мови: {1}",
"hint_none_channel_title": "⚠ Твірний канал не заданий",
"hint_none_channel_description": "Для правильної роботи робота необхідно задати твірний канал, входячи в який користувач зможе створити свій приватний голосовий канал. Встановіть твірний канал командою `{0}channel ID-КАНАЛУ",
"hint_none_category_title": "⚠ Твірна категорія не задана",
"hint_none_category_description": "Для правильної роботи робота необхідно задати твірну категорію, всередині якої для користувача буде створено його приватний канал. Встановіть твірну категорію командою `{0}category ID-КАТЕГОРІЇ`",
"hint_none_prefix_title": "⚠ Префікс не заданий",
"hint_none_prefix_description": "На цьому сервері використовується стандартний `{0}`.\nЩоб змінити його використовуйте `{1}prefix СИМВОЛ`",
"hint_none_locale_title": "⚠ Мова бота не задана",
"hint_none_locale_description": "На цьому сервері використовується стандартний `{0}`.\nЩоб змінити його використовуйте `{1}locale МОВА`",
"error_text_channel_title": "🚫 Помилка установки каналу",
"error_text_channel_description": "Вибраний канал повинен бути голосовим.",
"hint_none_channel_description": "Для правильної роботи робота необхідно задати твірний канал, входячи в який користувач зможе створити свій приватний голосовий канал. Встановіть твірний канал командою `/channel set`",
"hint_none_category_title": "⚠ Твірна категорія не встановлена",
"hint_none_category_description": "Для правильної роботи робота необхідно задати твірну категорію, всередині якої для користувача буде створено його приватний канал. Встановіть твірну категорію командою `/category set`",
"hint_none_locale_title": "⚠ Мова бота не встановлена",
"hint_none_locale_description": "На цьому сервері використовується стандартний `{0}`.\\nЩоб змінити його використовуйте `/locale set`",
"error_text_channel_title": "🚫 Помилка встановлення каналу",
"error_text_channel_description": "Обраний канал має бути голосовим каналом.",
"help_title": "Інформація про сервер",
"help_title_dm": "Команда бота",
"help_server": "Команди повинні виконуватись на сервері",
"help_prefix": " Префікс команд: `{0}`",
"help_server": "Команди слід запускати на сервері",
"help_locale": " Мова бота на сервері: `{0}`",
"help_channel_set": "☑ Твірний канал: `{0}`",
"help_channel_none": "⚠ Твірний канал не встановлено",
"help_category_set": "☑ Твірна категорія: `{0}`",
"help_category_none": "⚠ Твірна категорія не встановлена",
"help_cmd_shutdown": "Вимкнути бота",
"help_cmd_channel": "Встановити твірний канал\nКанал повинен бути голосовим",
"help_cmd_channel": "Встановити твірний канал\\nКанал повинен бути голосовим",
"help_cmd_category": "Встановити твірну категорію",
"help_cmd_prefix": "Встановити префікс команд",
"help_cmd_locale": "Змінити мову бота на сервері",
"help_notice_id": "Зверніть увагу, що ім'я каналу ≠ ID каналу",
"help_notice_id_category": "Зверніть увагу, що ім'я категорії ≠ ID категорії",
"forbidden_title": "🚫 Відмовлено у доступі",
"forbidden_title": "🚫 Немає прав доступу",
"forbidden_description": "Для налаштування приватних каналів потрібно мати право **Адміністратор**",
"dm_title": "🚫 Помилка виконання",
"dm_description": "Команди можна виконувати лише перебуваючи на сервері"
"dm_description": "Команди можна виконувати лише перебуваючи на сервері",
"admin_title": "🚫 Немає прав доступу",
"admin_description": "Треба бути адміністратором бота щоб зробити це"
}
}

View File

@ -0,0 +1,2 @@
ujson==5.9.0
py-cord[speed]==2.5.0

View File

@ -1 +1,2 @@
discord.py
py-cord==2.5.0
requests==2.31.0

View File

@ -1,356 +1,75 @@
import os
import sys
import json
import shutil
import requests
import threading
try:
import discord
from discord import Activity, ActivityType, ApplicationContext, Bot, Intents
from requests import get
except Exception as exp:
print(f"Module discord.py is not installed. Make sure to run 'pip install -r requirements.txt' before first start")
sys.exit()
print(
f"Dependencies not installed. Make sure to run 'pip install -r requirements.txt' before first start"
)
exit()
from os import getpid, path
from functions import *
pid = os.getpid()
version = 1.4
if loadJson("config.json")["owner"] == "SET-OWNER-ID" or loadJson("config.json")["bot_token"] == "SET-BOT-TOKEN":
print(f"Bot is not correctly configured.\nMake sure you've set up owner id and bot token in {path}/config.json\nLearn more here: https://github.com/profitrollgame/YusarinBot")
sys.exit()
pid = getpid()
version = 2.3
if (
not path.exists("config.json")
or loadJson("config.json")["owner"] == "SET-OWNER-ID"
or loadJson("config.json")["bot_token"] == "SET-BOT-TOKEN"
):
print(
f"Bot is not correctly configured.\nMake sure you've set up owner id and bot token in 'config.json'\nLearn more here: https://git.end-play.xyz/profitroll/YusarinBot"
)
exit()
if loadJson("config.json")["check_for_updates"]:
appendLog(f"Currently using YusarinBot v{str(version)}")
try:
serv_ver = requests.get("https://www.end-play.xyz/yusarin/version.txt").text.replace('\n', '')
if float(serv_ver) > version:
appendLog(f"YusarinBot version {serv_ver} is available. Download new version here: https://github.com/profitrollgame/YusarinBot/releases/latest")
appendLog(f"Currently using YusarinBot v{str(version)}")
releases = get(
"https://git.end-play.xyz/api/v1/repos/profitroll/YusarinBot/releases?draft=false&pre-release=false&page=1&limit=1"
).json()
if float(releases[0]["tag_name"].replace("v", "")) > version:
appendLog(
f"YusarinBot version {releases[0]['tag_name']} is available. Download new version here: {releases[0]['html_url']}"
)
except Exception as exp:
appendLog(f"Could not get YusarinBot cloud version due to {exp}. Currently using {str(version)}")
appendLog(
f"Could not get YusarinBot cloud version due to {exp}. Currently using {str(version)}"
)
intents = Intents().all()
client = Bot(intents=intents)
from cogs.cogCategory import CogCategory
from cogs.cogChannel import CogChannel
from cogs.cogLocale import CogLocale
from cogs.cogUtility import CogUtility
@client.slash_command(name="help", description="Get information about this server")
async def help(ctx: ApplicationContext):
await ctx.respond(embed=getHelpMessage(ctx, version))
intents = discord.Intents().all()
client = discord.Client(intents=intents)
@client.event
async def on_ready():
appendLog(f"Logged in as {client.user}")
config = loadJson("config.json")
await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=config["bot_activity"]))
await client.change_presence(
activity=Activity(type=ActivityType.listening, name=config["bot_activity"])
)
await clearTrash(client)
@client.event
async def on_guild_join(guild):
global path
os.mkdir(f"{path}/guilds/{str(guild.id)}")
os.mkdir(f"{path}/guilds/{str(guild.id)}/channels")
saveJson({}, f"{path}/guilds/{str(guild.id)}/config.json")
appendLog(f"Joined guild '{guild}' with id {str(guild.id)}")
@client.event
async def on_guild_remove(guild):
global path
try:
shutil.rmtree(f"{path}/guilds/{str(guild.id)}")
except:
pass
appendLog(f"Left guild '{guild}' with id {str(guild.id)}")
@client.event
async def on_voice_state_update(member, before, after):
global debug
config = loadJson("config.json")
vc_from = before.channel
vc_to = after.channel
# If user left vc
if vc_to is None:
if isUserVoice(vc_from):
if isVoiceOfUser(vc_from, member):
await removeUserVoice(vc_from)
return
else:
await changeNomicPerms("deny", vc_from, member)
# If user joined vc
else:
if isUserVoice(vc_from):
if isVoiceOfUser(vc_from, member):
await removeUserVoice(vc_from)
else:
await changeNomicPerms("deny", vc_from, member)
if isUserVoice(vc_to):
await changeNomicPerms("allow", vc_to, member)
if vc_to.id == guildConfGet(vc_to.guild, "channel"):
if guildConfGet(vc_to.guild, "category") is not None:
voice_chan = await createUserVoice(vc_to, discord.utils.get(vc_to.guild.categories, id=guildConfGet(vc_to.guild, "category")), member)
try:
await member.move_to(voice_chan)
except:
await removeUserVoice(voice_chan)
else:
if debug:
appendLog(f"Category for guild {vc_to.guild} ({str(vc_to.guild.id)}) is not set", guild=vc_to.guild)
else:
appendLog(f"Category for guild {vc_to.guild} is not set", guild=vc_to.guild)
# ==========================================================================================
@client.event
async def on_message(message):
config = loadJson("config.json")
if message.guild is not None:
try:
prefix = guildConfGet(message.guild, "prefix")
if prefix is None:
prefix = config["bot_prefix"]
except Exception as exp:
print(exp)
prefix = config["bot_prefix"]
else:
prefix = config["bot_prefix"]
if message.author == client.user:
return
if message.content in [f"{prefix}reboot", f"{prefix}restart", f"{prefix}shutdown", f"{prefix}die"]:
gotCommand(message)
if message.author.id == config["owner"]:
await message.reply(embed=makeEmbed(description=getMsg("shutdown", message.guild).format(message.author), color=strToColor(config["color_default"])), mention_author=False)
os.system(f"kill -9 {str(pid)}")
else:
return
elif message.content.startswith(f"{prefix}channel"):
gotCommand(message)
fullcmd = message.content.split()
if message.guild is not None:
if message.author.guild_permissions.administrator:
try:
if fullcmd[1] == "reset":
if guildConfGet(message.guild, "channel") is not None:
guildConfReset(message.guild, "channel")
await message.reply(embed=makeEmbed(title=getMsg("reset_channel_title", message.guild), description=getMsg("reset_channel_description", message.guild).format(prefix), color=strToColor(config["color_ok"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("hint_none_channel_title", message.guild), description=getMsg("hint_none_channel_description", message.guild).format(prefix), color=strToColor(config["color_warn"])), mention_author=False)
else:
selected_channel = discord.utils.get(message.guild.channels, id=int(fullcmd[1]))
if isinstance(selected_channel, discord.VoiceChannel):
guildConfSet(message.guild, "channel", int(fullcmd[1]))
await message.reply(embed=makeEmbed(title=getMsg("set_channel_title", message.guild), description=getMsg("set_channel_description", message.guild).format(selected_channel.name), color=strToColor(config["color_ok"])), mention_author=False)
if guildConfGet(message.guild, "category") is None:
await message.channel.send(embed=makeEmbed(title=getMsg("hint_none_category_title", message.guild), description=getMsg("hint_none_category_description", message.guild).format(prefix), color=strToColor(config["color_warn"])))
else:
await message.reply(embed=makeEmbed(title=getMsg("error_text_channel_title", message.guild), description=getMsg("error_text_channel_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
except Exception as exp:
if debug:
print(exp)
await message.reply(embed=makeEmbed(title=getMsg("error_channel_title", message.guild), description=getMsg("error_channel_description", message.guild).format(prefix), footer=getMsg("help_notice_id", message.guild), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("forbidden_title", message.guild), description=getMsg("forbidden_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("dm_title", message.guild), description=getMsg("dm_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
elif message.content.startswith(f"{prefix}category"):
gotCommand(message)
fullcmd = message.content.split()
if message.guild is not None:
if message.author.guild_permissions.administrator:
try:
if fullcmd[1] == "reset":
if guildConfGet(message.guild, "category") is not None:
guildConfReset(message.guild, "category")
await message.reply(embed=makeEmbed(title=getMsg("reset_category_title", message.guild), description=getMsg("reset_category_description", message.guild).format(prefix), color=strToColor(config["color_ok"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("hint_none_category_title", message.guild), description=getMsg("hint_none_category_description", message.guild).format(prefix), color=strToColor(config["color_warn"])), mention_author=False)
else:
selected_category = discord.utils.get(message.guild.channels, id=int(fullcmd[1]))
guildConfSet(message.guild, "category", int(fullcmd[1]))
await message.reply(embed=makeEmbed(title=getMsg("set_category_title", message.guild), description=getMsg("set_category_description", message.guild).format(selected_category.name), color=strToColor(config["color_ok"])), mention_author=False)
if guildConfGet(message.guild, "channel") is None:
await message.channel.send(embed=makeEmbed(title=getMsg("hint_none_channel_title", message.guild), description=getMsg("hint_none_channel_description", message.guild).format(prefix), color=strToColor(config["color_warn"])))
except Exception as exp:
if debug:
print(exp)
await message.reply(embed=makeEmbed(title=getMsg("error_category_title", message.guild), description=getMsg("error_category_description", message.guild).format(prefix), footer=getMsg("help_notice_id_category", message.guild), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("forbidden_title", message.guild), description=getMsg("forbidden_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("dm_title", message.guild), description=getMsg("dm_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
elif message.content.startswith(f"{prefix}prefix"):
gotCommand(message)
fullcmd = message.content.split()
if message.guild is not None:
if message.author.guild_permissions.administrator:
try:
if fullcmd[1] == "reset":
if guildConfGet(message.guild, "prefix") is not None:
guildConfReset(message.guild, "prefix")
await message.reply(embed=makeEmbed(title=getMsg("reset_prefix_title", message.guild), description=getMsg("reset_prefix_description", message.guild).format(config["bot_prefix"], config["bot_prefix"]), color=strToColor(config["color_ok"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("hint_none_prefix_title", message.guild), description=getMsg("hint_none_prefix_description", message.guild).format(prefix, prefix), color=strToColor(config["color_warn"])), mention_author=False)
else:
guildConfSet(message.guild, "prefix", fullcmd[1])
await message.reply(embed=makeEmbed(title=getMsg("set_prefix_title", message.guild), description=getMsg("set_prefix_description", message.guild).format(fullcmd[1]), color=strToColor(config["color_ok"])), mention_author=False)
except:
await message.reply(embed=makeEmbed(title=getMsg("error_prefix_title", message.guild), description=getMsg("error_prefix_description", message.guild).format(prefix), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("forbidden_title", message.guild), description=getMsg("forbidden_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("dm_title", message.guild), description=getMsg("dm_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
elif message.content.startswith(f"{prefix}locale"):
gotCommand(message)
fullcmd = message.content.split()
if message.guild is not None:
if message.author.guild_permissions.administrator:
try:
if fullcmd[1] == "reset":
if guildConfGet(message.guild, "locale") is not None:
guildConfReset(message.guild, "locale")
appendLog(f"Server's locale has been reset", message.guild)
await message.reply(embed=makeEmbed(title=getMsg("reset_locale_title", message.guild), description=getMsg("reset_locale_description", message.guild).format(getMsg("locale_name", message.guild), prefix), color=strToColor(config["color_ok"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("hint_none_locale_title", message.guild), description=getMsg("hint_none_locale_description", message.guild).format(getMsg("locale_name", message.guild), prefix), color=strToColor(config["color_warn"])), mention_author=False)
else:
for locale_file in os.listdir(f"{path}/locale/"):
if locale_file[:-5] == fullcmd[1]:
guildConfSet(message.guild, "locale", fullcmd[1])
appendLog(f"Server's locale is now set to {fullcmd[1]}", message.guild)
await message.reply(embed=makeEmbed(title=getMsg("set_locale_title", message.guild), description=getMsg("set_locale_description", message.guild).format(getMsg("locale_name", message.guild)), color=strToColor(config["color_ok"])), mention_author=False)
return
locales = []
for locale_file in os.listdir(f"{path}/locale/"):
locales.append(f"`{locale_file[:-5]}`")
await message.reply(embed=makeEmbed(title=getMsg("error_locale_title", message.guild), description=getMsg("error_locale_description", message.guild).format(prefix, ", ".join(locales)), color=strToColor(config["color_error"])), mention_author=False)
except:
locales = []
for locale_file in os.listdir(f"{path}/locale/"):
locales.append(f"`{locale_file[:-5]}`")
await message.reply(embed=makeEmbed(title=getMsg("error_locale_title", message.guild), description=getMsg("error_locale_description", message.guild).format(prefix, ", ".join(locales)), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("forbidden_title", message.guild), description=getMsg("forbidden_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
else:
await message.reply(embed=makeEmbed(title=getMsg("dm_title", message.guild), description=getMsg("dm_description", message.guild), color=strToColor(config["color_error"])), mention_author=False)
elif message.content.startswith(f"{prefix}help"):
gotCommand(message)
await message.reply(embed=getHelpMessage(message, version, prefix=prefix), mention_author=False)
#if loadJson("config.json")["auto_clear_trash"]:
# run func
client.add_cog(CogCategory(client))
client.add_cog(CogChannel(client))
client.add_cog(CogLocale(client))
client.add_cog(CogUtility(client))
appendLog(f"Trying to log in...")
client.run(loadJson("config.json")["bot_token"])