tldr: core, warn's skeleton
This commit is contained in:
parent
b5b7f0c7ef
commit
815709d68b
17 changed files with 328 additions and 106 deletions
|
@ -8,6 +8,7 @@
|
|||
<w>postgresql</w>
|
||||
<w>socketstats</w>
|
||||
<w>splt</w>
|
||||
<w>systemd</w>
|
||||
<w>tutux</w>
|
||||
<w>webhooks</w>
|
||||
</words>
|
||||
|
|
|
@ -3,10 +3,17 @@
|
|||
<component name="ChangeListManager">
|
||||
<list default="true" id="c97c8a30-7573-4dcd-a0d4-5bf94b8ddbbd" name="5ed57ed9960f35191182a924 core" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/setup.cfg" beforeDir="false" afterPath="$PROJECT_DIR$/setup.cfg" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/__main__.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/__main__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/images/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/cogs/images/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/logs/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/cogs/logs/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/network/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/cogs/network/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/bot.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/core/bot.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/core/config.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/data_manager.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/core/data_manager.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/utils/functions/extra.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/core/utils/functions/extra.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/logging.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/logging.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/setup.py" beforeDir="false" afterPath="$PROJECT_DIR$/tuxbot/setup.py" afterDir="false" />
|
||||
</list>
|
||||
<list id="a3abf5c0-7587-46e4-8f09-88e34a1ab8a4" name="5ed41911b012e33f68a07e7a i18n" comment="" />
|
||||
<list id="6566fca1-2e90-48bb-9e74-dd3badbaca99" name="Default Changelist" comment="" />
|
||||
|
@ -38,7 +45,7 @@
|
|||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/tuxbot" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/tuxbot/core" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.detected.package.tslint" value="true" />
|
||||
<property name="node.js.path.for.package.eslint" value="project" />
|
||||
|
@ -49,6 +56,13 @@
|
|||
<property name="tasks.open.task.update.state.enabled" value="false" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/tuxbot/core" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs/network" />
|
||||
<recent name="$PROJECT_DIR$" />
|
||||
</key>
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs/network" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs/logs" />
|
||||
|
@ -56,13 +70,6 @@
|
|||
<recent name="$PROJECT_DIR$/tuxbot/cogs" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/core" />
|
||||
</key>
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/tuxbot" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs/network" />
|
||||
<recent name="$PROJECT_DIR$" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs" />
|
||||
<recent name="$PROJECT_DIR$/utils/locales" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="SvnConfiguration">
|
||||
<configuration />
|
||||
|
@ -96,7 +103,6 @@
|
|||
</task>
|
||||
<task id="5ed41911b012e33f68a07e7a" summary="i18n">
|
||||
<changelist id="a3abf5c0-7587-46e4-8f09-88e34a1ab8a4" name="5ed41911b012e33f68a07e7a i18n" comment="" />
|
||||
<created>1591290805787</created>
|
||||
<option name="issue" value="true" />
|
||||
<url>https://trello.com/c/vK0cBbF2/38-i18n</url>
|
||||
<option name="number" value="38" />
|
||||
|
@ -108,7 +114,6 @@
|
|||
</task>
|
||||
<task active="true" id="5ed57ed9960f35191182a924" summary="core">
|
||||
<changelist id="c97c8a30-7573-4dcd-a0d4-5bf94b8ddbbd" name="5ed57ed9960f35191182a924 core" comment="" />
|
||||
<created>1591290805787</created>
|
||||
<option name="issue" value="true" />
|
||||
<url>https://trello.com/c/SafaMBht/40-core</url>
|
||||
<option name="number" value="40" />
|
||||
|
@ -118,7 +123,7 @@
|
|||
<workItem from="1591054878071" duration="1039000" />
|
||||
<workItem from="1591088657371" duration="4107000" />
|
||||
<workItem from="1591128560850" duration="40267000" />
|
||||
<workItem from="1591281151234" duration="9745000" />
|
||||
<workItem from="1591281151234" duration="23336000" />
|
||||
</task>
|
||||
<option name="localTasksCounter" value="2" />
|
||||
<option name="createBranch" value="false" />
|
||||
|
@ -142,10 +147,10 @@
|
|||
<option name="version" value="2" />
|
||||
</component>
|
||||
<component name="WindowStateProjectService">
|
||||
<state x="2338" y="213" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1589991158766">
|
||||
<state x="2338" y="213" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1591298885935">
|
||||
<screen x="1920" y="0" width="1920" height="1080" />
|
||||
</state>
|
||||
<state x="2338" y="213" key="#com.intellij.execution.impl.EditConfigurationsDialog/1920.0.1920.1080/0.29.1920.1051@1920.0.1920.1080" timestamp="1589991158766" />
|
||||
<state x="2338" y="213" key="#com.intellij.execution.impl.EditConfigurationsDialog/1920.0.1920.1080/0.29.1920.1051@1920.0.1920.1080" timestamp="1591298885935" />
|
||||
<state x="2616" y="357" width="521" height="396" key="#com.intellij.fileTypes.FileTypeChooser" timestamp="1589928148179">
|
||||
<screen x="1920" y="0" width="1920" height="1080" />
|
||||
</state>
|
||||
|
|
|
@ -13,9 +13,11 @@ install_requires =
|
|||
aiohttp==3.6.2
|
||||
aiosqlite==0.13.0
|
||||
appdirs==1.4.4
|
||||
astunparse==1.6.3
|
||||
async-timeout==3.0.1
|
||||
asyncpg==0.20.1
|
||||
attrs==19.3.0
|
||||
braceexpand==0.1.5
|
||||
cachetools==4.1.0
|
||||
certifi==2020.4.5.1
|
||||
chardet==3.0.4
|
||||
|
@ -27,9 +29,11 @@ install_requires =
|
|||
dnspython==1.16.0
|
||||
humanize==2.4.0
|
||||
idna==2.9
|
||||
import-expression==1.1.3
|
||||
ipinfo==3.0.0
|
||||
ipwhois==1.1.0
|
||||
iso8601==0.1.12
|
||||
jishaku==1.18.2.188
|
||||
multidict==4.7.6
|
||||
psutil==5.7.0
|
||||
PyPika==0.37.7
|
||||
|
@ -40,6 +44,7 @@ install_requires =
|
|||
typing-extensions==3.7.4.2
|
||||
urllib3==1.25.9
|
||||
websockets==8.1
|
||||
wheel==0.34.2
|
||||
yarl==1.4.2
|
||||
|
||||
[options.entry_points]
|
||||
|
|
|
@ -16,7 +16,7 @@ from pip._vendor import distro
|
|||
|
||||
import tuxbot.logging
|
||||
from tuxbot.core import data_manager
|
||||
from tuxbot.core.bot import Tux
|
||||
from tuxbot.core.bot import Tux, ExitCodes
|
||||
from tuxbot.core.utils.functions.cli import bordered
|
||||
from . import __version__
|
||||
|
||||
|
@ -140,10 +140,10 @@ async def shutdown_handler(tux: Tux, signal_type, exit_code=None) -> NoReturn:
|
|||
"""
|
||||
if signal_type:
|
||||
log.info("%s received. Quitting...", signal_type)
|
||||
sys.exit(0)
|
||||
sys.exit(ExitCodes.SHUTDOWN)
|
||||
elif exit_code is None:
|
||||
log.info("Shutting down from unhandled exception")
|
||||
tux.shutdown_code = 1
|
||||
tux.shutdown_code = ExitCodes.CRITICAL
|
||||
|
||||
if exit_code is not None:
|
||||
tux.shutdown_code = exit_code
|
||||
|
@ -161,7 +161,7 @@ async def shutdown_handler(tux: Tux, signal_type, exit_code=None) -> NoReturn:
|
|||
await asyncio.gather(*pending, return_exceptions=True)
|
||||
|
||||
|
||||
async def run_bot(tux: Tux, cli_flags: Namespace) -> None:
|
||||
async def run_bot(tux: Tux, cli_flags: Namespace, loop) -> None:
|
||||
"""This run the bot.
|
||||
|
||||
Parameters
|
||||
|
@ -193,13 +193,14 @@ async def run_bot(tux: Tux, cli_flags: Namespace) -> None:
|
|||
|
||||
if not token:
|
||||
log.critical("Token must be set if you want to login.")
|
||||
sys.exit(1)
|
||||
sys.exit(ExitCodes.CRITICAL)
|
||||
|
||||
try:
|
||||
await tux.load_packages()
|
||||
await tux.start(token, bot=True)
|
||||
except discord.LoginFailure:
|
||||
log.critical("This token appears to be valid.")
|
||||
sys.exit(1)
|
||||
sys.exit(ExitCodes.CRITICAL)
|
||||
|
||||
return None
|
||||
|
||||
|
@ -229,7 +230,7 @@ def main() -> NoReturn:
|
|||
+ "No instance provided ! "
|
||||
"You can use 'tuxbot -L' to list all available instances"
|
||||
+ Style.RESET_ALL)
|
||||
sys.exit(1)
|
||||
sys.exit(ExitCodes.CRITICAL)
|
||||
|
||||
tux = Tux(
|
||||
cli_flags=cli_flags,
|
||||
|
@ -237,8 +238,11 @@ def main() -> NoReturn:
|
|||
dm_help=None
|
||||
)
|
||||
|
||||
loop.run_until_complete(run_bot(tux, cli_flags))
|
||||
loop.run_until_complete(run_bot(tux, cli_flags, loop))
|
||||
except KeyboardInterrupt:
|
||||
print(Fore.RED
|
||||
+ "Please use <prefix>quit instead of Ctrl+C to Shutdown!"
|
||||
+ Style.RESET_ALL)
|
||||
log.warning("Please use <prefix>quit instead of Ctrl+C to Shutdown!")
|
||||
log.error("Received KeyboardInterrupt")
|
||||
if tux is not None:
|
||||
|
@ -258,7 +262,7 @@ def main() -> NoReturn:
|
|||
asyncio.set_event_loop(None)
|
||||
loop.stop()
|
||||
loop.close()
|
||||
exit_code = 1 if tux is None else tux.shutdown_code
|
||||
exit_code = ExitCodes.CRITICAL if tux is None else tux.shutdown_code
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
|
|
0
tuxbot/cogs/__init__.py
Normal file
0
tuxbot/cogs/__init__.py
Normal file
|
@ -1,5 +1,6 @@
|
|||
from .images import Images
|
||||
from ...core.bot import Tux
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Tux):
|
||||
bot.add_cog(Images(bot))
|
||||
|
|
|
@ -3,9 +3,10 @@ import logging
|
|||
from discord.ext import commands
|
||||
|
||||
from .logs import Logs, GatewayHandler, on_error
|
||||
from ...core.bot import Tux
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Tux):
|
||||
cog = Logs(bot)
|
||||
bot.add_cog(cog)
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from .network import Network
|
||||
from ...core.bot import Tux
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Tux):
|
||||
bot.add_cog(Network(bot))
|
||||
|
|
6
tuxbot/cogs/warnings/__init__.py
Normal file
6
tuxbot/cogs/warnings/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from .warnings import Warnings
|
||||
from ...core.bot import Tux
|
||||
|
||||
|
||||
def setup(bot: Tux):
|
||||
bot.add_cog(Warnings(bot))
|
47
tuxbot/cogs/warnings/warnings.py
Normal file
47
tuxbot/cogs/warnings/warnings.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
from typing import Union
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from tuxbot.core import checks
|
||||
from tuxbot.core.bot import Tux
|
||||
|
||||
|
||||
class Warnings(commands.Cog, name="Warnings"):
|
||||
def __init__(self, bot: Tux):
|
||||
self.bot = bot
|
||||
|
||||
@commands.group(name='warn', alias=['warning'])
|
||||
@commands.guild_only()
|
||||
@checks.is_mod()
|
||||
async def _warn(self, ctx: commands.Context):
|
||||
pass
|
||||
|
||||
@_warn.command(name="add")
|
||||
@commands.guild_only()
|
||||
async def _warn_add(
|
||||
self,
|
||||
ctx: commands.Context,
|
||||
member: Union[discord.User, discord.Member],
|
||||
reason: str
|
||||
):
|
||||
pass
|
||||
|
||||
@_warn.command(name="delete", aliases=["del", "remove"])
|
||||
@commands.guild_only()
|
||||
async def action_del(
|
||||
self,
|
||||
ctx: commands.Context,
|
||||
warn_id: int,
|
||||
reason: str = ""
|
||||
):
|
||||
pass
|
||||
|
||||
@_warn.command(name="list", aliases=["all"])
|
||||
@commands.guild_only()
|
||||
async def action_del(
|
||||
self,
|
||||
ctx: commands.Context,
|
||||
member: Union[discord.User, discord.Member] = None
|
||||
):
|
||||
pass
|
|
@ -1,15 +1,19 @@
|
|||
import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
import sys
|
||||
from typing import List, Union
|
||||
|
||||
import discord
|
||||
from colorama import Fore, Style, init
|
||||
from discord.ext import commands
|
||||
from . import Config
|
||||
from .data_manager import logs_data_path
|
||||
|
||||
from .utils.functions.cli import bordered
|
||||
|
||||
from . import __version__
|
||||
from .utils.functions.extra import ContextPlus
|
||||
|
||||
log = logging.getLogger("tuxbot")
|
||||
init()
|
||||
|
@ -22,24 +26,30 @@ NAME = r"""
|
|||
|_| \__,_/_/\_\_.__/ \___/ \__| |_.__/ \___/ \__|
|
||||
"""
|
||||
|
||||
l_extensions: List[str] = [
|
||||
"jishaku"
|
||||
packages: List[str] = [
|
||||
"jishaku",
|
||||
"tuxbot.cogs.warnings"
|
||||
]
|
||||
|
||||
|
||||
class Tux(commands.AutoShardedBot):
|
||||
def __init__(self, *args, cli_flags=None, bot_dir: Path = Path.cwd(), **kwargs):
|
||||
_loading: asyncio.Task
|
||||
|
||||
def __init__(self, *args, cli_flags=None, **kwargs):
|
||||
# by default, if the bot shutdown without any intervention,
|
||||
# it's a crash
|
||||
self.shutdown_code = 1
|
||||
self.shutdown_code = ExitCodes.CRITICAL
|
||||
self.cli_flags = cli_flags
|
||||
self.instance_name = self.cli_flags.instance_name
|
||||
self.last_exception = None
|
||||
self.logs = logs_data_path(self.instance_name)
|
||||
|
||||
self.config = Config(self.instance_name)
|
||||
|
||||
async def _prefixes(bot, message) -> List[str]:
|
||||
prefixes = self.config.get_prefixes(message.guild)
|
||||
prefixes = self.config('core').get('prefixes')
|
||||
|
||||
prefixes.extend(self.config.get_prefixes(message.guild))
|
||||
|
||||
if self.config('core').get('mentionable'):
|
||||
return commands.when_mentioned_or(*prefixes)(bot, message)
|
||||
|
@ -51,18 +61,38 @@ class Tux(commands.AutoShardedBot):
|
|||
if "owner_ids" in kwargs:
|
||||
kwargs["owner_ids"] = set(kwargs["owner_ids"])
|
||||
else:
|
||||
kwargs["owner_ids"] = self.config.owner_ids()
|
||||
kwargs["owner_ids"] = self.config.owners_id()
|
||||
|
||||
message_cache_size = 100_000
|
||||
kwargs["max_messages"] = message_cache_size
|
||||
self.max_messages = message_cache_size
|
||||
|
||||
self.uptime = None
|
||||
self.main_dir = bot_dir
|
||||
self._app_owners_fetched = False # to prevent abusive API calls
|
||||
|
||||
super().__init__(*args, help_command=None, **kwargs)
|
||||
|
||||
async def load_packages(self):
|
||||
if packages:
|
||||
print("Loading packages...")
|
||||
for package in packages:
|
||||
try:
|
||||
self.load_extension(package)
|
||||
except Exception as e:
|
||||
print(Fore.RED
|
||||
+ f"Failed to load package {package}"
|
||||
+ Style.RESET_ALL
|
||||
+ f" check "
|
||||
f"{str((self.logs / 'tuxbot.log').resolve())} "
|
||||
f"for more details")
|
||||
|
||||
log.exception(
|
||||
f"Failed to load package {package}",
|
||||
exc_info=e
|
||||
)
|
||||
|
||||
async def on_ready(self):
|
||||
self.uptime = datetime.datetime.now()
|
||||
INFO = {
|
||||
'title': "INFO",
|
||||
'rows': [
|
||||
|
@ -81,7 +111,7 @@ class Tux(commands.AutoShardedBot):
|
|||
'title': "COGS",
|
||||
'rows': []
|
||||
}
|
||||
for extension in l_extensions:
|
||||
for extension in packages:
|
||||
COGS['rows'].append(
|
||||
f"[{'X' if extension in self.extensions else ' '}] {extension}"
|
||||
)
|
||||
|
@ -91,3 +121,84 @@ class Tux(commands.AutoShardedBot):
|
|||
print(bordered(INFO, COGS))
|
||||
|
||||
print(f"\n{'=' * 118}\n\n")
|
||||
|
||||
async def is_owner(self, user: Union[discord.User, discord.Member]) -> bool:
|
||||
"""Determines if the user is a bot owner.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
user: Union[discord.User, discord.Member]
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
"""
|
||||
if user.id in self.config.owners_id():
|
||||
return True
|
||||
|
||||
owner = False
|
||||
if not self._app_owners_fetched:
|
||||
app = await self.application_info()
|
||||
if app.team:
|
||||
ids = [m.id for m in app.team.members]
|
||||
self.config.update('core', 'owners_id', ids)
|
||||
owner = user.id in ids
|
||||
self._app_owners_fetched = True
|
||||
|
||||
return owner
|
||||
|
||||
async def get_context(self, message: discord.Message, *, cls=None):
|
||||
return await super().get_context(message, cls=ContextPlus)
|
||||
|
||||
async def process_commands(self, message: discord.Message):
|
||||
"""Check for blacklists.
|
||||
|
||||
"""
|
||||
if message.author.bot:
|
||||
return
|
||||
|
||||
if message.guild.id in self.config.get_blacklist('guild') \
|
||||
or message.channel.id in self.config.get_blacklist('channel') \
|
||||
or message.author.id in self.config.get_blacklist('user'):
|
||||
return
|
||||
|
||||
ctx = await self.get_context(message)
|
||||
|
||||
if ctx is None or ctx.valid is False:
|
||||
self.dispatch("message_without_command", message)
|
||||
else:
|
||||
await self.invoke(ctx)
|
||||
|
||||
async def on_message(self, message: discord.Message):
|
||||
await self.process_commands(message)
|
||||
|
||||
async def logout(self):
|
||||
"""Disconnect from Discord and closes all actives connections.
|
||||
|
||||
Todo: add postgresql logout here
|
||||
"""
|
||||
await super().logout()
|
||||
|
||||
async def shutdown(self, *, restart: bool = False):
|
||||
"""Gracefully quit.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
restart:bool
|
||||
If `True`, systemd or the launcher gonna see custom exit code
|
||||
and reboot.
|
||||
|
||||
"""
|
||||
if not restart:
|
||||
self.shutdown_code = ExitCodes.SHUTDOWN
|
||||
else:
|
||||
self.shutdown_code = ExitCodes.RESTART
|
||||
|
||||
await self.logout()
|
||||
sys.exit(self.shutdown_code)
|
||||
|
||||
|
||||
class ExitCodes:
|
||||
CRITICAL = 1
|
||||
SHUTDOWN = 0
|
||||
RESTART = 42
|
||||
|
|
63
tuxbot/core/checks.py
Normal file
63
tuxbot/core/checks.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
from typing import Awaitable, Dict
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands import (
|
||||
bot_has_permissions,
|
||||
has_permissions,
|
||||
is_owner,
|
||||
)
|
||||
|
||||
from tuxbot.core.utils.functions.extra import ContextPlus
|
||||
|
||||
__all__ = [
|
||||
"bot_has_permissions",
|
||||
"has_permissions",
|
||||
"is_owner",
|
||||
"is_mod",
|
||||
"is_admin",
|
||||
"check_permissions",
|
||||
"guild_owner_or_permissions",
|
||||
]
|
||||
|
||||
|
||||
def is_mod():
|
||||
async def pred(ctx):
|
||||
if await ctx.bot.is_owner(ctx.author):
|
||||
return True
|
||||
permissions: discord.Permissions = ctx.channel.permissions_for(ctx.author)
|
||||
return permissions.manage_messages
|
||||
|
||||
return commands.check(pred)
|
||||
|
||||
|
||||
def is_admin():
|
||||
async def pred(ctx):
|
||||
if await ctx.bot.is_owner(ctx.author):
|
||||
return True
|
||||
permissions: discord.Permissions = ctx.channel.permissions_for(ctx.author)
|
||||
return permissions.administrator
|
||||
|
||||
return commands.check(pred)
|
||||
|
||||
|
||||
async def check_permissions(ctx: "ContextPlus", **perms: Dict[str, bool]):
|
||||
if await ctx.bot.is_owner(ctx.author):
|
||||
return True
|
||||
|
||||
elif not perms:
|
||||
return False
|
||||
resolved = ctx.channel.permissions_for(ctx.author)
|
||||
|
||||
return all(
|
||||
getattr(resolved, name, None) == value for name, value in perms.items()
|
||||
)
|
||||
|
||||
|
||||
def guild_owner_or_permissions(**perms: Dict[str, bool]):
|
||||
async def pred(ctx):
|
||||
if ctx.author is ctx.guild.owner:
|
||||
return True
|
||||
return await check_permissions(ctx, **perms)
|
||||
|
||||
return commands.check(pred)
|
|
@ -3,7 +3,7 @@ import logging
|
|||
|
||||
__all__ = ["Config"]
|
||||
|
||||
from typing import List, Dict
|
||||
from typing import List, Dict, Union
|
||||
|
||||
import discord
|
||||
|
||||
|
@ -39,8 +39,8 @@ class Config:
|
|||
def __call__(self, item):
|
||||
return self.__getitem__(item)
|
||||
|
||||
def owner_ids(self) -> List[int]:
|
||||
return self.__getitem__('core').get('owner_ids')
|
||||
def owners_id(self) -> List[int]:
|
||||
return self.__getitem__('core').get('owners_id')
|
||||
|
||||
def token(self) -> str:
|
||||
return self.__getitem__('core').get('token')
|
||||
|
@ -53,3 +53,29 @@ class Config:
|
|||
.get('prefixes', [])
|
||||
|
||||
return prefixes
|
||||
|
||||
def get_blacklist(self, key: str) -> List[Union[str, int]]:
|
||||
core = self.__getitem__('core')
|
||||
blacklist = core \
|
||||
.get('blacklist', {}) \
|
||||
.get(key, [])
|
||||
|
||||
return blacklist
|
||||
|
||||
def update(self, cog_name, item, value) -> dict:
|
||||
datas = self.__getitem__(cog_name)
|
||||
path = data_path(self._cog_instance)
|
||||
|
||||
datas[item] = value
|
||||
|
||||
if cog_name != 'core':
|
||||
path = path / 'cogs' / cog_name
|
||||
else:
|
||||
path /= 'core'
|
||||
|
||||
settings_file = path / 'settings.json'
|
||||
|
||||
with settings_file.open('w') as f:
|
||||
json.dump(datas, f, indent=4)
|
||||
|
||||
return datas
|
||||
|
|
|
@ -69,3 +69,18 @@ def cog_data_path(instance_name: str, cog_name: str) -> Path:
|
|||
Generated path for cog's configs.
|
||||
"""
|
||||
return data_path(instance_name) / "data" / instance_name / "cogs" / cog_name
|
||||
|
||||
|
||||
def logs_data_path(instance_name: str) -> Path:
|
||||
"""Return Path for logs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
instance_name:str
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
Generated path for logs files.
|
||||
"""
|
||||
return data_path(instance_name) / "data" / instance_name / "logs"
|
||||
|
|
|
@ -1,48 +1,11 @@
|
|||
import ast
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
|
||||
import discord
|
||||
from discord.ext import commands, flags
|
||||
|
||||
from configs.bot.protected import protected
|
||||
from configs.bot.settings import prefixes
|
||||
|
||||
|
||||
class ContextPlus(commands.Context):
|
||||
async def send(self, content=None, *args, **kwargs):
|
||||
if content is not None:
|
||||
for value in protected:
|
||||
content = content.replace(
|
||||
str(value),
|
||||
'[Deleted]'
|
||||
)
|
||||
|
||||
if kwargs.get('content') is not None:
|
||||
for value in protected:
|
||||
kwargs['content'] = kwargs['content'].replace(
|
||||
str(value),
|
||||
'[Deleted]'
|
||||
)
|
||||
|
||||
if kwargs.get('embeds') is not None and len(kwargs.get('embeds')) > 0:
|
||||
for i, embed in enumerate(kwargs.get('embeds')):
|
||||
embed = str(kwargs.get('embed').to_dict())
|
||||
for value in protected:
|
||||
embed = embed.replace(str(value), '[Deleted]')
|
||||
kwargs['embeds'][i] = discord.Embed.from_dict(
|
||||
ast.literal_eval(embed)
|
||||
)
|
||||
|
||||
if kwargs.get('embed') is not None:
|
||||
embed = str(kwargs.get('embed').to_dict())
|
||||
for value in protected:
|
||||
embed = embed.replace(str(value), '[Deleted]')
|
||||
kwargs['embed'] = discord.Embed.from_dict(
|
||||
ast.literal_eval(embed)
|
||||
)
|
||||
|
||||
if (hasattr(self.command, 'deletable') and self.command.deletable) \
|
||||
and kwargs.pop('deletable', True):
|
||||
message = await super().send(content, *args, **kwargs)
|
||||
|
@ -86,29 +49,3 @@ class GroupPlus(flags.FlagGroup):
|
|||
|
||||
def group_extra(*args, **kwargs):
|
||||
return commands.group(*args, **kwargs, cls=GroupPlus)
|
||||
|
||||
|
||||
async def get_prefix(bot, message):
|
||||
custom_prefix = prefixes
|
||||
if message.guild:
|
||||
path = f"configs/guilds/{str(message.guild.id)}.json"
|
||||
|
||||
if os.path.exists(path):
|
||||
with open(path) as f:
|
||||
datas = json.load(f)
|
||||
|
||||
custom_prefix = datas["Prefix"]
|
||||
|
||||
return commands.when_mentioned_or(*custom_prefix)(bot, message)
|
||||
|
||||
|
||||
def get_owners() -> list:
|
||||
with open("configs/bot/whitelist.json") as f:
|
||||
datas = json.load(f)
|
||||
|
||||
return datas['owners']
|
||||
|
||||
|
||||
def get_blacklist() -> dict:
|
||||
with open("configs/bot/blacklist.json") as f:
|
||||
return json.load(f)
|
||||
|
|
|
@ -17,6 +17,7 @@ def init_logging(level: int, location: pathlib.Path) -> None:
|
|||
location:Path
|
||||
Where to store logs.
|
||||
"""
|
||||
|
||||
dpy_logger = logging.getLogger("discord")
|
||||
dpy_logger.setLevel(logging.WARN)
|
||||
dpy_logger_file = location / 'discord.log'
|
||||
|
@ -39,10 +40,7 @@ def init_logging(level: int, location: pathlib.Path) -> None:
|
|||
maxBytes=MAX_BYTES, backupCount=MAX_OLD_LOGS
|
||||
)
|
||||
|
||||
dpy_logger.addHandler(dpy_handler)
|
||||
base_logger.addHandler(base_handler)
|
||||
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(formatter)
|
||||
base_logger.addHandler(stdout_handler)
|
||||
dpy_logger.addHandler(stdout_handler)
|
||||
dpy_logger.addHandler(dpy_handler)
|
||||
base_logger.addHandler(base_handler)
|
||||
|
|
|
@ -292,6 +292,7 @@ def finish_setup(data_dir: Path) -> NoReturn:
|
|||
'prefixes': prefixes,
|
||||
'mentionable': mentionable,
|
||||
'owners_id': owners_id,
|
||||
'locale': "en-US"
|
||||
}
|
||||
|
||||
with core_file.open("w") as fs:
|
||||
|
|
Loading…
Reference in a new issue