Compare commits
No commits in common. "main" and "v1.1" have entirely different histories.
173
.gitignore
vendored
173
.gitignore
vendored
@ -1,173 +0,0 @@
|
||||
# ---> 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
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
}
|
70
README.md
70
README.md
@ -1,77 +1,41 @@
|
||||
<h1 align="center">YusarinBot</h1>
|
||||
# YusarinBot
|
||||
|
||||
<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.
|
||||
Simple, clear, easy, reliable.
|
||||
A specially designed bot for creating private voice channels at your 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://git.end-play.xyz/profitroll/YusarinBot`
|
||||
1. `git clone https://github.com/profitrollgame/YusarinBot`
|
||||
2. `cd YusarinBot`
|
||||
3. `pip install -r requirements.txt`
|
||||
4. `cp config_example.json config.json`
|
||||
5. `nano config.json`
|
||||
6. `python yusarin.py`
|
||||
4. `nano config.json`
|
||||
5. `python yusarin.py`
|
||||
|
||||
## Installation (Detailed)
|
||||
|
||||
1. Download and install Python 3.8+
|
||||
2. Download bot's release: <https://git.end-play.xyz/profitroll/YusarinBot/releases/latest>
|
||||
1. Download and install Python 3 (3.6+ should be fine)
|
||||
2. Download bot's release: https://github.com/profitrollgame/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. 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`
|
||||
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`
|
||||
|
||||
## Config explanation
|
||||
|
||||
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]
|
||||
- "bot_token" - Token of your Discord bot [String]
|
||||
- "bot_prefix" - Default prefix for all bot commands [String]
|
||||
- "bot_locale" - Default language file of bot. Name of file in `locale` folder without extension is used [String]
|
||||
- "bot_activity" - The name (string) of the song bot will be listening to [String]
|
||||
- "color_default" - HTML color used in help messages embed [String]
|
||||
- "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]
|
||||
- "auto_clear_trash" - Option that defines whether bot should clean all buggy inactive channels every "auto_clear_timer" seconds [Boolean]
|
||||
- "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://www.end-play.xyz/yusarin/invite>
|
||||
3. If you have questions/suggestions - just join our [Discord Support Server](https://discord.com/invite/2zpzErtnNT)
|
||||
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
|
||||
|
@ -1,91 +0,0 @@
|
||||
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"]),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# =========================================================================================================================
|
@ -1,155 +0,0 @@
|
||||
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"]),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# =========================================================================================================================
|
@ -1,105 +0,0 @@
|
||||
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"]),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# =========================================================================================================================
|
@ -1,53 +0,0 @@
|
||||
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"]),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# =========================================================================================================================
|
11
config.json
Normal file
11
config.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"owner": SET-OWNER-ID,
|
||||
"bot_name": "Yusa Nishimori",
|
||||
"bot_token": "SET-BOT-TOKEN",
|
||||
"bot_prefix": "$",
|
||||
"bot_locale": "en",
|
||||
"bot_activity": "How-Low-Hello - Keep on Burnin'",
|
||||
"check_for_updates": true,
|
||||
"auto_clear_trash": false,
|
||||
"auto_clear_timer": 120
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"debug": false,
|
||||
"owner": "SET-OWNER-ID",
|
||||
"bot_name": "Yusa Nishimori",
|
||||
"bot_token": "SET-BOT-TOKEN",
|
||||
"bot_prefix": "$",
|
||||
"bot_locale": "en",
|
||||
"bot_activity": "How-Low-Hello - Keep on Burnin'",
|
||||
"color_default": "#F2C48D",
|
||||
"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,
|
||||
"auto_clear_trash": false,
|
||||
"auto_clear_timer": 120
|
||||
}
|
512
functions.py
512
functions.py
@ -1,174 +1,102 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import discord
|
||||
|
||||
from datetime import datetime
|
||||
from gzip import open as gzipopen
|
||||
from os import listdir, makedirs, path, remove, stat
|
||||
from shutil import copyfileobj
|
||||
from typing import Any, Literal, Union
|
||||
from pathlib import Path
|
||||
|
||||
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
|
||||
path = Path(__file__).resolve().parent
|
||||
|
||||
log_size = 512
|
||||
|
||||
# This is the default option for "debug" key in
|
||||
# file config.json, so if cebug is not set in it
|
||||
# bot will use this value instead.
|
||||
debug = False
|
||||
|
||||
try:
|
||||
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():
|
||||
try:
|
||||
if not path.isdir("logs"):
|
||||
makedirs("logs", exist_ok=True)
|
||||
global path
|
||||
path = str(path)
|
||||
|
||||
log = stat("logs/latest.log")
|
||||
try:
|
||||
if not os.path.isdir(f"{path}/logs"):
|
||||
os.mkdir(f"{path}/logs")
|
||||
|
||||
log = os.stat(path + '/logs/latest.log')
|
||||
global log_size
|
||||
|
||||
if (log.st_size / 1024) > log_size:
|
||||
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()
|
||||
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()
|
||||
except FileNotFoundError:
|
||||
print("Not found")
|
||||
print('Not found')
|
||||
pass
|
||||
|
||||
|
||||
# Append string to log
|
||||
def appendLog(message: str, guild: Union[Guild, None] = None, announce=True) -> None:
|
||||
global debug
|
||||
def appendLog(message, guild="none"):
|
||||
global path
|
||||
|
||||
if guild == None:
|
||||
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] {message}'
|
||||
else:
|
||||
if debug:
|
||||
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}'
|
||||
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] [{str(guild)}] {message}'
|
||||
|
||||
if announce:
|
||||
print(message_formatted, flush=True)
|
||||
print(message_formatted)
|
||||
|
||||
checkSize()
|
||||
|
||||
log = open("logs/latest.log", "a") # type: ignore
|
||||
log.write(f"{message_formatted}\n")
|
||||
log = open(path + '/logs/latest.log', 'a')
|
||||
log.write(f'{message_formatted}\n')
|
||||
log.close()
|
||||
|
||||
|
||||
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))
|
||||
def saveJson(value, filename):
|
||||
with open(filename, 'w', encoding="utf-8") as f:
|
||||
json.dump(value, f, indent=4, ensure_ascii=False)
|
||||
f.close()
|
||||
|
||||
|
||||
def loadJson(filename: str) -> Any:
|
||||
global debug
|
||||
def loadJson(filename):
|
||||
try:
|
||||
with open(filename, "r", encoding="utf-8") as json_file:
|
||||
output = loads(json_file.read())
|
||||
with open(filename, 'r', encoding="utf-8") as json_file:
|
||||
output = json.load(json_file)
|
||||
json_file.close()
|
||||
except Exception as exp:
|
||||
if debug:
|
||||
appendLog(f"Could not load json file {filename} due to exception {exp}")
|
||||
appendLog(f"Could not get contents of json file {filename} due to exception {exp}")
|
||||
output = {}
|
||||
return output
|
||||
|
||||
|
||||
def colorToStr():
|
||||
pass
|
||||
|
||||
|
||||
def strToColor(string: str) -> int:
|
||||
return int(hex(int(string.replace("#", ""), 16)), 0)
|
||||
|
||||
|
||||
def gotCommand(message: Message) -> None:
|
||||
global debug
|
||||
if debug:
|
||||
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: Guild, variable: str) -> Any:
|
||||
global debug
|
||||
def guildConfGet(guild, variable):
|
||||
global path
|
||||
config = loadJson(f"{path}/guilds/{str(guild)}/config.json")
|
||||
try:
|
||||
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
|
||||
)
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def guildConfSet(guild: Guild, variable: str, value: Any) -> None:
|
||||
config = loadJson(f"guilds/{str(guild.id)}/config.json")
|
||||
def guildConfSet(guild, variable, value):
|
||||
global path
|
||||
config = loadJson(f"{path}/guilds/{str(guild)}/config.json")
|
||||
config[variable] = value
|
||||
try:
|
||||
saveJson(config, f"guilds/{str(guild.id)}/config.json")
|
||||
saveJson(config, f"{path}/guilds/{str(guild)}/config.json")
|
||||
except:
|
||||
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)
|
||||
os.mkdir(f"{path}/guilds/{str(guild)}")
|
||||
os.mkdir(f"{path}/guilds/{str(guild)}/channels")
|
||||
saveJson(config, f"{path}/guilds/{str(guild)}/config.json")
|
||||
|
||||
|
||||
def guildConfReset(guild: Guild, variable: str) -> None:
|
||||
try:
|
||||
config = loadJson(f"guilds/{str(guild.id)}/config.json")
|
||||
def guildConfReset(guild, variable):
|
||||
global path
|
||||
config = loadJson(f"{path}/guilds/{str(guild)}/config.json")
|
||||
del config[variable]
|
||||
try:
|
||||
saveJson(config, f"guilds/{str(guild.id)}/config.json")
|
||||
saveJson(config, f"{path}/guilds/{str(guild)}/config.json")
|
||||
except:
|
||||
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)
|
||||
os.mkdir(f"{path}/guilds/{str(guild)}")
|
||||
os.mkdir(f"{path}/guilds/{str(guild)}/channels")
|
||||
saveJson(config, f"{path}/guilds/{str(guild)}/config.json")
|
||||
|
||||
|
||||
def guildLocaleGet(guild: Guild) -> str:
|
||||
config = loadJson(f"config.json")
|
||||
def guildLocaleGet(guild):
|
||||
global path
|
||||
config = loadJson(f"{path}/config.json")
|
||||
try:
|
||||
locale = guildConfGet(guild, "locale")
|
||||
locale = guildConfGet(guild.id, "locale")
|
||||
except:
|
||||
return config["bot_locale"]
|
||||
if locale is None:
|
||||
@ -176,63 +104,20 @@ def guildLocaleGet(guild: Guild) -> str:
|
||||
else:
|
||||
return locale
|
||||
|
||||
|
||||
def getMsg(string: str, guild: Union[Guild, None] = None) -> str:
|
||||
def getMsg(string, guild):
|
||||
global path
|
||||
config = loadJson("config.json")
|
||||
try:
|
||||
locale = loadJson(f"locale/{guildLocaleGet(guild)}.json")
|
||||
locale = loadJson(f'{path}/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
|
||||
)
|
||||
return string
|
||||
appendLog(f"Could not get locale string named {string} due to exception {exp}")
|
||||
return f"Could not get locale string {string}"
|
||||
|
||||
|
||||
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: int, guild: Guild, type: Literal["Any", "Text", "Voice"] = "Any"
|
||||
) -> bool:
|
||||
global debug
|
||||
if number == None:
|
||||
return False
|
||||
def isUserVoice(vc):
|
||||
global path
|
||||
try:
|
||||
if type == "Voice":
|
||||
selected_channel = utils.get(guild.channels, id=number)
|
||||
if isinstance(selected_channel, VoiceChannel):
|
||||
return True
|
||||
elif type == "Text":
|
||||
selected_channel = utils.get(guild.channels, id=number)
|
||||
if isinstance(selected_channel, TextChannel):
|
||||
return True
|
||||
elif type == "Any":
|
||||
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: int, guild: Guild):
|
||||
global debug
|
||||
try:
|
||||
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: VoiceChannel) -> bool:
|
||||
try:
|
||||
channels_list = listdir(f"guilds/{str(vc.guild.id)}/channels/")
|
||||
channels_list = os.listdir(f"{path}/guilds/{str(vc.guild.id)}/channels/")
|
||||
if f"{str(vc.id)}.json" in channels_list:
|
||||
return True
|
||||
else:
|
||||
@ -240,168 +125,84 @@ def isUserVoice(vc: VoiceChannel) -> bool:
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
async def removeUserVoice(vc: VoiceChannel) -> None:
|
||||
global debug
|
||||
channels_list = listdir(f"guilds/{str(vc.guild.id)}/channels/")
|
||||
async def removeUserVoice(vc):
|
||||
global path
|
||||
channels_list = os.listdir(f"{path}/guilds/{str(vc.guild.id)}/channels/")
|
||||
if f"{vc.id}.json" in channels_list:
|
||||
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
|
||||
vc_file = f"{path}/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"])
|
||||
needed_channel = discord.utils.get(vc.guild.channels, id=vc.id)
|
||||
nomic_channel = discord.utils.get(vc.guild.channels, id=vc_conf["nomic"])
|
||||
|
||||
remove(vc_file)
|
||||
os.remove(vc_file)
|
||||
|
||||
if needed_channel is None:
|
||||
appendLog(
|
||||
f"Removed voice channel '{needed_channel}' of user with id {str(vc_conf['ownerid'])}",
|
||||
guild=vc.guild,
|
||||
)
|
||||
else:
|
||||
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:
|
||||
appendLog(f"Removed voice channel {str(needed_channel.id)} of user {str(vc_conf['ownerid'])}", guild=vc.guild.id)
|
||||
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,
|
||||
)
|
||||
appendLog(f"Removed nomic channel {str(nomic_channel.id)} of channel {str(needed_channel.id)}", guild=vc.guild.id)
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
async def createUserVoice(
|
||||
vc: VoiceChannel, category: CategoryChannel, member: Member
|
||||
) -> VoiceChannel:
|
||||
global debug
|
||||
async def createUserVoice(vc, category, member):
|
||||
global path
|
||||
chan = {}
|
||||
overwrites_channel = {
|
||||
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
|
||||
),
|
||||
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)
|
||||
}
|
||||
overwrites_nomic = {
|
||||
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
|
||||
),
|
||||
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)
|
||||
}
|
||||
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,
|
||||
)
|
||||
else:
|
||||
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"
|
||||
created_channel = await vc.guild.create_voice_channel(getMsg("name_voice", vc.guild).format(member.name), category=category, overwrites=overwrites_channel)
|
||||
appendLog(f"Created voice channel {str(created_channel.id)} for user {str(member.id)}", guild=vc.guild.id)
|
||||
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"
|
||||
chan["ownerid"] = member.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,
|
||||
)
|
||||
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)))
|
||||
appendLog(f"Created nomic channel {str(nomic_channel.id)} for channel {str(created_channel.id)}", guild=vc.guild.id)
|
||||
chan["nomic"] = nomic_channel.id
|
||||
saveJson(chan, vc_file)
|
||||
return created_channel
|
||||
|
||||
|
||||
def isVoiceOfUser(vc: VoiceChannel, member: Member) -> bool:
|
||||
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
|
||||
def isVoiceOfUser(vc, member):
|
||||
global path
|
||||
vc_file = f"{path}/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: Literal["deny", "allow"], vc: VoiceChannel, member: Member
|
||||
) -> None:
|
||||
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
|
||||
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)
|
||||
if loadJson("config.json")["enable_nomic"]:
|
||||
nomic_channel = utils.get(vc.guild.channels, id=vc_conf["nomic"])
|
||||
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: Client):
|
||||
if not path.isdir(f"guilds/"):
|
||||
makedirs(f"guilds", exist_ok=True)
|
||||
guilds_list = listdir(f"guilds/")
|
||||
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/")
|
||||
for guild in guilds_list:
|
||||
guild_object = client.get_guild(int(guild))
|
||||
if path.isdir(f"guilds/{guild}/channels"):
|
||||
channels_list = listdir(f"guilds/{guild}/channels/")
|
||||
if os.path.isdir(f"{path}/guilds/{guild}/channels"):
|
||||
channels_list = os.listdir(f"{path}/guilds/{guild}/channels/")
|
||||
for channel in channels_list:
|
||||
channel_id = channel[:-5]
|
||||
try:
|
||||
selected_channel = utils.get(
|
||||
guild_object.voice_channels, id=int(channel_id)
|
||||
)
|
||||
channel_owner = loadJson(f"guilds/{guild}/channels/{channel}")[
|
||||
"ownerid"
|
||||
]
|
||||
selected_channel = discord.utils.get(guild_object.voice_channels, id=int(channel_id))
|
||||
channel_owner = loadJson(f"{path}/guilds/{guild}/channels/{channel}")["ownerid"]
|
||||
remove_channel = True
|
||||
for member in selected_channel.members:
|
||||
if member.id == channel_owner:
|
||||
@ -409,101 +210,36 @@ async def clearTrash(client: Client):
|
||||
if remove_channel:
|
||||
await removeUserVoice(selected_channel)
|
||||
except:
|
||||
remove(f"guilds/{guild}/channels/{channel_id}.json")
|
||||
|
||||
os.remove(f"{path}/guilds/{guild}/channels/{channel_id}.json")
|
||||
|
||||
#async def autoClearTrash(client):
|
||||
# execute clearTrash every 120 seconds
|
||||
|
||||
async def guildConfigured(guild):
|
||||
|
||||
def getHelpMessage(ctx: ApplicationContext, version: float) -> Embed:
|
||||
# channelExists(number, guild, type="Voice")
|
||||
|
||||
config = loadJson("config.json")
|
||||
|
||||
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)
|
||||
|
||||
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 = 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", ctx.guild))
|
||||
|
||||
return embed
|
||||
|
||||
|
||||
async def guildConfigured(guild: Guild) -> str:
|
||||
output = {}
|
||||
config = loadJson("config.json")
|
||||
|
||||
for kind in ["channel", "category"]:
|
||||
if guildConfGet(guild, kind) is not None:
|
||||
for kind in ["channel", "category", "prefix"]:
|
||||
if guildConfGet(guild.id, kind) is not None:
|
||||
try:
|
||||
guild_object = utils.get(guild.categories, id=guildConfGet(guild, kind))
|
||||
output[kind] = getMsg("configured_" + kind, guild).format(
|
||||
guild_object.name
|
||||
)
|
||||
if kind == "channel":
|
||||
guild_object = discord.utils.get(guild.channels, id=guildConfGet(guild.id, kind))
|
||||
output[kind] = getMsg("configured_"+kind, guild).format(guild_object.name)
|
||||
elif kind == "category":
|
||||
guild_object = discord.utils.get(guild.categories, id=guildConfGet(guild.id, kind))
|
||||
output[kind] = getMsg("configured_"+kind, guild).format(guild_object.name)
|
||||
elif kind == "prefix":
|
||||
output[kind] = getMsg("info_prefix", guild).format(guildConfGet(guild.id, kind))
|
||||
except Exception as exp:
|
||||
if kind == "prefix":
|
||||
output[kind] = getMsg("info_prefix", guild).format(config["bot_prefix"])
|
||||
else:
|
||||
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)
|
||||
|
||||
return getMsg("server_config", guild).format(
|
||||
getMsg("info_locale", guild).format(getMsg("locale_name", guild)),
|
||||
output["channel"],
|
||||
output["category"],
|
||||
)
|
||||
return getMsg("server_config", guild).format(output["prefix"], getMsg("info_locale", guild).format(getMsg("locale_name", guild)), output["channel"], output["category"])
|
||||
|
@ -1,55 +1,38 @@
|
||||
{
|
||||
"messages": {
|
||||
"shutdown": "**{0}** Shutting down...",
|
||||
"shutdown": "Shutting down...",
|
||||
"locale_name": "English",
|
||||
"locale_set": "Bot's locale has been changed to `English`",
|
||||
"help": "**List of command:**\n{0}• Set parent channel: `{1}channel CHANNEL-ID`\n• Set parent category: `{2}category CATEGORY-ID`\n• Set commands prefix: `{3}prefix SYMBOL`\n• Change bot's locale on server `{4}locale LOCALE`\n\nTo reset channel/category/prefix use `reset` as argument\n\nPlease note that channel/category name ≠ ID of channel/category",
|
||||
"help_owner": "• Turn off the bot: `{0}shutdown`\n",
|
||||
"command_in_dm": "Commands can only be executed on the server",
|
||||
"command_forbidden": "To set up private channels, you need to have **Administrator** permission on the server",
|
||||
"usage_channel": "Correct usage: `{0}channel CHANNEL-ID`\nPlease note that name of channel ≠ ID of channel.\nFind out more about this here: https://support.discord.com/hc/articles/206346498-Where-can-I-find-my-User-Server-Message-ID",
|
||||
"usage_category": "Correct usage: `{0}category CATEGORY-ID`\nPlease note that name of category ≠ ID of category.\nFind out more about it here: https://support.discord.com/hc/articles/206346498-Where-can-I-find-my-User-Server-Message-ID",
|
||||
"usage_prefix": "Correct usage: `{0}prefix SYMBOL`",
|
||||
"usage_locale": "Correct usage: `{0}locale LOCALE`\nAvailable locales: {1}",
|
||||
"result_channel": "Voice channel **{0}** is now set as parent",
|
||||
"result_category": "Category **{0}** is now set as parent",
|
||||
"result_prefix": "Command prefix **{0}** is now set as primary for this server",
|
||||
"warn_channel": "⚠ Parent channel is not set!\nFor the bot to work, you need to set parent channel: `{0}channel CHANNEL-ID`",
|
||||
"warn_category": "⚠ Parent category is not set!\nFor the bot to work, you need to set parent category: `{0}category CATEGORY-ID`",
|
||||
"reset_channel": "Parent voice channel has been reset",
|
||||
"reset_category": "Parent category has been reset",
|
||||
"reset_prefix": "Commands prefix has been reset and now is `{0}`",
|
||||
"reset_locale": "Bot's locale on this server has been reset and now is `{0}`",
|
||||
"none_channel": "Parent voice channel is not set",
|
||||
"none_category": "Parent category is not set",
|
||||
"none_prefix": "Commands prefix is not set, using default prefix `{0}`",
|
||||
"none_locale": "Bot's locale on this server is not set, using default locale: `{0}`",
|
||||
"server_config": "**Server status:**\n{0}\n{1}\n{2}\n{3}\n\n",
|
||||
"info_prefix": "ℹ Commands prefix: `{0}`",
|
||||
"info_locale": "ℹ Bot's server language: `{0}`",
|
||||
"unconfigured_channel": "⚠ Parent channel",
|
||||
"unconfigured_category": "⚠ Parent category",
|
||||
"configured_channel": "☑ Parent channel: `{0}`",
|
||||
"configured_category": "☑ Parent category: `{0}`",
|
||||
"name_voice": "{0}'s channel",
|
||||
"name_nomic": "no-mic-{0}",
|
||||
"description_nomic": "Text channel for communication without a microphone\nVoice room ID: {0}",
|
||||
"set_channel_title": "☑ Parent channel set",
|
||||
"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_locale_title": "☑ Bot language set",
|
||||
"set_locale_description": "This server is now using `{0}`",
|
||||
"reset_channel_title": "☑ Parent channel reset",
|
||||
"reset_channel_description": "Use `/channel set` to select a new channel",
|
||||
"reset_category_title": "☑ Parent category reset",
|
||||
"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 `/locale set` to select a different one",
|
||||
"error_channel_title": "🚫 Error installing channel",
|
||||
"error_channel_description": "Correct Usage: `/channel set`",
|
||||
"error_category_title": "🚫 Error setting category",
|
||||
"error_category_description": "Correct Usage: `/category set`",
|
||||
"error_locale_title": "🚫 Error installing language",
|
||||
"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 `/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 `/category set`",
|
||||
"hint_none_locale_title": "⚠ Bot language not set",
|
||||
"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_locale": "ℹ Server bot language: `{0}`",
|
||||
"help_channel_set": "☑ Parent channel: `{0}`",
|
||||
"help_channel_none": "⚠ Parent channel not installed",
|
||||
"help_category_set": "☑ Parent category: `{0}`",
|
||||
"help_category_none": "⚠ No parent category set",
|
||||
"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_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",
|
||||
"admin_title": "🚫 Permission denied",
|
||||
"admin_description": "You must be bot owner to perform this"
|
||||
"description_nomic": "Text channel for no mic communication\nVoice room ID: {0}"
|
||||
}
|
||||
}
|
38
locale/ru.json
Normal file
38
locale/ru.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"messages": {
|
||||
"shutdown": "Выключаюсь...",
|
||||
"locale_name": "Русский",
|
||||
"locale_set": "Язык бота на сервере был изменён на `Русский`",
|
||||
"help": "**Список команд:**\n{0}• Установить родительский канал: `{1}channel ID-КАНАЛА`\n• Установить родительскую категорию: `{2}category ID-КАТЕГОРИИ`\n• Установить префикс команд: `{3}prefix СИМВОЛ`\n• Сменить язык бота на сервере: `{4}locale ЯЗЫК`\n\nДля сброса канала/категории/префикса используйте `reset` как аргумент\n\nОбратите внимание, что имя канала/категории ≠ ID канала/категории",
|
||||
"help_owner": "• Выключиться: `{0}shutdown`\n",
|
||||
"command_in_dm": "Команды можно исполнять только находясь на сервере",
|
||||
"command_forbidden": "Для настройки приватных каналов нужно иметь право **Администратор** на сервере",
|
||||
"usage_channel": "Правильное использование: `{0}channel ID-КАНАЛА`\nОбратите внимание, что имя канала ≠ ID канала.\nУзнайте больше об этом тут: https://support.discord.com/hc/articles/206346498-Where-can-I-find-my-User-Server-Message-ID",
|
||||
"usage_category": "Правильное использование: `{0}category ID-КАТЕГОРИИ`\nОбратите внимание, что имя категории ≠ ID категории.\nУзнайте больше об этом тут: https://support.discord.com/hc/articles/206346498-Where-can-I-find-my-User-Server-Message-ID",
|
||||
"usage_prefix": "Правильное использование: `{0}prefix СИМВОЛ`",
|
||||
"usage_locale": "Правильное использование: `{0}locale ЯЗЫК`\nДоступные языки: {1}",
|
||||
"result_channel": "Голосовой канал `{0}` был установлен как родительский",
|
||||
"result_category": "Категория `{0}` была установлена как родительская",
|
||||
"result_prefix": "Префикс `{0}` был установлен как основной для этого сервера",
|
||||
"warn_channel": "⚠ Родительский канал не установлен!\nДля работы бота нужно установить канал: `{0}channel ID-КАНАЛА`",
|
||||
"warn_category": "⚠ Родительская категория не установлена!\nДля работы бота нужно установить категорию: `{0}category ID-КАТЕГОРИИ`",
|
||||
"reset_channel": "Родительский голосовой канал был сброшен",
|
||||
"reset_category": "Родительская категория была сброшена",
|
||||
"reset_prefix": "Прификс команд был сброшен, теперь это `{0}`",
|
||||
"reset_locale": "Язык бота на этом сервере был сброшен, теперь это `{0}`",
|
||||
"none_channel": "Родительский голосовой канал не был задан",
|
||||
"none_category": "Родительская категория не была задана",
|
||||
"none_prefix": "Префикс команд не был задан, используется стандартный `{0}`",
|
||||
"none_locale": "Язык бота на сервере не был задан, используется стандартный: `{0}`",
|
||||
"server_config": "**Статус сервера:**\n{0}\n{1}\n{2}\n{3}\n\n",
|
||||
"info_prefix": "ℹ Префикс команд: `{0}`",
|
||||
"info_locale": "ℹ Язык бота на сервере: `{0}`",
|
||||
"unconfigured_channel": "⚠ Родительский канал",
|
||||
"unconfigured_category": "⚠ Родительская категория",
|
||||
"configured_channel": "☑ Родительский канал: `{0}`",
|
||||
"configured_category": "☑ Родительская категория: `{0}`",
|
||||
"name_voice": "Канал {0}",
|
||||
"name_nomic": "без-микро-{0}",
|
||||
"description_nomic": "Текстовый канал для коммуникации без микрофона\nID голосовой комнаты: {0}"
|
||||
}
|
||||
}
|
@ -1,55 +1,38 @@
|
||||
{
|
||||
"messages": {
|
||||
"shutdown": "**{0}** Вимикаюсь...",
|
||||
"shutdown": "Вимикаюсь...",
|
||||
"locale_name": "Українська",
|
||||
"locale_set": "Мова бота на сервері була змінена на `Українську`",
|
||||
"help": "**Перелік команд:**\n{0}• Встановити твірний канал: `{1}channel ID-КАНАЛА`\n• Встановити твірну категорію: `{2}category ID-КАТЕГОРІЇ`\n• Встановити префікс команд: `{3}prefix СИМВОЛ`\n• Змінити мову бота на сервері: `{4}locale МОВА`\n\nДля скидання каналу/категорії/префіксу використовуйте `reset` як аргумент\n\nЗверніть увагу, що назва каналу/категорії ≠ ID каналу/категорії",
|
||||
"help_owner": "• Вимкнутись: `{0}shutdown`\n",
|
||||
"command_in_dm": "Команди можна виконувати тільки знаходячись на сервері",
|
||||
"command_forbidden": "Для налаштування приватних каналів потрібно мати право **Адміністратор** на сервері",
|
||||
"usage_channel": "Правильне використання: `{0}channel ID-КАНАЛА`\nЗверніть увагу, що назва канала ≠ ID канала.\nДізнайтеся більше про це тут: https://support.discord.com/hc/articles/206346498-Where-can-I-find-my-User-Server-Message-ID",
|
||||
"usage_category": "Правильне використання: `{0}category ID-КАТЕГОРІЇ`\nЗверніть увагу, що назва категорії ≠ ID категорії.\nДізнайтеся більше про це тут: https://support.discord.com/hc/articles/206346498-Where-can-I-find-my-User-Server-Message-ID",
|
||||
"usage_prefix": "Правильне використання: `{0}prefix СИМВОЛ`",
|
||||
"usage_locale": "Правильне використання: `{0}locale МОВА`\nДоступні мови: {1}",
|
||||
"result_channel": "Голосовий канал **{0}** було встановлено як твірний",
|
||||
"result_category": "Категорія **{0}** була встановлена як твірна",
|
||||
"result_prefix": "Префікс **{0}** було встановлено як основний для цього сервера",
|
||||
"warn_channel": "⚠ Твірний канал не встановлено!\nДля роботи робота потрібно встановити канал: `{0}channel ID-КАНАЛА`",
|
||||
"warn_category": "⚠ Твірна категорія не встановлена!\nДля роботи робота потрібно встановити категорію: `{0}category ID-КАТЕГОРІЇ`",
|
||||
"reset_channel": "Твірний голосовий канал було скинуто",
|
||||
"reset_category": "Твірну категорію було скинуто",
|
||||
"reset_prefix": "Префікс команд було скинуто, тепер це `{0}`",
|
||||
"reset_locale": "Мову бота на цьому сервері було скинуто, тепер це `{0}`",
|
||||
"none_channel": "Твірний голосовий канал не було задано",
|
||||
"none_category": "Твірну категорію не було задано",
|
||||
"none_prefix": "Префікс команд не було задано, використовується стандартний `{0}`",
|
||||
"none_locale": "Мова бота на сервері не була задана, використовується стандартна: `{0}`",
|
||||
"server_config": "**Статус сервера:**\n{0}\n{1}\n{2}\n{3}\n\n",
|
||||
"info_prefix": "ℹ Префікс команд: `{0}`",
|
||||
"info_locale": "ℹ Мова бота на сервері: `{0}`",
|
||||
"unconfigured_channel": "⚠ Твірний канал",
|
||||
"unconfigured_category": "⚠ Твірна категорія",
|
||||
"configured_channel": "☑ Твірний канал: `{0}`",
|
||||
"configured_category": "☑ Твірна категорія: `{0}`",
|
||||
"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_locale_title": "☑ Мова бота встановлена",
|
||||
"set_locale_description": "На цьому сервері тепер використовується `{0}`",
|
||||
"reset_channel_title": "☑ Твірний канал скинутий",
|
||||
"reset_channel_description": "Для вибору нового каналу використовуйте `/channel set`",
|
||||
"reset_category_title": "☑ Твірну категорію скинуто",
|
||||
"reset_category_description": "Використовуйте `/category set` для вибору нової категорії",
|
||||
"reset_locale_title": "☑ Мова бота скинута",
|
||||
"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": "Правильне використання: `/locale set`\\nДоступні мови: {1}",
|
||||
"hint_none_channel_title": "⚠ Твірний канал не заданий",
|
||||
"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_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_locale": "Змінити мову бота на сервері",
|
||||
"help_notice_id": "Зверніть увагу, що ім'я каналу ≠ ID каналу",
|
||||
"help_notice_id_category": "Зверніть увагу, що ім'я категорії ≠ ID категорії",
|
||||
"forbidden_title": "🚫 Немає прав доступу",
|
||||
"forbidden_description": "Для налаштування приватних каналів потрібно мати право **Адміністратор**",
|
||||
"dm_title": "🚫 Помилка виконання",
|
||||
"dm_description": "Команди можна виконувати лише перебуваючи на сервері",
|
||||
"admin_title": "🚫 Немає прав доступу",
|
||||
"admin_description": "Треба бути адміністратором бота щоб зробити це"
|
||||
"description_nomic": "Текстовий канал для комунікації без мікрофона\nID голосової кімнати: {0}"
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
ujson==5.10.0
|
||||
py-cord[speed]==2.6.1
|
@ -1,2 +1 @@
|
||||
py-cord==2.6.1
|
||||
requests==2.32.3
|
||||
discord.py
|
343
yusarin.py
343
yusarin.py
@ -1,75 +1,312 @@
|
||||
try:
|
||||
from discord import Activity, ActivityType, ApplicationContext, Bot, Intents
|
||||
from requests import get
|
||||
except Exception as exp:
|
||||
print(
|
||||
f"Dependencies not installed. Make sure to run 'pip install -r requirements.txt' before first start"
|
||||
)
|
||||
exit()
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
import threading
|
||||
|
||||
from os import getpid, path
|
||||
try:
|
||||
import discord
|
||||
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()
|
||||
|
||||
from functions import *
|
||||
|
||||
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()
|
||||
pid = os.getpid()
|
||||
version = 1.1
|
||||
|
||||
if loadJson("config.json")["check_for_updates"]:
|
||||
appendLog(f"Currently using YusarinBot v{str(version)}")
|
||||
try:
|
||||
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']}"
|
||||
)
|
||||
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)}")
|
||||
except Exception as exp:
|
||||
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))
|
||||
appendLog(f"Could not get YusarinBot cloud version due to {exp}. Currently using {str(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=Activity(type=ActivityType.listening, name=config["bot_activity"])
|
||||
)
|
||||
await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=config["bot_activity"]))
|
||||
|
||||
await clearTrash(client)
|
||||
|
||||
|
||||
client.add_cog(CogCategory(client))
|
||||
client.add_cog(CogChannel(client))
|
||||
client.add_cog(CogLocale(client))
|
||||
client.add_cog(CogUtility(client))
|
||||
@client.event
|
||||
async def on_voice_state_update(member, before, after):
|
||||
|
||||
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.id, "channel"):
|
||||
if guildConfGet(vc_to.guild.id, "category") is not None:
|
||||
voice_chan = await createUserVoice(vc_to, discord.utils.get(vc_to.guild.categories, id=guildConfGet(vc_to.guild.id, "category")), member)
|
||||
try:
|
||||
await member.move_to(voice_chan)
|
||||
except:
|
||||
await removeUserVoice(voice_chan)
|
||||
else:
|
||||
appendLog(f"Category for guild {str(vc_to.guild.id)} is not set", guild=vc_to.guild.id)
|
||||
|
||||
# ==========================================================================================
|
||||
|
||||
@client.event
|
||||
async def on_message(message):
|
||||
|
||||
config = loadJson("config.json")
|
||||
|
||||
if message.guild is not None:
|
||||
try:
|
||||
prefix = guildConfGet(message.guild.id, "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"]:
|
||||
|
||||
if message.author.id == config["owner"]:
|
||||
|
||||
await message.channel.send(getMsg("shutdown", message.guild))
|
||||
os.system(f"kill -9 {str(pid)}")
|
||||
|
||||
else:
|
||||
|
||||
return
|
||||
|
||||
elif message.content.startswith(f"{prefix}channel"):
|
||||
|
||||
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.id, "channel") is not None:
|
||||
|
||||
guildConfReset(message.guild.id, "channel")
|
||||
|
||||
await message.channel.send(getMsg("reset_channel", message.guild))
|
||||
|
||||
else:
|
||||
|
||||
await message.channel.send(getMsg("none_channel", message.guild))
|
||||
|
||||
else:
|
||||
|
||||
selected_channel = discord.utils.get(message.guild.channels, id=int(fullcmd[1]))
|
||||
|
||||
guildConfSet(message.guild.id, "channel", int(fullcmd[1]))
|
||||
|
||||
await message.channel.send(getMsg("result_channel", message.guild).format(selected_channel.name))
|
||||
|
||||
if guildConfGet(message.guild.id, "category") is None:
|
||||
|
||||
await message.channel.send(getMsg("warn_category", message.guild).format(prefix))
|
||||
|
||||
except Exception as exp:
|
||||
|
||||
#print(exp)
|
||||
|
||||
await message.channel.send(getMsg("usage_channel", message.guild).format(prefix))
|
||||
|
||||
else:
|
||||
|
||||
await message.channel.send(getMsg("command_forbidden", message.guild))
|
||||
|
||||
else:
|
||||
await message.channel.send(getMsg("command_in_dm", message.guild))
|
||||
|
||||
elif message.content.startswith(f"{prefix}category"):
|
||||
|
||||
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.id, "category") is not None:
|
||||
|
||||
guildConfReset(message.guild.id, "category")
|
||||
|
||||
await message.channel.send(getMsg("reset_category", message.guild))
|
||||
|
||||
else:
|
||||
|
||||
await message.channel.send(getMsg("none_category", message.guild))
|
||||
|
||||
else:
|
||||
|
||||
selected_category = discord.utils.get(message.guild.channels, id=int(fullcmd[1]))
|
||||
|
||||
guildConfSet(message.guild.id, "category", int(fullcmd[1]))
|
||||
|
||||
await message.channel.send(getMsg("result_category", message.guild).format(selected_category.name))
|
||||
|
||||
if guildConfGet(message.guild.id, "channel") is None:
|
||||
|
||||
await message.channel.send(getMsg("warn_channel", message.guild).format(prefix))
|
||||
|
||||
except Exception as exp:
|
||||
|
||||
#print(exp)
|
||||
|
||||
await message.channel.send(getMsg("usage_category", message.guild).format(prefix))
|
||||
|
||||
else:
|
||||
|
||||
await message.channel.send(getMsg("command_forbidden", message.guild))
|
||||
|
||||
else:
|
||||
await message.channel.send(getMsg("command_in_dm", message.guild))
|
||||
|
||||
elif message.content.startswith(f"{prefix}prefix"):
|
||||
|
||||
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.id, "prefix") is not None:
|
||||
|
||||
guildConfReset(message.guild.id, "prefix")
|
||||
|
||||
await message.channel.send(getMsg("reset_prefix", message.guild).format(config["bot_prefix"]))
|
||||
|
||||
else:
|
||||
|
||||
await message.channel.send(getMsg("none_prefix", message.guild).format(prefix))
|
||||
|
||||
else:
|
||||
|
||||
guildConfSet(message.guild.id, "prefix", fullcmd[1])
|
||||
|
||||
await message.channel.send(getMsg("result_prefix", message.guild).format(fullcmd[1]))
|
||||
|
||||
except:
|
||||
|
||||
await message.channel.send(getMsg("usage_prefix", message.guild).format(prefix))
|
||||
|
||||
else:
|
||||
await message.channel.send(getMsg("command_forbidden", message.guild))
|
||||
|
||||
else:
|
||||
await message.channel.send(getMsg("command_in_dm", message.guild))
|
||||
|
||||
elif message.content.startswith(f"{prefix}locale"):
|
||||
|
||||
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.id, "locale") is not None:
|
||||
|
||||
guildConfReset(message.guild.id, "locale")
|
||||
appendLog(f"Server's locale has been reset", message.guild.id)
|
||||
await message.channel.send(getMsg("reset_locale", message.guild).format(getMsg("locale_name", message.guild)))
|
||||
|
||||
else:
|
||||
|
||||
await message.channel.send(getMsg("none_locale", message.guild).format(getMsg("locale_name", message.guild)))
|
||||
|
||||
else:
|
||||
|
||||
for locale_file in os.listdir(f"{path}/locale/"):
|
||||
if locale_file[:-5] == fullcmd[1]:
|
||||
guildConfSet(message.guild.id, "locale", fullcmd[1])
|
||||
appendLog(f"Server's locale is now set to {fullcmd[1]}", message.guild.id)
|
||||
await message.channel.send(getMsg("locale_set", message.guild))
|
||||
return
|
||||
|
||||
locales = []
|
||||
|
||||
for locale_file in os.listdir(f"{path}/locale/"):
|
||||
locales.append(f"`{locale_file[:-5]}`")
|
||||
|
||||
await message.channel.send(getMsg("usage_locale", message.guild).format(prefix, ", ".join(locales)))
|
||||
|
||||
except:
|
||||
|
||||
locales = []
|
||||
|
||||
for locale_file in os.listdir(f"{path}/locale/"):
|
||||
locales.append(f"`{locale_file[:-5]}`")
|
||||
|
||||
await message.channel.send(getMsg("usage_locale", message.guild).format(prefix, ", ".join(locales)))
|
||||
|
||||
else:
|
||||
await message.channel.send(getMsg("command_forbidden", message.guild))
|
||||
|
||||
else:
|
||||
await message.channel.send(getMsg("command_in_dm", message.guild))
|
||||
|
||||
elif message.content.startswith(f"{prefix}help"):
|
||||
if message.author.id == config["owner"]:
|
||||
if message.guild is not None:
|
||||
await message.channel.send(await guildConfigured(message.guild) + getMsg("help", message.guild).format(getMsg("help_owner", message.guild).format(prefix), prefix, prefix, prefix, prefix, prefix))
|
||||
else:
|
||||
await message.channel.send(getMsg("help", message.guild).format(getMsg("help_owner", message.guild).format(prefix), prefix, prefix, prefix, prefix, prefix))
|
||||
else:
|
||||
if message.guild is not None:
|
||||
await message.channel.send(await guildConfigured(message.guild) + getMsg("help").format("", prefix, prefix, prefix, prefix))
|
||||
else:
|
||||
await message.channel.send(getMsg("help", message.guild).format("", prefix, prefix, prefix, prefix))
|
||||
|
||||
#if loadJson("config.json")["auto_clear_trash"]:
|
||||
# run func
|
||||
|
||||
appendLog(f"Trying to log in...")
|
||||
|
||||
client.run(loadJson("config.json")["bot_token"])
|
Loading…
Reference in New Issue
Block a user