@@ -1,7 +0,0 @@ | |||
build: | |||
image: latest | |||
python: | |||
version: 3.6 | |||
requirements_file: requirements.txt |
@@ -40,7 +40,7 @@ from roxbot import guild_settings as gs | |||
# Sets up Logging | |||
logger = logging.getLogger('discord') | |||
logger.setLevel(logging.INFO) | |||
handler = logging.FileHandler(filename='roxbot.log', encoding='utf-8', mode='w') | |||
handler = logging.FileHandler(filename='roxbot.log', encoding='utf-8', mode='a') | |||
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s')) | |||
logger.addHandler(handler) | |||
@@ -61,12 +61,6 @@ async def on_ready(): | |||
bot.load_extension("roxbot.core") | |||
print("core.py Loaded") | |||
bot.load_extension("roxbot.err_handle") | |||
print("err_handle.py Loaded") | |||
bot.load_extension("roxbot.logging") | |||
print("logging.py Loaded") | |||
print("") | |||
print("Discord.py version: " + discord.__version__) | |||
print("Client logged in\n") |
@@ -24,24 +24,23 @@ | |||
from roxbot import checks, http, guild_settings, converters, utils, roxbotfacts | |||
from roxbot.exceptions import * | |||
from roxbot.enums import EmbedColours | |||
from roxbot.logging import log | |||
from roxbot.utils import blacklisted | |||
from roxbot.utils import blacklisted, log | |||
import configparser | |||
dev_mode = False | |||
settings = configparser.ConfigParser() | |||
settings.read("roxbot/settings/preferences.ini") | |||
config = configparser.ConfigParser() | |||
config.read("roxbot/settings/preferences.ini") | |||
command_prefix = settings["Roxbot"]["Command_Prefix"] | |||
owner = int(settings["Roxbot"]["OwnerID"]) | |||
command_prefix = config["Roxbot"]["Command_Prefix"] | |||
owner = int(config["Roxbot"]["OwnerID"]) | |||
token = settings["Tokens"]["Discord"] | |||
tat_token = settings["Tokens"]["Tatsumaki"] | |||
imgur_token = settings["Tokens"]["Imgur"] | |||
token = config["Tokens"]["Discord"] | |||
imgur_token = config["Tokens"]["Imgur"] | |||
__description__ = """RoxBot, A Discord Bot made by a filthy Mercy Main. Built with love (and discord.py) by Roxxers#7443. | |||
@@ -51,7 +50,7 @@ __description__ = """RoxBot, A Discord Bot made by a filthy Mercy Main. Built wi | |||
[Found a bug or need to report an issue? Report it here](https://gitlab.roxxers.xyz/roxxers/roxbot/issues/new?issue) | |||
[Say Thanks](https://saythanks.io/to/Roxxers)""" | |||
__author__ = "Roxanne Gibson" | |||
__version__ = "2.0.0a" | |||
__version__ = "2.0.0" | |||
datetime_formatting = "{:%a %Y/%m/%d %H:%M:%S} UTC" | |||
@@ -36,6 +36,7 @@ ags_id = 393764974444675073 | |||
selfieperms = 394939389823811584 | |||
nsfwimageperms = 394941004043649036 | |||
newbie = 450042170112475136 | |||
tat_token = roxbot.config["Tokens"]["Tatsumaki"] | |||
def is_ags(): | |||
@@ -45,7 +46,7 @@ def is_ags(): | |||
async def tatsumaki_api_call(member, guild): | |||
base = "https://api.tatsumaki.xyz/" | |||
url = base + "guilds/" + str(guild.id) + "/members/" + str(member.id) + "/stats" | |||
return await roxbot.http.api_request(url, headers={"Authorization": roxbot.tat_token}) | |||
return await roxbot.http.api_request(url, headers={"Authorization": tat_token}) | |||
class AsortedGenderSounds: |
@@ -24,8 +24,12 @@ | |||
import os | |||
import string | |||
import typing | |||
import logging | |||
import asyncio | |||
import datetime | |||
import youtube_dl | |||
import roxbot | |||
@@ -33,21 +37,206 @@ import discord | |||
from discord.ext import commands | |||
class Core: | |||
"""Cog for commands that change the bot account and bot running.""" | |||
class ErrorHandling: | |||
COMMANDNOTFOUND = "That Command doesn't exist." | |||
COMMANDONCOOLDOWN = "This command is on cooldown, please wait {:.2f} seconds before trying again." | |||
CHECKFAILURE = "You do not have permission to do this. Back off, thot!" | |||
TOOMANYARGS = "Too many arguments given." | |||
DISABLEDCOMMAND = "This command is disabled." | |||
COGSETTINGDISABLED = "{} is disabled on this server." | |||
NODMS = "This command cannot be used in private messages." | |||
YTDLDOWNLOADERROR = "Video could not be downloaded: {}" | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.dev = roxbot.dev_mode | |||
async def on_command_error(self, ctx, error): | |||
if self.dev: | |||
raise error | |||
else: | |||
# UserError warning section | |||
user_errors = (commands.MissingRequiredArgument, commands.BadArgument, | |||
commands.TooManyArguments, roxbot.UserError) | |||
if isinstance(error, user_errors): | |||
embed = discord.Embed(colour=roxbot.EmbedColours.orange) | |||
if isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, roxbot.UserError)): | |||
embed.description = error.args[0] | |||
elif isinstance(error, commands.TooManyArguments): | |||
embed.description = self.TOOMANYARGS | |||
return await ctx.send(embed=embed) | |||
# ActualErrorHandling | |||
embed = discord.Embed() | |||
if isinstance(error, commands.NoPrivateMessage): | |||
embed.description = self.NODMS | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.DisabledCommand): | |||
embed.description = self.DISABLEDCOMMAND | |||
logging.INFO(embed.description) | |||
elif isinstance(error, roxbot.CogSettingDisabled): | |||
embed.description = self.COGSETTINGDISABLED.format(error.args[0]) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.CommandNotFound): | |||
try: | |||
# Sadly this is the only part that makes a cog not modular. I have tried my best though to make it usable without the cog. | |||
cc = roxbot.guild_settings.get(ctx.guild)["custom_commands"] | |||
is_custom_command = bool(ctx.invoked_with in cc["1"] or ctx.invoked_with in cc["2"]) | |||
is_emoticon_face = bool(any(x in string.punctuation for x in ctx.message.content.strip(ctx.prefix)[0])) | |||
is_too_short = bool(len(ctx.message.content) <= 2) | |||
if is_custom_command or is_emoticon_face or is_too_short: | |||
embed = None | |||
else: | |||
embed.description = self.COMMANDNOTFOUND | |||
logging.INFO(embed.description) | |||
except (KeyError, AttributeError): | |||
# KeyError for cog missing, AttributeError if a command invoked via DM | |||
embed.description = self.COMMANDNOTFOUND | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.BotMissingPermissions): | |||
embed.description = "{}".format(error.args[0].replace("Bot", "Roxbot")) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.MissingPermissions): | |||
embed.description = "{}".format(error.args[0]) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.CommandOnCooldown): | |||
embed.description = self.COMMANDONCOOLDOWN.format(error.retry_after) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, (commands.CheckFailure, commands.NotOwner)): | |||
embed.description = self.CHECKFAILURE | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.CommandInvokeError): | |||
# YOUTUBE_DL ERROR HANDLING | |||
if isinstance(error.original, youtube_dl.utils.GeoRestrictedError): | |||
embed.description = self.YTDLDOWNLOADERROR.format("Video is GeoRestricted.") | |||
logging.INFO(embed.description) | |||
elif isinstance(error.original, youtube_dl.utils.DownloadError): | |||
embed.description = self.YTDLDOWNLOADERROR.format(error.original.exc_info[1]) | |||
logging.INFO(embed.description) | |||
# Final catches for errors undocumented. | |||
else: | |||
logging.ERROR(str(error)) | |||
embed = discord.Embed(title='Command Error', colour=roxbot.EmbedColours.dark_red) | |||
embed.description = str(error) | |||
embed.add_field(name='User', value=ctx.author) | |||
embed.add_field(name='Message', value=ctx.message.content) | |||
embed.timestamp = datetime.datetime.utcnow() | |||
elif isinstance(error, commands.CommandError): | |||
embed.description = "Error: {}".format(error.args[0]) | |||
logging.ERROR(embed.description) | |||
else: | |||
logging.ERROR(str(error)) | |||
if embed: | |||
embed.colour = roxbot.EmbedColours.dark_red | |||
await ctx.send(embed=embed) | |||
class Logging: | |||
"""Cog that deals with internal logging with Roxbot that is posted in Discord.""" | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.settings = { | |||
"logging": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool", "channel": "channel"}, | |||
"channel": 0 | |||
} | |||
} | |||
self.bot.add_listener(self.cleanup_logging_settings, "on_guild_channel_delete") | |||
self.bot.add_listener(self.log_member_join, "on_member_join") | |||
self.bot.add_listener(self.log_member_remove, "on_member_remove") | |||
@staticmethod | |||
async def cleanup_logging_settings(channel): | |||
"""Cleans up settings on removal of stored IDs.""" | |||
settings = roxbot.guild_settings.get(channel.guild) | |||
r_logging = settings["logging"] | |||
if channel.id == r_logging["channel"]: | |||
r_logging["channel"] = 0 | |||
settings.update(r_logging, "logging") | |||
async def log_member_join(self, member): | |||
r_logging = roxbot.guild_settings.get(member.guild)["logging"] | |||
if r_logging["enabled"]: | |||
channel = self.bot.get_channel(r_logging["channel"]) | |||
embed = discord.Embed(title="{} joined the server".format(member), colour=roxbot.EmbedColours.pink) | |||
embed.add_field(name="ID", value=member.id) | |||
embed.add_field(name="Mention", value=member.mention) | |||
embed.add_field(name="Date Account Created", value=roxbot.datetime_formatting.format(member.created_at)) | |||
embed.add_field(name="Date Joined", value=roxbot.datetime_formatting.format(member.joined_at)) | |||
embed.set_thumbnail(url=member.avatar_url) | |||
return await channel.send(embed=embed) | |||
async def log_member_remove(self, member): | |||
# TODO: Add some way of detecting whether a user left/was kicked or was banned. | |||
r_logging = roxbot.guild_settings.get(member.guild)["logging"] | |||
if r_logging["enabled"]: | |||
channel = self.bot.get_channel(r_logging["channel"]) | |||
embed = discord.Embed(description="{} left the server".format(member), colour=roxbot.EmbedColours.pink) | |||
return await channel.send(embed=embed) | |||
@commands.has_permissions(manage_channels=True) | |||
@commands.guild_only() | |||
@commands.command(aliases=["log"]) | |||
async def logging(self, ctx, setting, *, channel: typing.Optional[discord.TextChannel] = None): | |||
"""Edits the logging settings. | |||
Options: | |||
enable/disable: Enable/disables logging. | |||
channel: sets the channel. | |||
""" | |||
setting = setting.lower() | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
if setting == "enable": | |||
settings["logging"]["enabled"] = 1 | |||
await ctx.send("'logging' was enabled!") | |||
elif setting == "disable": | |||
settings["logging"]["enabled"] = 0 | |||
await ctx.send("'logging' was disabled :cry:") | |||
elif setting == "channel": | |||
if not channel: | |||
channel = ctx.channel | |||
settings["logging"]["channel"] = channel.id | |||
await ctx.send("{} has been set as the logging channel!".format(channel.mention)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(settings["logging"], "logging") | |||
class Core(ErrorHandling, Logging): | |||
"""Core bot cog. Includes management commands, logging, error handling, and backups.""" | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
super().__init__(self.bot) | |||
# Backup setup | |||
self.backup_task = self.bot.loop.create_task(self.auto_backups()) | |||
############# | |||
# Backups # | |||
############# | |||
async def auto_backups(self): | |||
await self.bot.wait_until_ready() | |||
raw_settings = {} | |||
for guild in self.bot.guilds: | |||
raw_settings = {**raw_settings, **roxbot.guild_settings._open_config(guild, os.listdir('roxbot/settings/servers/{}'.format(guild.id)))} | |||
directory = os.listdir('roxbot/settings/servers/{}'.format(guild.id)) | |||
raw_settings = {**raw_settings, **roxbot.guild_settings._open_config(guild, directory)} | |||
while not self.bot.is_closed(): | |||
current_settings = {} | |||
for guild in self.bot.guilds: | |||
current_settings = {**current_settings, **roxbot.guild_settings._open_config(guild, os.listdir('roxbot/settings/servers/{}'.format(guild.id)))} | |||
directory = os.listdir('roxbot/settings/servers/{}'.format(guild.id)) | |||
current_settings = {**current_settings, **roxbot.guild_settings._open_config(guild, directory)} | |||
if raw_settings != current_settings: | |||
raw_settings = current_settings | |||
time = datetime.datetime.now() | |||
@@ -62,6 +251,10 @@ class Core: | |||
roxbot.guild_settings.backup(filename) | |||
return await ctx.send("Settings file backed up as a folder named '{}".format(filename)) | |||
############################ | |||
# Bot Managment Commands # | |||
############################ | |||
@commands.command() | |||
@commands.is_owner() | |||
async def blacklist(self, ctx, option): |
@@ -1,139 +0,0 @@ | |||
# -*- coding: utf-8 -*- | |||
# MIT License | |||
# | |||
# Copyright (c) 2017-2018 Roxanne Gibson | |||
# | |||
# Permission is hereby granted, free of charge, to any person obtaining a copy | |||
# of this software and associated documentation files (the "Software"), to deal | |||
# in the Software without restriction, including without limitation the rights | |||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
# copies of the Software, and to permit persons to whom the Software is | |||
# furnished to do so, subject to the following conditions: | |||
# | |||
# The above copyright notice and this permission notice shall be included in all | |||
# copies or substantial portions of the Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
# SOFTWARE. | |||
import string | |||
import logging | |||
import datetime | |||
import youtube_dl | |||
import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings | |||
class ErrHandle: | |||
COMMANDNOTFOUND = "That Command doesn't exist." | |||
COMMANDONCOOLDOWN = "This command is on cooldown, please wait {:.2f} seconds before trying again." | |||
CHECKFAILURE = "You do not have permission to do this. Back off, thot!" | |||
TOOMANYARGS = "Too many arguments given." | |||
DISABLEDCOMMAND = "This command is disabled." | |||
COGSETTINGDISABLED = "{} is disabled on this server." | |||
NODMS = "This command cannot be used in private messages." | |||
YTDLDOWNLOADERROR = "Video could not be downloaded: {}" | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.dev = roxbot.dev_mode | |||
async def on_command_error(self, ctx, error): | |||
if self.dev: | |||
raise error | |||
else: | |||
# UserError warning section | |||
user_errors = (commands.MissingRequiredArgument, commands.BadArgument, | |||
commands.TooManyArguments, roxbot.UserError) | |||
if isinstance(error, user_errors): | |||
embed = discord.Embed(colour=roxbot.EmbedColours.orange) | |||
if isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, roxbot.UserError)): | |||
embed.description = error.args[0] | |||
elif isinstance(error, commands.TooManyArguments): | |||
embed.description = self.TOOMANYARGS | |||
return await ctx.send(embed=embed) | |||
# ActualErrorHandling | |||
embed = discord.Embed() | |||
if isinstance(error, commands.NoPrivateMessage): | |||
embed.description = self.NODMS | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.DisabledCommand): | |||
embed.description = self.DISABLEDCOMMAND | |||
logging.INFO(embed.description) | |||
elif isinstance(error, roxbot.CogSettingDisabled): | |||
embed.description = self.COGSETTINGDISABLED.format(error.args[0]) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.CommandNotFound): | |||
try: | |||
# Sadly this is the only part that makes a cog not modular. I have tried my best though to make it usable without the cog. | |||
cc = guild_settings.get(ctx.guild)["custom_commands"] | |||
is_custom_command = bool(ctx.invoked_with in cc["1"] or ctx.invoked_with in cc["2"]) | |||
is_emoticon_face = bool(any(x in string.punctuation for x in ctx.message.content.strip(ctx.prefix)[0])) | |||
is_too_short = bool(len(ctx.message.content) <= 2) | |||
if is_custom_command or is_emoticon_face or is_too_short: | |||
embed = None | |||
else: | |||
embed.description = self.COMMANDNOTFOUND | |||
logging.INFO(embed.description) | |||
except (KeyError, AttributeError): | |||
# KeyError for cog missing, AttributeError if a command invoked via DM | |||
embed.description = self.COMMANDNOTFOUND | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.BotMissingPermissions): | |||
embed.description = "{}".format(error.args[0].replace("Bot", "Roxbot")) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.MissingPermissions): | |||
embed.description = "{}".format(error.args[0]) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.CommandOnCooldown): | |||
embed.description = self.COMMANDONCOOLDOWN.format(error.retry_after) | |||
logging.INFO(embed.description) | |||
elif isinstance(error, (commands.CheckFailure, commands.NotOwner)): | |||
embed.description = self.CHECKFAILURE | |||
logging.INFO(embed.description) | |||
elif isinstance(error, commands.CommandInvokeError): | |||
# YOUTUBE_DL ERROR HANDLING | |||
if isinstance(error.original, youtube_dl.utils.GeoRestrictedError): | |||
embed.description = self.YTDLDOWNLOADERROR.format("Video is GeoRestricted.") | |||
logging.INFO(embed.description) | |||
elif isinstance(error.original, youtube_dl.utils.DownloadError): | |||
embed.description = self.YTDLDOWNLOADERROR.format(error.original.exc_info[1]) | |||
logging.INFO(embed.description) | |||
# Final catches for errors undocumented. | |||
else: | |||
logging.ERROR(str(error)) | |||
embed = discord.Embed(title='Command Error', colour=roxbot.EmbedColours.dark_red) | |||
embed.description = str(error) | |||
embed.add_field(name='User', value=ctx.author) | |||
embed.add_field(name='Message', value=ctx.message.content) | |||
embed.timestamp = datetime.datetime.utcnow() | |||
elif isinstance(error, commands.CommandError): | |||
embed.description = "Error: {}".format(error.args[0]) | |||
logging.ERROR(embed.description) | |||
else: | |||
logging.ERROR(str(error)) | |||
if embed: | |||
embed.colour = roxbot.EmbedColours.dark_red | |||
await ctx.send(embed=embed) | |||
def setup(bot_client): | |||
bot_client.add_cog(ErrHandle(bot_client)) |
@@ -1,128 +0,0 @@ | |||
# -*- coding: utf-8 -*- | |||
# MIT License | |||
# | |||
# Copyright (c) 2017-2018 Roxanne Gibson | |||
# | |||
# Permission is hereby granted, free of charge, to any person obtaining a copy | |||
# of this software and associated documentation files (the "Software"), to deal | |||
# in the Software without restriction, including without limitation the rights | |||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
# copies of the Software, and to permit persons to whom the Software is | |||
# furnished to do so, subject to the following conditions: | |||
# | |||
# The above copyright notice and this permission notice shall be included in all | |||
# copies or substantial portions of the Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
# SOFTWARE. | |||
import typing | |||
import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings | |||
async def log(guild, channel, command_name, **kwargs): | |||
"""Logs activity internally for Roxbot. Will only do anything if the server enables internal logging. | |||
This is mostly used for logging when certain commands are used that can be an issue for admins. Esp when Roxbot outputs | |||
something that could break the rules, then deletes their message. | |||
Params | |||
======= | |||
guild: discord.Guild | |||
Used to check if the guild has logging enabled | |||
channel: discord.TextChannel | |||
command_name: str | |||
kwargs: dict | |||
All kwargs and two other params will be added to the logging embed as fields, allowing you to customise the output | |||
""" | |||
logging = guild_settings.get(guild)["logging"] | |||
if logging["enabled"]: | |||
embed = discord.Embed(title="{} command logging".format(command_name), colour=roxbot.EmbedColours.pink) | |||
for key, value in kwargs.items(): | |||
embed.add_field(name=key, value=value) | |||
return await channel.send(embed=embed) | |||
class Logging: | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.settings = { | |||
"logging": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool", "channel": "channel"}, | |||
"channel": 0 | |||
} | |||
} | |||
async def on_guild_channel_delete(self, channel): | |||
"""Cleans up settings on removal of stored IDs.""" | |||
settings = roxbot.guild_settings.get(channel.guild) | |||
logging = settings["logging"] | |||
if channel.id == logging["channel"]: | |||
logging["channel"] = 0 | |||
settings.update(logging, "logging") | |||
async def on_member_join(self, member): | |||
logging = guild_settings.get(member.guild)["logging"] | |||
if logging["enabled"]: | |||
channel = self.bot.get_channel(logging["channel"]) | |||
embed = discord.Embed(title="{} joined the server".format(member), colour=roxbot.EmbedColours.pink) | |||
embed.add_field(name="ID", value=member.id) | |||
embed.add_field(name="Mention", value=member.mention) | |||
embed.add_field(name="Date Account Created", value=roxbot.datetime_formatting.format(member.created_at)) | |||
embed.add_field(name="Date Joined", value=roxbot.datetime_formatting.format(member.joined_at)) | |||
embed.set_thumbnail(url=member.avatar_url) | |||
return await channel.send(embed=embed) | |||
async def on_member_remove(self, member): | |||
# TODO: Add some way of detecting whether a user left/was kicked or was banned. | |||
logging = guild_settings.get(member.guild)["logging"] | |||
if logging["enabled"]: | |||
channel = self.bot.get_channel(logging["channel"]) | |||
embed = discord.Embed(description="{} left the server".format(member), colour=roxbot.EmbedColours.pink) | |||
return await channel.send(embed=embed) | |||
@commands.has_permissions(manage_channels=True) | |||
@commands.guild_only() | |||
@commands.command(aliases=["log"]) | |||
async def logging(self, ctx, setting, *, channel: typing.Optional[discord.TextChannel] = None): | |||
"""Edits the logging settings. | |||
Options: | |||
enable/disable: Enable/disables logging. | |||
channel: sets the channel. | |||
""" | |||
setting = setting.lower() | |||
settings = guild_settings.get(ctx.guild) | |||
if setting == "enable": | |||
settings["logging"]["enabled"] = 1 | |||
await ctx.send("'logging' was enabled!") | |||
elif setting == "disable": | |||
settings["logging"]["enabled"] = 0 | |||
await ctx.send("'logging' was disabled :cry:") | |||
elif setting == "channel": | |||
if not channel: | |||
channel = ctx.channel | |||
settings["logging"]["channel"] = channel.id | |||
await ctx.send("{} has been set as the logging channel!".format(channel.mention)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(settings["logging"], "logging") | |||
def setup(bot_client): | |||
bot_client.add_cog(Logging(bot_client)) |
@@ -15,11 +15,11 @@ Imgur=TokenHere | |||
Tatsumaki=TokenHere | |||
[Backups] | |||
; Settings for the servers.json backups. | |||
; Settings for the server settings backups. | |||
; This is the file that contains all settings for all servers the bot is in. | |||
; Explaintion: | |||
; enabled: Whether or not backups should be enabled. This is heavily recommened to be kept on. | |||
; rate: The amount of time in seconds that the bot will check for changes in the settings file to backup. Default: 300 # 5 Minutes | |||
; rate: The amount of time in minutes that the bot will check for changes in the settings file to backup. Default: 5 minutes | |||
enabled=True | |||
rate=300 | |||
rate=5 |
@@ -27,6 +27,9 @@ import asyncio | |||
import discord | |||
import argparse | |||
from roxbot import guild_settings | |||
from roxbot.enums import EmbedColours | |||
class ArgParser(argparse.ArgumentParser): | |||
"""Create Roxbot's own version of ArgumentParser that doesn't exit the program on error.""" | |||
@@ -138,3 +141,27 @@ def blacklisted(user): | |||
if str(user.id)+"\n" == line: | |||
return True | |||
return False | |||
async def log(guild, channel, command_name, **kwargs): | |||
"""Logs activity internally for Roxbot. Will only do anything if the server enables internal logging. | |||
This is mostly used for logging when certain commands are used that can be an issue for admins. Esp when Roxbot outputs | |||
something that could break the rules, then deletes their message. | |||
Params | |||
======= | |||
guild: discord.Guild | |||
Used to check if the guild has logging enabled | |||
channel: discord.TextChannel | |||
command_name: str | |||
kwargs: dict | |||
All kwargs and two other params will be added to the logging embed as fields, allowing you to customise the output | |||
""" | |||
logging = guild_settings.get(guild)["logging"] | |||
if logging["enabled"]: | |||
embed = discord.Embed(title="{} command logging".format(command_name), colour=EmbedColours.pink) | |||
for key, value in kwargs.items(): | |||
embed.add_field(name=key, value=value) | |||
return await channel.send(embed=embed) |