@@ -11,6 +11,8 @@ bot-env/ | |||
roxbot/settings/servers\.json | |||
roxbot/settings/servers\.json | |||
roxbot/settings/preferences.ini | |||
env/ | |||
@@ -22,3 +24,7 @@ site/ | |||
roxbot/settings/roxbot\.conf | |||
roxbot/settings/db\.sqlite | |||
roxbot/settings/db.sqlite | |||
roxbot/settings/servers\.old/ |
@@ -5,3 +5,4 @@ numpy==1.14.3 | |||
youtube_dl | |||
emoji==0.5.1 | |||
dataset==1.1.0 | |||
pony==0.7.9 |
@@ -30,11 +30,11 @@ import time | |||
import traceback | |||
import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings as gs | |||
from roxbot import db | |||
from roxbot import core | |||
from roxbot.scripts import JSONtoDB | |||
class term: | |||
@@ -84,22 +84,21 @@ bot = core.Roxbot( | |||
async def on_ready(): | |||
print("Logged in as: {}".format(term.fOKGREEN.format(str(bot.user))), end="\n\n") | |||
# this is so if we're added to a server while we're offline we deal with it | |||
roxbot.guild_settings.error_check(bot.guilds, bot.cogs) | |||
print("Guilds in: [{}]".format(len(bot.guilds))) | |||
for guild in bot.guilds: | |||
print(guild) | |||
roxbot.scripts.JSONtoDB.check_convert(bot.guilds) | |||
@bot.event | |||
async def on_guild_join(guild): | |||
gs.add_guild(guild, bot.cogs) | |||
db.populate_single_settings(bot) | |||
@bot.event | |||
async def on_guild_remove(guild): | |||
gs.remove_guild(guild) | |||
db.delete_single_settings(guild) | |||
@bot.check | |||
@@ -136,13 +135,6 @@ async def about(ctx): | |||
return await ctx.channel.send(embed=em) | |||
@commands.command(pass_context=False, hidden=True) | |||
async def settings(): | |||
# This is to block any customcommand or command from being made with the same name. | |||
# This is to avoid conflicts with the internal settings system. | |||
raise commands.CommandNotFound("settings") | |||
if __name__ == "__main__": | |||
start_time = time.time() | |||
print(term.fHEADER.format(term.fBOLD.format(term.title))) | |||
@@ -160,13 +152,15 @@ if __name__ == "__main__": | |||
# Load Extension Cogs | |||
print("Cogs Loaded:") | |||
for cog in roxbot.cogs: | |||
for cog in roxbot.cog_list: | |||
try: | |||
bot.load_extension(cog) | |||
print(cog.split(".")[2]) | |||
except ImportError: | |||
print("{} FAILED TO LOAD. MISSING REQUIREMENTS".format(cog.split(".")[2])) | |||
bot.loop.create_task(db.populate_db(bot)) | |||
print(term.seperator) | |||
print("Client logging in...", end="\r") | |||
@@ -29,7 +29,7 @@ from .enums import EmbedColours | |||
from .config import config | |||
from .exceptions import UserError, CogSettingDisabled | |||
from . import checks, http, guild_settings, converters, utils, roxbotfacts, exceptions | |||
from . import checks, http, converters, utils, roxbotfacts, exceptions, db | |||
command_prefix = config["Roxbot"]["Command_Prefix"] | |||
@@ -46,7 +46,7 @@ backup_rate = int(config["Backups"]["rate"]) * 60 # Convert minutes to seconds | |||
dev_mode = False | |||
datetime = "{:%a %Y/%m/%d %H:%M:%S} UTC" | |||
cogs = [ | |||
cog_list = [ | |||
"roxbot.cogs.admin", | |||
"roxbot.cogs.customcommands", | |||
"roxbot.cogs.fun", |
@@ -24,6 +24,7 @@ | |||
import roxbot | |||
from roxbot.db import * | |||
import discord | |||
from discord.ext import commands | |||
@@ -41,8 +42,8 @@ def is_nsfw(): | |||
is_dm_channel = bool(isinstance(ctx.channel, discord.DMChannel)) | |||
is_nsfw_guild_channel = bool(isinstance(ctx.channel, discord.TextChannel) and ctx.channel.is_nsfw()) | |||
if is_nsfw_guild_channel: | |||
nsfw_enabled = bool(roxbot.guild_settings.get(ctx.guild)["nsfw"]["enabled"]) | |||
return nsfw_enabled | |||
with db_session: | |||
return bool(db.get("SELECT `enabled` FROM `NSFWSingle` WHERE `guild_id` = '{}'".format(ctx.guild.id))) | |||
else: | |||
return is_dm_channel | |||
return commands.check(pred) |
@@ -24,23 +24,25 @@ | |||
import datetime | |||
import time | |||
import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings as gs | |||
from roxbot.db import * | |||
def _is_admin_or_mod(message): | |||
if message.author.id == roxbot.owner: | |||
return True | |||
perm_roles = gs.get(message.channel.guild).perm_roles | |||
for role in message.author.roles: | |||
if role.id in perm_roles.get("admin") or role.id in perm_roles.get("mod"): | |||
return True | |||
return False | |||
class AdminSingle(db.Entity): | |||
warning_limit = Required(int, default=0) | |||
guild_id = Required(int, unique=True, size=64) | |||
class AdminWarnings(db.Entity): | |||
user_id = Required(int, size=64) | |||
warned_by = Required(int, size=64) | |||
warning = Optional(str) | |||
date = Required(datetime.datetime, unique=True) | |||
guild_id = Required(int, size=64) | |||
class Admin(commands.Cog): | |||
@@ -80,13 +82,7 @@ class Admin(commands.Cog): | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.settings = { | |||
"admin": { | |||
"convert": {"warnings": "hide"}, | |||
"warning_limit": 0, | |||
"warnings": {}, | |||
} | |||
} | |||
self.autogen_db = AdminSingle | |||
@commands.guild_only() | |||
@commands.has_permissions(manage_messages=True) | |||
@@ -126,7 +122,7 @@ class Admin(commands.Cog): | |||
@commands.bot_has_permissions(manage_messages=True, read_message_history=True) | |||
@commands.cooldown(1, 5) | |||
@commands.command() | |||
async def purge(self, ctx, limit=0, *, author: roxbot.converters.User=None): | |||
async def purge(self, ctx, limit=0, *, author: roxbot.converters.User = None): | |||
"""Purges the text channel the command is execture in. You can specify a certain user to purge as well. | |||
Options: | |||
@@ -160,7 +156,7 @@ class Admin(commands.Cog): | |||
raise commands.CommandNotFound("Subcommand '{}' does not exist.".format(ctx.subcommand_passed)) | |||
@warn.command() | |||
async def add(self, ctx, user: discord.User=None, *, warning=""): | |||
async def add(self, ctx, user: discord.User = None, *, warning=""): | |||
"""Adds a warning to a user. | |||
Options: | |||
@@ -173,29 +169,19 @@ class Admin(commands.Cog): | |||
""" | |||
# Warning in the settings is a dictionary of user ids. The user ids are equal to a list of dictionaries. | |||
settings = gs.get(ctx.guild) | |||
warnings = settings["admin"]["warnings"] | |||
warning_limit = settings["admin"]["warning_limit"] | |||
warning_dict = { | |||
"warned-by": ctx.author.id, | |||
"date": time.time(), | |||
"warning": warning | |||
} | |||
user_id = str(user.id) | |||
if user_id not in warnings: | |||
warnings[user_id] = [] | |||
with db_session: | |||
warning_limit = AdminSingle.get(guild_id=ctx.guild.id).warning_limit | |||
user_warnings = select(w for w in AdminWarnings if w.user_id == user.id and w.guild_id == ctx.guild.id)[:] | |||
amount_warnings = len(user_warnings) | |||
warn_limit = 10 | |||
if len(warnings[user_id]) > warn_limit: | |||
if amount_warnings > warn_limit: | |||
embed = discord.Embed(description=self.WARN_WARN_ADD_LIMIT_REACHED.format(warn_limit), colour=roxbot.EmbedColours.red) | |||
return await ctx.send(embed=embed) | |||
warnings[user_id].append(warning_dict) | |||
settings["admin"]["warnings"] = warnings | |||
settings.update(settings["admin"], "admin") | |||
with db_session: | |||
AdminWarnings(user_id=user.id, warned_by=ctx.author.id, date=datetime.datetime.utcnow(), warning=warning, guild_id=ctx.guild.id) | |||
amount_warnings = len(warnings[user_id]) | |||
if amount_warnings >= warning_limit > 0: | |||
await ctx.author.send(self.OK_WARN_ADD_USER_LIMIT_DM.format(str(user), amount_warnings, warning_limit)) | |||
@@ -203,7 +189,7 @@ class Admin(commands.Cog): | |||
return await ctx.send(embed=embed) | |||
@warn.command() | |||
async def list(self, ctx, *, user: roxbot.converters.User=None): | |||
async def list(self, ctx, *, user: roxbot.converters.User = None): | |||
"""Lists all warning in this guild or all the warnings for one user. | |||
Options: | |||
@@ -215,35 +201,35 @@ class Admin(commands.Cog): | |||
# List all warnings for @Roxbot | |||
;warn list @Roxbot | |||
""" | |||
settings = gs.get(ctx.guild) | |||
warnings = settings["admin"]["warnings"] | |||
if user is None: | |||
paginator = commands.Paginator() | |||
for member in warnings: | |||
# Remove users with no warning here instead of remove cause im lazy | |||
if not warnings[member]: | |||
warnings.pop(member) | |||
else: | |||
member_obj = discord.utils.get(ctx.guild.members, id=int(member)) | |||
if member_obj: | |||
paginator.add_line("{}: {} Warning(s)".format(str(member_obj), len(warnings[member]))) | |||
warnings = {} | |||
with db_session: | |||
for warning in select(warn for warn in AdminWarnings if warn.guild_id == ctx.guild.id)[:]: | |||
if warning.user_id not in warnings: | |||
warnings[warning.user_id] = [] | |||
else: | |||
paginator.add_line("{}: {} Warning(s)".format(member, len(warnings[member]))) | |||
warnings[warning.user_id].append(warning) | |||
for u, warning in warnings.items(): | |||
member_obj = discord.utils.get(ctx.guild.members, id=u) | |||
if member_obj: | |||
paginator.add_line("{}: {} Warning(s)".format(str(member_obj), len(warnings[u]))) | |||
else: | |||
paginator.add_line("{}: {} Warning(s)".format(u, len(warnings[u]))) | |||
# This is in case we have removed some users from the list. | |||
settings["admin"]["warnings"] = warnings | |||
settings.update(settings["admin"], "admin") | |||
if not paginator.pages: | |||
embed = discord.Embed(description=self.OK_WARN_LIST_NO_WARNINGS, colour=roxbot.EmbedColours.orange) | |||
return await ctx.send(embed=embed) | |||
for page in paginator.pages: | |||
return await ctx.send(embed=discord.Embed(description=page, colour=roxbot.EmbedColours.pink)) | |||
return await ctx.send(page) | |||
else: | |||
user_id = str(user.id) | |||
with db_session: | |||
user_warnings = select(w for w in AdminWarnings if w.user_id == user.id and w.guild_id == ctx.guild.id).order_by(AdminWarnings.date)[:] | |||
if not warnings.get(user_id): | |||
if not user_warnings: | |||
embed = discord.Embed(description=self.OK_WARN_LIST_USER_NO_WARNINGS, colour=roxbot.EmbedColours.orange) | |||
return await ctx.send(embed=embed) | |||
@@ -251,20 +237,20 @@ class Admin(commands.Cog): | |||
em.set_thumbnail(url=user.avatar_url) | |||
x = 1 | |||
userlist = warnings[user_id] | |||
for warning in userlist: | |||
for warning in user_warnings: | |||
try: | |||
warned_by = str(await self.bot.get_user_info(warning["warned-by"])) | |||
warned_by = str(ctx.guild.get_member(warning.warned_by)) | |||
if warned_by is None: | |||
warned_by = str(await self.bot.get_user_info(warning.warned_by)) | |||
except discord.ext.commands.CommandInvokeError: | |||
warned_by = warning["warned-by"] | |||
date = roxbot.datetime.format(datetime.datetime.fromtimestamp(warning["date"])) | |||
warn_reason = warning["warning"] | |||
em.add_field(name="Warning %s" % x, value="Warned by: {}\nTime: {}\nReason: {}".format(warned_by, date, warn_reason)) | |||
warned_by = warning.warned_by | |||
date = datetime.datetime.strftime(warning.date, roxbot.datetime.strip("{:} UTC")+" UTC") | |||
em.add_field(name="Warning %s" % x, value="Warned by: {}\nTime: {}\nReason: {}".format(warned_by, date, warning.warning)) | |||
x += 1 | |||
return await ctx.send(embed=em) | |||
@warn.command() | |||
async def remove(self, ctx, user: roxbot.converters.User=None, index=None): | |||
async def remove(self, ctx, user: roxbot.converters.User, index=None): | |||
"""Removes one or all of the warnings for a user. | |||
Options:= | |||
@@ -277,44 +263,40 @@ class Admin(commands.Cog): | |||
# Remove warning 2 for Roxbot | |||
;warn remove Roxbot 2 | |||
""" | |||
user_id = str(user.id) | |||
settings = gs.get(ctx.guild) | |||
warnings = settings["admin"]["warnings"] | |||
if index: | |||
try: | |||
index = int(index) | |||
index -= 1 | |||
warnings[user_id].pop(index) | |||
if not warnings[user_id]: | |||
warnings.pop(user_id) | |||
settings["admin"]["warnings"] = warnings | |||
settings.update(settings["admin"], "admin") | |||
embed = discord.Embed(description=self.OK_WARN_REMOVE_REMOVED_WARNING.format(index+1, str(user)), colour=roxbot.EmbedColours.pink) | |||
return await ctx.send(embed=embed) | |||
except Exception as e: | |||
embed = discord.Embed(colour=roxbot.EmbedColours.red) | |||
if isinstance(e, IndexError): | |||
embed.description = self.ERROR_WARN_REMOVE_INDEXERROR.format(len(settings["warnings"][user_id])) | |||
elif isinstance(e, KeyError): | |||
embed.description = self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user)) | |||
elif isinstance(e, ValueError): | |||
embed.description = self.ERROR_WARN_REMOVE_VALUEERROR | |||
with db_session: | |||
if index: | |||
try: | |||
index = int(index) - 1 | |||
query = select(w for w in AdminWarnings if w.user_id == user.id and w.guild_id == ctx.guild.id) | |||
if query: | |||
user_warnings = query[:] | |||
else: | |||
raise KeyError | |||
user_warnings[index].delete() | |||
embed = discord.Embed(description=self.OK_WARN_REMOVE_REMOVED_WARNING.format(index+1, str(user)), colour=roxbot.EmbedColours.pink) | |||
return await ctx.send(embed=embed) | |||
except Exception as e: | |||
embed = discord.Embed(colour=roxbot.EmbedColours.red) | |||
if isinstance(e, IndexError): | |||
embed.description = self.ERROR_WARN_REMOVE_INDEXERROR.format(len(user_warnings)) | |||
elif isinstance(e, KeyError): | |||
embed.description = self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user)) | |||
elif isinstance(e, ValueError): | |||
embed.description = self.ERROR_WARN_REMOVE_VALUEERROR | |||
else: | |||
raise e | |||
return await ctx.send(embed=embed) | |||
else: | |||
query = select(w for w in AdminWarnings if w.user_id == user.id and w.guild_id == ctx.guild.id) | |||
if query.exists(): | |||
delete(w for w in AdminWarnings if w.user_id == user.id and w.guild_id == ctx.guild.id) | |||
embed = discord.Embed(description=self.OK_WARN_REMOVE_REMOVED_WARNINGS.format(str(user)), colour=roxbot.EmbedColours.pink) | |||
return await ctx.send(embed=embed) | |||
else: | |||
raise e | |||
return ctx.send(embed=embed) | |||
else: | |||
try: | |||
warnings.pop(user_id) | |||
settings["admin"]["warnings"] = warnings | |||
settings.update(settings["admin"], "admin") | |||
embed = discord.Embed(description=self.OK_WARN_REMOVE_REMOVED_WARNINGS.format(str(user)), colour=roxbot.EmbedColours.pink) | |||
return await ctx.send(embed=embed) | |||
except KeyError: | |||
embed = discord.Embed(description=self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user)), colour=roxbot.EmbedColours.orange) | |||
return await ctx.send(embed=embed) | |||
embed = discord.Embed(description=self.WARN_WARN_REMOVE_USER_NOT_FOUND.format(str(user)), colour=roxbot.EmbedColours.red) | |||
return await ctx.send(embed=embed) | |||
@commands.bot_has_permissions(ban_members=True) | |||
@warn.command() | |||
@@ -331,17 +313,15 @@ class Admin(commands.Cog): | |||
# Dryrun the prune command to see how many warnings would be removed | |||
;warn prune 1 | |||
""" | |||
settings = gs.get(ctx.guild) | |||
warnings = settings["admin"]["warnings"].copy() | |||
count = 0 | |||
x = 0 | |||
for ban in await ctx.guild.bans(): | |||
for user in warnings: | |||
if int(user) == ban.user.id: | |||
with db_session: | |||
query = select(w for w in AdminWarnings if w.user_id == ban.user.id and w.guild_id == ctx.guild.id) | |||
if query.exists(): | |||
if dry_run == 0: | |||
settings["admin"]["warnings"].pop(user) | |||
count += 1 | |||
settings.update(settings["admin"], "admin") | |||
embed = discord.Embed(description=self.OK_WARN_PRUNE_PRUNED.format(count), colour=roxbot.EmbedColours.pink) | |||
query.delete() | |||
x += 1 | |||
embed = discord.Embed(description=self.OK_WARN_PRUNE_PRUNED.format(x), colour=roxbot.EmbedColours.pink) | |||
return await ctx.send(embed=embed) | |||
@warn.command(aliases=["sl", "setlimit"]) | |||
@@ -353,10 +333,10 @@ class Admin(commands.Cog): | |||
""" | |||
if number_of_warnings < 0: | |||
raise commands.BadArgument(self.ERROR_WARN_SL_NEG) | |||
settings = gs.get(ctx.guild) | |||
admin = settings["admin"] | |||
admin["warning_limit"] = number_of_warnings | |||
settings.update(admin, "admin") | |||
with db_session: | |||
guild_settings = AdminSingle.get(guild_id=ctx.guild.id) | |||
guild_settings.warning_limit = number_of_warnings | |||
if number_of_warnings == 0: | |||
embed = discord.Embed(description=self.OK_WARN_SL_SET_ZERO, colour=roxbot.EmbedColours.pink) | |||
return await ctx.send(embed=embed) |
@@ -24,137 +24,79 @@ | |||
import datetime | |||
import typing | |||
import discord | |||
from discord.ext import commands | |||
import roxbot | |||
ags_id = 393764974444675073 | |||
selfieperms = 394939389823811584 | |||
nsfwimageperms = 394941004043649036 | |||
newbie = 450042170112475136 | |||
tat_token = roxbot.config["Tokens"]["Tatsumaki"] | |||
def is_ags(): | |||
return commands.check(lambda ctx: ctx.guild.id == ags_id) | |||
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": tat_token}) | |||
class AssortedGenderSounds(commands.Cog): | |||
"""Custom Cog for the AssortedGenderSounds Discord Server.""" | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.acceptable_roles = (nsfwimageperms, selfieperms) | |||
self.settings = { | |||
"limited_to_guild": str(ags_id), | |||
"ags": { | |||
"log_channel": "", | |||
"required_days": "", | |||
"required_score": "", | |||
} | |||
} | |||
self.required_score = 2000 | |||
self.days = 5 | |||
self.logging_channel_id = 394959819796381697 | |||
self.newbie_role_id = 450042170112475136 | |||
self.selfie_role_id = 394939389823811584 | |||
self.ags_id = 393764974444675073 | |||
self.tat_token = roxbot.config["Tokens"]["Tatsumaki"] | |||
self.bot.add_listener(self.grab_objects, "on_ready") | |||
self.ags = None | |||
self.selfie_role = None | |||
self.newbie_role = None | |||
self.logging_channel = None | |||
async def cog_check(self, ctx): | |||
return ctx.guild.id == self.ags_id | |||
async def grab_objects(self): | |||
self.ags = self.bot.get_guild(self.ags_id) | |||
self.selfie_role = self.ags.get_role(self.selfie_role_id) | |||
self.newbie_role = self.ags.get_role(self.newbie_role_id) | |||
self.logging_channel = self.ags.get_channel(self.logging_channel_id) | |||
@commands.Cog.listener() | |||
async def on_member_join(self, member): | |||
if member.guild.id == ags_id: | |||
role = member.guild.get_role(newbie) | |||
await member.add_roles(role, reason="Auto-add role on join") | |||
if member.guild == self.ags: | |||
await member.add_roles(self.newbie_role, reason="Auto-add role on join") | |||
await member.send("Please read our <#396697172139180033> and <#422514427263188993> channels. To gain access to the server, you must agree to the rules.") | |||
async def tatsumaki_api_call(self, 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": self.tat_token}) | |||
@commands.command() | |||
async def agree(self, ctx): | |||
role = ctx.guild.get_role(newbie) | |||
try: | |||
return await ctx.author.remove_roles(role, reason="User has agreed the rules and has been given access to the server.") | |||
return await ctx.author.remove_roles(self.newbie_role, reason="User has agreed the rules and has been given access to the server.") | |||
except discord.HTTPException: | |||
pass | |||
@commands.command(hidden=True) | |||
async def perms(self, ctx, role): | |||
"""Shell command to do the perm assigning. Only should be invoked by another command.""" | |||
# Just in case some cunt looks at the source code and thinks they can give themselves Admin. | |||
if role.id not in self.acceptable_roles: | |||
return False | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
@commands.command(name="selfieperms") | |||
async def selfie_perms(self, ctx): | |||
"""Requests the selfie perm role.""" | |||
member = ctx.author | |||
required_score = settings["ags"]["required_score"] | |||
days = int(settings["ags"]["required_days"]) | |||
data = await tatsumaki_api_call(member, ctx.guild) | |||
data = await self.tatsumaki_api_call(member, ctx.guild) | |||
if data is None: | |||
return await ctx.send("Tatsumaki API call returned nothing. Maybe the API is down?") | |||
if role in member.roles: | |||
await member.remove_roles(role, reason="Requested removal of {0.name}".format(role)) | |||
return await ctx.send("You already had {0.name}. It has now been removed.".format(role)) | |||
if self.selfie_role in member.roles: | |||
await member.remove_roles(self.selfie_role, reason="Requested removal of {0.name}".format(self.selfie_role)) | |||
return await ctx.send("You already had {0.name}. It has now been removed.".format(self.selfie_role)) | |||
time = datetime.datetime.now() - ctx.author.joined_at | |||
if time > datetime.timedelta(days=days) and int(data["score"]) >= required_score: | |||
await member.add_roles(role, reason="Requested {0.name}".format(role)) | |||
await ctx.send("You now have the {0.name} role".format(role)) | |||
if time > datetime.timedelta(days=self.days) and int(data["score"]) >= self.required_score: | |||
await member.add_roles(self.selfie_role, reason="Requested {0.name}".format(self.selfie_role)) | |||
await ctx.send("You now have the {0.name} role".format(self.selfie_role)) | |||
else: | |||
return await ctx.send( | |||
"You do not meet the requirements for this role. You need at least {} score with <@!172002275412279296> and to have been in the server for {} days.".format(required_score, days) | |||
"You do not meet the requirements for this role. You need at least {} score with <@!172002275412279296> and to have been in the server for {} days.".format(self.required_score, self.days) | |||
) | |||
@is_ags() | |||
@commands.command() | |||
async def selfieperms(self, ctx): | |||
"""Requests the selfie perm role.""" | |||
arg = None | |||
for role in ctx.guild.roles: | |||
if role.id == selfieperms: | |||
arg = role | |||
if not arg: | |||
return ctx.send("Error, message roxie thanks.") | |||
return await ctx.invoke(self.perms, role=arg) | |||
#@is_not_nsfw_disabled() | |||
@is_ags() | |||
@commands.command(hidden=True, enabled=False) | |||
async def nsfwperms(self, ctx): | |||
"""Requests the NSFW Image Perm role.""" | |||
arg = None | |||
for role in ctx.guild.roles: | |||
if role.id == nsfwimageperms: | |||
arg = role | |||
if not arg: | |||
return ctx.send("Error, message roxie thanks.") | |||
return await ctx.invoke(self.perms, role=arg) | |||
@commands.command() | |||
async def ags(self, ctx, selection, amount: typing.Optional[int], *, channel: typing.Optional[discord.TextChannel] = None): | |||
selection = selection.lower() | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
ags = settings["ags"] | |||
if selection == "log_channel": | |||
if not channel: | |||
channel = ctx.channel | |||
elif ctx.message.channel_mentions: | |||
channel = ctx.channel_mentions[0] | |||
else: | |||
channel = ctx.guild.get_channel(channel) | |||
ags["log_channel"] = channel.id | |||
await ctx.send("Logging Channel set to '{}'".format(channel.name)) | |||
elif selection == "required_days": | |||
ags["required_days"] = amount | |||
await ctx.send("Required days set to '{}'".format(str(amount))) | |||
elif selection == "required_score": | |||
ags["required_score"] = amount | |||
await ctx.send("Required score set to '{}'".format(str(amount))) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(ags, "ags") | |||
def setup(bot_client): | |||
bot_client.add_cog(AssortedGenderSounds(bot_client)) |
@@ -29,6 +29,16 @@ import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot.db import * | |||
class CCCommands(db.Entity): | |||
# Sadly no way to add a custom constraint to this while we either use pony or sqlite/ | |||
name = Required(str) | |||
output = Required(Json) | |||
type = Required(int, py_check=lambda val: 0 <= val <= 2) | |||
guild_id = Required(int, size=64) | |||
composite_key(name, guild_id) | |||
class CustomCommands(commands.Cog): | |||
@@ -52,21 +62,11 @@ class CustomCommands(commands.Cog): | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.embed_fields = ("title", "description", "colour", "color", "footer", "image", "thumbnail", "url") | |||
self.settings = { | |||
"custom_commands": { | |||
"0": {}, | |||
"1": {}, | |||
"2": {}, | |||
"convert": {"0": "hide", "1": "hide", "2": "hide"} | |||
} | |||
} | |||
@staticmethod | |||
def _get_output(command): | |||
# Check for a list as the output. If so, randomly select a item from the list. | |||
if isinstance(command, list): | |||
command = random.choice(command) | |||
return command | |||
return random.choice(command) | |||
@staticmethod | |||
def _cc_to_embed(command_output): | |||
@@ -121,26 +121,32 @@ class CustomCommands(commands.Cog): | |||
# Emulate Roxbot's blacklist system | |||
if self.bot.blacklisted(message.author): | |||
raise commands.CheckFailure() | |||
raise commands.CheckFailure | |||
settings = roxbot.guild_settings.get(message.guild) | |||
msg = message.content.lower() | |||
channel = message.channel | |||
if msg.startswith(self.bot.command_prefix): | |||
command = msg.split(self.bot.command_prefix)[1] | |||
if command in settings["custom_commands"]["1"]: | |||
command_output = self._get_output(settings["custom_commands"]["1"][command]) | |||
return await channel.send(command_output) | |||
elif command in settings["custom_commands"]["2"]: | |||
command_output = self._get_output(settings["custom_commands"]["2"][command]) | |||
embed = self._cc_to_embed(command_output) | |||
return await channel.send(embed=embed) | |||
else: | |||
for command in settings["custom_commands"]["0"]: | |||
if msg == command: | |||
command_output = self._get_output(settings["custom_commands"]["0"][command]) | |||
return await channel.send(command_output) | |||
with db_session: | |||
if msg.startswith(self.bot.command_prefix): | |||
command_name = msg.split(self.bot.command_prefix)[1] | |||
command = CCCommands.get(name=command_name, guild_id=message.guild.id) | |||
try: | |||
if command.type == 1: | |||
output = self._get_output(command.output) | |||
return await channel.send(output) | |||
elif command.type == 2: | |||
embed = self._cc_to_embed(command.output) | |||
return await channel.send(embed=embed) | |||
except AttributeError: | |||
pass | |||
else: | |||
try: | |||
command = CCCommands.get(name=msg, guild_id=message.guild.id, type=0) | |||
if command: | |||
output = self._get_output(command.output) | |||
return await channel.send(output) | |||
except: | |||
pass | |||
@commands.guild_only() | |||
@commands.group(aliases=["cc"]) | |||
@@ -175,18 +181,16 @@ class CustomCommands(commands.Cog): | |||
# Add an embed command called test3 with a title of "Title" and a description that is a markdown hyperlink to a youtube video, and the colour #deadbf | |||
;cc add embed test3 title "Title" description "[Click here for a rad video](https://www.youtube.com/watch?v=dQw4w9WgXcQ)" colour #deadbf | |||
Note: With custom commands, it is important to remember that "" is used to pass any text with spaces as one argument. If the output you want requires the use of these characters, surround your output with three speech quotes at either side instead. | |||
Note: With custom commands, it is important to remember that "" is used to pass any text with spaces as one argument. If the output you want requires the use of these characters, surround your output with three speech quotes at either side instead. | |||
""" | |||
command = command.lower() | |||
if command_type in ("0", "no_prefix", "no prefix"): | |||
command_type = "0" | |||
if len(output) == 1: | |||
output = output[0] | |||
command_type = 0 | |||
elif command_type in ("1", "prefix"): | |||
command_type = "1" | |||
if len(output) == 1: | |||
output = output[0] | |||
command_type = 1 | |||
elif command_type in ("2", "embed"): | |||
command_type = "2" | |||
command_type = 2 | |||
if len(output) < 2: | |||
raise roxbot.UserError(self.ERROR_EMBED_VALUE) | |||
try: | |||
@@ -196,26 +200,22 @@ class CustomCommands(commands.Cog): | |||
else: | |||
raise roxbot.UserError(self.ERROR_INCORRECT_TYPE) | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
no_prefix_commands = settings["custom_commands"]["0"] | |||
prefix_commands = settings["custom_commands"]["1"] | |||
embed_commands = settings["custom_commands"]["2"] | |||
command = command.lower() | |||
with db_session: | |||
if ctx.message.mentions or ctx.message.mention_everyone or ctx.message.role_mentions: | |||
raise roxbot.UserError(self.ERROR_AT_MENTION) | |||
elif len(output) > 1800: | |||
raise roxbot.UserError(self.ERROR_OUTPUT_TOO_LONG) | |||
elif command in self.bot.all_commands.keys() and command_type == "1": | |||
raise roxbot.UserError(self.ERROR_COMMAND_EXISTS_INTERNAL) | |||
elif command in no_prefix_commands or command in prefix_commands or command in embed_commands: | |||
raise roxbot.UserError(self.ERROR_COMMAND_EXISTS) | |||
elif len(command.split(" ")) > 1 and command_type == "1": | |||
raise roxbot.UserError(self.ERROR_PREFIX_SPACE) | |||
settings["custom_commands"][command_type][command] = output | |||
settings.update(settings["custom_commands"], "custom_commands") | |||
return await ctx.send(self.OUTPUT_ADD.format(command, output)) | |||
if ctx.message.mentions or ctx.message.mention_everyone or ctx.message.role_mentions: | |||
raise roxbot.UserError(self.ERROR_AT_MENTION) | |||
elif len(output) > 1800: | |||
raise roxbot.UserError(self.ERROR_OUTPUT_TOO_LONG) | |||
elif command in self.bot.all_commands.keys() and command_type == 1: | |||
raise roxbot.UserError(self.ERROR_COMMAND_EXISTS_INTERNAL) | |||
elif select(c for c in CCCommands if c.name == command and c.guild_id == ctx.guild.id).exists(): | |||
raise roxbot.UserError(self.ERROR_COMMAND_EXISTS) | |||
elif len(command.split(" ")) > 1 and command_type == "1": | |||
raise roxbot.UserError(self.ERROR_PREFIX_SPACE) | |||
CCCommands(name=command, guild_id=ctx.guild.id, output=output, type=command_type) | |||
return await ctx.send(self.OUTPUT_ADD.format(command, output if len(output) > 1 else output[0])) | |||
@commands.has_permissions(manage_messages=True) | |||
@custom.command() | |||
@@ -229,41 +229,29 @@ class CustomCommands(commands.Cog): | |||
For more examples of how to setup a custom command, look at the help for the ;custom add command. | |||
You cannot change the type of a command. If you want to change the type, remove the command and re-add it. | |||
""" | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
no_prefix_commands = settings["custom_commands"]["0"] | |||
prefix_commands = settings["custom_commands"]["1"] | |||
embed_commands = settings["custom_commands"]["2"] | |||
if ctx.message.mentions or ctx.message.mention_everyone or ctx.message.role_mentions: | |||
raise roxbot.UserError(self.ERROR_AT_MENTION) | |||
if command in no_prefix_commands: | |||
if len(edit) == 1: | |||
edit = edit[0] | |||
settings["custom_commands"]["0"][command] = edit | |||
settings.update(settings["custom_commands"], "custom_commands") | |||
return await ctx.send(self.OUTPUT_EDIT.format(command, edit)) | |||
elif command in prefix_commands: | |||
if len(edit) == 1: | |||
edit = edit[0] | |||
settings["custom_commands"]["1"][command] = edit | |||
settings.update(settings["custom_commands"], "custom_commands") | |||
return await ctx.send(self.OUTPUT_EDIT.format(command, edit)) | |||
elif command in embed_commands: | |||
if len(edit) < 2: | |||
raise roxbot.UserError(self.ERROR_EMBED_VALUE) | |||
try: | |||
edit = self._embed_parse_options(edit) | |||
except ValueError: | |||
raise roxbot.UserError(self.ERROR_OUTPUT_TOO_LONG) | |||
settings["custom_commands"]["2"][command] = edit | |||
settings.update(settings["custom_commands"], "custom_commands") | |||
return await ctx.send(self.OUTPUT_EDIT.format(command, edit)) | |||
else: | |||
raise roxbot.UserError(self.ERROR_COMMAND_NULL) | |||
if not edit: | |||
raise commands.BadArgument("Missing required argument: edit") | |||
with db_session: | |||
query = CCCommands.get(name=command.lower(), guild_id=ctx.guild.id) | |||
if query: | |||
if query.type == 2: | |||
if len(edit) < 2: | |||
raise roxbot.UserError(self.ERROR_EMBED_VALUE) | |||
try: | |||
edit = self._embed_parse_options(edit) | |||
query.output = edit | |||
return await ctx.send(self.OUTPUT_EDIT.format(command, edit)) | |||
except ValueError: | |||
raise roxbot.UserError(self.ERROR_OUTPUT_TOO_LONG) | |||
else: | |||
query.output = edit | |||
return await ctx.send(self.OUTPUT_EDIT.format(command, edit if len(edit) > 1 else edit[0])) | |||
else: | |||
raise roxbot.UserError(self.ERROR_COMMAND_NULL) | |||
@commands.has_permissions(manage_messages=True) | |||
@custom.command() | |||
@@ -274,61 +262,54 @@ class CustomCommands(commands.Cog): | |||
# Remove custom command called "test" | |||
;cc remove test | |||
""" | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
command = command.lower() | |||
no_prefix_commands = settings["custom_commands"]["0"] | |||
prefix_commands = settings["custom_commands"]["1"] | |||
embed_commands = settings["custom_commands"]["2"] | |||
if command in no_prefix_commands: | |||
command_type = "0" | |||
elif command in prefix_commands: | |||
command_type = "1" | |||
elif command in embed_commands: | |||
command_type = "2" | |||
else: | |||
raise roxbot.UserError(self.ERROR_COMMAND_NULL) | |||
settings["custom_commands"][command_type].pop(command) | |||
settings.update(settings["custom_commands"], "custom_commands") | |||
return await ctx.send(self.OUTPUT_REMOVE.format(command)) | |||
with db_session: | |||
c = CCCommands.get(name=command, guild_id=ctx.guild.id) | |||
if c: | |||
c.delete() | |||
return await ctx.send(self.OUTPUT_REMOVE.format(command)) | |||
else: | |||
raise roxbot.UserError(self.ERROR_COMMAND_NULL) | |||
@custom.command() | |||
async def list(self, ctx, debug="0"): | |||
"""Lists all custom commands for this guild.""" | |||
if debug != "0" and debug != "1": | |||
debug = "0" | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
cc = settings["custom_commands"] | |||
no_prefix_commands = cc["0"] | |||
prefix_commands = {**cc["1"], **cc["2"]} | |||
paginator = commands.Paginator() | |||
paginator.add_line("Here is the list of Custom Commands...") | |||
with db_session: | |||
no_prefix_commands = select(c for c in CCCommands if c.type == 0 and c.guild_id == ctx.guild.id)[:] | |||
prefix_commands = select(c for c in CCCommands if c.type == 1 and c.guild_id == ctx.guild.id)[:] | |||
embed_commands = select(c for c in CCCommands if c.type == 2 and c.guild_id == ctx.guild.id)[:] | |||
def add_commands(commands, paginator): | |||
if not commands: | |||
paginator.add_line("There are no commands setup.") | |||
else: | |||
for command in commands: | |||
output = command.name | |||
if debug == "1": | |||
output += " = '{}'".format(command.output if command.type == 2 else command.output[0]) | |||
paginator.add_line("- " + output) | |||
paginator = commands.Paginator(prefix="```md") | |||
paginator.add_line("__Here is the list of Custom Commands...__") | |||
paginator.add_line() | |||
paginator.add_line("Commands that require Prefix:") | |||
if not prefix_commands: | |||
paginator.add_line("There are no commands setup.") | |||
else: | |||
for command in prefix_commands: | |||
if debug == "1": | |||
command += " = '{}'".format(prefix_commands[command]) | |||
paginator.add_line("- " + command) | |||
paginator.add_line("__Prefix Commands (Non Embeds):__") | |||
add_commands(prefix_commands, paginator) | |||
paginator.add_line() | |||
paginator.add_line("__Prefix Commands (Embeds):__") | |||
add_commands(embed_commands, paginator) | |||
paginator.add_line() | |||
paginator.add_line("Commands that don't require prefix:") | |||
if not no_prefix_commands: | |||
paginator.add_line("There are no commands setup.") | |||
else: | |||
for command in no_prefix_commands: | |||
if debug == "1": | |||
command += " = '{}'".format(no_prefix_commands[command]) | |||
paginator.add_line("- " + command) | |||
output = paginator.pages | |||
for page in output: | |||
paginator.add_line("__Commands that don't require prefix:__") | |||
add_commands(no_prefix_commands, paginator) | |||
for page in paginator.pages: | |||
await ctx.send(page) | |||
@@ -29,48 +29,49 @@ import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings | |||
from roxbot.db import * | |||
class JoinLeaveSingle(db.Entity): | |||
greets_enabled = Required(bool, default=False) | |||
goodbyes_enabled = Required(bool, default=False) | |||
greets_channel_id = Optional(int, nullable=True, size=64) | |||
goodbyes_channel_id = Optional(int, nullable=True, size=64) | |||
greets_custom_message = Optional(str, nullable=True) | |||
guild_id = Required(int, size=64, unique=True) | |||
class JoinLeave(commands.Cog): | |||
"""JoinLeave is a cog that allows you to create custom welcome and goodbye messages for your Discord server. """ | |||
def __init__(self, Bot): | |||
self.bot = Bot | |||
self.settings = { | |||
"greets": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool", "welcome-channel": "channel"}, | |||
"welcome-channel": 0, | |||
"custom-message": "", | |||
"default-message": "Be sure to read the rules." | |||
}, | |||
"goodbyes": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool", "goodbye-channel": "channel"}, | |||
"goodbye-channel": 0, | |||
} | |||
} | |||
DEFAULT_MESSAGE = "Be sure to read the rules." | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.autogen_db = JoinLeaveSingle | |||
@commands.Cog.listener() | |||
async def on_member_join(self, member): | |||
""" | |||
Greets users when they join a server. | |||
""" | |||
settings = guild_settings.get(member.guild) | |||
if not settings["greets"]["enabled"]: | |||
if member == self.bot.user: | |||
return | |||
with db_session: | |||
settings = JoinLeaveSingle.get(guild_id=member.guild.id) | |||
if not settings.greets_enabled: | |||
return | |||
if settings["greets"]["custom-message"]: | |||
message = settings["greets"]["custom-message"] | |||
else: | |||
message = settings["greets"]["default-message"] | |||
message = settings.greets_custom_message or self.DEFAULT_MESSAGE | |||
em = discord.Embed( | |||
title="Welcome to {}!".format(member.guild), | |||
description='Hey {}! Welcome to **{}**! {}'.format(member.mention, member.guild, message), | |||
colour=roxbot.EmbedColours.pink) | |||
em.set_thumbnail(url=member.avatar_url) | |||
channel = member.guild.get_channel(settings["greets"]["welcome-channel"]) | |||
channel = member.guild.get_channel(settings.greets_channel_id) | |||
return await channel.send(embed=em) | |||
@commands.Cog.listener() | |||
@@ -78,27 +79,27 @@ class JoinLeave(commands.Cog): | |||
""" | |||
The same but the opposite | |||
""" | |||
settings = guild_settings.get(member.guild) | |||
channel = settings["goodbyes"]["goodbye-channel"] | |||
if not settings["goodbyes"]["enabled"]: | |||
if member == self.bot.user: | |||
return | |||
else: | |||
channel = member.guild.get_channel(channel) | |||
return await channel.send(embed=discord.Embed( | |||
description="{}#{} has left or been beaned.".format(member.name, member.discriminator), colour=roxbot.EmbedColours.pink)) | |||
with db_session: | |||
settings = JoinLeaveSingle.get(guild_id=member.guild.id) | |||
if settings.goodbyes_enabled: | |||
try: | |||
channel = member.guild.get_channel(settings.goodbyes_channel_id) | |||
return await channel.send(embed=discord.Embed( | |||
description="{}#{} has left or been beaned.".format(member.name, member.discriminator), colour=roxbot.EmbedColours.pink)) | |||
except AttributeError: | |||
pass | |||
@commands.Cog.listener() | |||
async def on_guild_channel_delete(self, channel): | |||
"""Cleans up settings on removal of stored IDs.""" | |||
settings = guild_settings.get(channel.guild) | |||
greets = settings["greets"] | |||
goodbyes = settings["goodbyes"] | |||
if channel.id == greets["welcome-channel"]: | |||
greets["welcome-channel"] = 0 | |||
settings.update(greets, "greets") | |||
if channel.id == goodbyes["goodbye-channel"]: | |||
goodbyes["goodbye-channel"] = 0 | |||
settings.update(goodbyes, "goodbyes") | |||
with db_session: | |||
settings = JoinLeaveSingle.get(guild_id=channel.guild.id) | |||
if channel.id == settings.greets_channel_id: | |||
settings.greets_channel_id = None | |||
if channel.id == settings.goodbyes_channel_id: | |||
settings.goodbyes_channel_id = None | |||
@commands.guild_only() | |||
@commands.has_permissions(manage_messages=True) | |||
@@ -117,28 +118,28 @@ class JoinLeave(commands.Cog): | |||
`;greets message "Be sure to read the rules and say hi! :wave:"` | |||
`;greets channel` # if no channel is provided, it will default to the channel the command is executed in. | |||
""" | |||
if (not channel and not text): | |||
raise commands.MissingRequiredArgument("Missing at least one of: `channel` or `text`") | |||
setting = setting.lower() | |||
settings = guild_settings.get(ctx.guild) | |||
greets = settings["greets"] | |||
if setting == "enable": | |||
greets["enabled"] = 1 | |||
await ctx.send("'greets' was enabled!") | |||
elif setting == "disable": | |||
greets["enabled"] = 0 | |||
await ctx.send("'greets' was disabled :cry:") | |||
elif setting in ("channel", "welcome-channel", "greet-channel"): | |||
if channel is None: | |||
channel = ctx.channel | |||
greets["welcome-channel"] = channel.id | |||
await ctx.send("Set greets channel to {}".format(channel.mention)) | |||
elif setting in ("message", "custom-message"): | |||
greets["custom-message"] = text | |||
await ctx.send("Custom message set to '{}'".format(text)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(greets, "greets") | |||
with db_session: | |||
settings = JoinLeaveSingle.get(guild_id=ctx.guild.id) | |||
if setting == "enable": | |||
settings.greets_enabled = True | |||
await ctx.send("'greets' was enabled!") | |||
elif setting == "disable": | |||
settings.greets_enabled = False | |||
await ctx.send("'greets' was disabled :cry:") | |||
elif setting in ("channel", "greet-channel"): | |||
channel = channel or ctx.channel | |||
settings.greets_channel_id = channel.id | |||
await ctx.send("Set greets channel to {}".format(channel.mention)) | |||
elif setting in ("message", "custom-message"): | |||
settings.greets_custom_message = text | |||
await ctx.send("Custom message set to '{}'".format(text)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
@commands.guild_only() | |||
@commands.has_permissions(manage_messages=True) | |||
@@ -156,22 +157,20 @@ class JoinLeave(commands.Cog): | |||
`;goodbyes channel #logs` | |||
""" | |||
setting = setting.lower() | |||
settings = guild_settings.get(ctx.guild) | |||
goodbyes = settings["goodbyes"] | |||
if setting == "enable": | |||
goodbyes["enabled"] = 1 | |||
await ctx.send("'goodbyes' was enabled!") | |||
elif setting == "disable": | |||
goodbyes["enabled"] = 0 | |||
await ctx.send("'goodbyes' was disabled :cry:") | |||
elif setting in ("channel", "goodbye-channel"): | |||
if channel is None: | |||
channel = ctx.channel | |||
goodbyes["goodbye-channel"] = channel.id | |||
await ctx.send("Set goodbye channel to {}".format(channel.mention)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(goodbyes, "goodbyes") | |||
def setup(Bot): | |||
Bot.add_cog(JoinLeave(Bot)) | |||
with db_session: | |||
settings = JoinLeaveSingle.get(guild_id=ctx.guild.id) | |||
if setting == "enable": | |||
settings.goodbyes_enabled = True | |||
await ctx.send("'goodbyes' was enabled!") | |||
elif setting == "disable": | |||
settings.goodbyes_enabled = False | |||
await ctx.send("'goodbyes' was disabled :cry:") | |||
elif setting in ("channel", "goodbye-channel"): | |||
channel = channel or ctx.channel | |||
settings.goodbyes_channel_id = channel.id | |||
await ctx.send("Set goodbye channel to {}".format(channel.mention)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
def setup(bot_client): | |||
bot_client.add_cog(JoinLeave(bot_client)) |
@@ -27,32 +27,33 @@ import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings as gs | |||
from roxbot.db import * | |||
def tag_blacklist(guild): | |||
blacklist = "" | |||
for tag in gs.get(guild)["nsfw"]["blacklist"]: | |||
blacklist += " -{}".format(tag) | |||
return blacklist | |||
class NSFWSingle(db.Entity): | |||
enabled = Required(bool, default=False) | |||
blacklisted_tags = Optional(StrArray) | |||
guild_id = Required(int, unique=True, size=64) | |||
class NFSW(commands.Cog): | |||
class NSFW(commands.Cog): | |||
"""The NSFW cog is a collection of commands that post images from popular NSFW sites. """ | |||
def __init__(self, bot_client): | |||
self.bot = bot_client | |||
self.cache = {} | |||
self.settings = { | |||
"nsfw": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool"}, | |||
"blacklist": [] | |||
} | |||
} | |||
self.autogen_db = NSFWSingle | |||
@db_session | |||
def tag_blacklist(self, guild): | |||
blacklist = "" | |||
blacklist_db = NSFWSingle.get(guild_id=guild.id).blacklisted_tags | |||
for tag in blacklist_db: | |||
blacklist += " -{}".format(tag) | |||
return blacklist | |||
async def gelbooru_clone(self, ctx, base_url, endpoint_url, tags): | |||
if isinstance(ctx.channel, discord.TextChannel): | |||
banned_tags = tag_blacklist(ctx.guild) | |||
banned_tags = self.tag_blacklist(ctx.guild) | |||
else: | |||
banned_tags = "" | |||
@@ -131,32 +132,29 @@ class NFSW(commands.Cog): | |||
# Remove "Roxbot" as a blacklisted tag | |||
;nsfw removebadtag Roxbot | |||
""" | |||
setting = setting.lower() | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
nsfw = settings["nsfw"] | |||
if setting == "enable": | |||
nsfw["enabled"] = 1 | |||
await ctx.send("'nsfw' was enabled!") | |||
elif setting == "disable": | |||
nsfw["enabled"] = 0 | |||
await ctx.send("'nsfw' was disabled :cry:") | |||
elif setting == "addbadtag": | |||
if changes not in nsfw["blacklist"]: | |||
nsfw["blacklist"].append(changes) | |||
await ctx.send("'{}' has been added to the blacklisted tag list.".format(changes)) | |||
with db_session: | |||
nsfw_settings = NSFWSingle.get(guild_id=ctx.guild.id) | |||
if setting == "enable": | |||
nsfw_settings.enabled = True | |||
await ctx.send("'nsfw' was enabled!") | |||
elif setting == "disable": | |||
nsfw_settings.enabled = False | |||
await ctx.send("'nsfw' was disabled :cry:") | |||
elif setting == "addbadtag": | |||
if changes not in nsfw_settings.blacklisted_tags: | |||
nsfw_settings.blacklisted_tags.append(changes) | |||
await ctx.send("'{}' has been added to the blacklisted tag list.".format(changes)) | |||
else: | |||
return await ctx.send("'{}' is already in the list.".format(changes)) | |||
elif setting == "removebadtag": | |||
try: | |||
nsfw_settings.blacklisted_tags.remove(changes) | |||
await ctx.send("'{}' has been removed from the blacklisted tag list.".format(changes)) | |||
except ValueError: | |||
return await ctx.send("That tag was not in the blacklisted tag list.") | |||
else: | |||
return await ctx.send("'{}' is already in the list.".format(changes)) | |||
elif setting == "removebadtag": | |||
try: | |||
nsfw["blacklist"].remove(changes) | |||
await ctx.send("'{}' has been removed from the blacklisted tag list.".format(changes)) | |||
except ValueError: | |||
return await ctx.send("That tag was not in the blacklisted tag list.") | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(nsfw, "nsfw") | |||
return await ctx.send("No valid option given.") | |||
def setup(bot_client): | |||
bot_client.add_cog(NFSW(bot_client)) | |||
bot_client.add_cog(NSFW(bot_client)) |
@@ -27,30 +27,32 @@ import discord | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings as gs | |||
from roxbot.db import * | |||
class SelfAssignRoles(db.Entity): | |||
role_id = Required(int, unique=True, size=64) | |||
guild_id = Required(int, size=64) | |||
class SelfAssignSingle(db.Entity): | |||
enabled = Required(bool, default=False) | |||
guild_id = Required(int, unique=True, size=64) | |||
class SelfAssign(commands.Cog): | |||
"""The SelfAssign cog allows guild's to mark roles as 'self assignable'. This allows users to give themselves these roles and to see all the roles marked as 'self assignable'.""" | |||
def __init__(self, Bot): | |||
self.bot = Bot | |||
self.settings = { | |||
"self_assign": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool", "roles": "role"}, | |||
"roles": [] | |||
} | |||
} | |||
self.autogen_db = SelfAssignSingle | |||
@commands.Cog.listener() | |||
async def on_guild_role_delete(self, role): | |||
"""Cleans up settings on removal of stored IDs.""" | |||
settings = gs.get(role.guild) | |||
sa = settings["self_assign"] | |||
for sa_role in sa["roles"]: | |||
if int(sa_role) == role.id: | |||
sa["roles"].remove(role.id) | |||
return settings.update(sa, "self_assign") | |||
with db_session: | |||
query = SelfAssignRoles.get(role_id=role.id) | |||
if query: | |||
query.delete() | |||
@commands.guild_only() | |||
@commands.has_permissions(manage_roles=True) | |||
@@ -67,37 +69,34 @@ class SelfAssign(commands.Cog): | |||
`;sa enable` | |||
`;sa add ROLE` | |||
""" | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
self_assign = settings["self_assign"] | |||
setting = setting.lower() | |||
if setting == "enable": | |||
self_assign["enabled"] = 1 | |||
await ctx.send("'self_assign' was enabled!") | |||
elif setting == "disable": | |||
self_assign["enabled"] = 0 | |||
await ctx.send("'self_assign' was disabled :cry:") | |||
elif setting == "add": | |||
try: | |||
if role.id in self_assign["roles"]: | |||
return await ctx.send("{} is already a self-assignable role.".format(role.name)) | |||
self_assign["roles"].append(role.id) | |||
await ctx.send('Role "{}" added'.format(str(role))) | |||
except AttributeError: | |||
raise commands.BadArgument("Could not find that role.") | |||
elif setting == "remove": | |||
try: | |||
if role.id in self_assign["roles"]: | |||
self_assign["roles"].remove(role.id) | |||
await ctx.send('"{}" has been removed from the self-assignable roles.'.format(str(role))) | |||
else: | |||
return await ctx.send("That role was not in the list.") | |||
except AttributeError: | |||
raise commands.BadArgument("Could not find that role.") | |||
else: | |||
return await ctx.send("No valid option given.") | |||
return settings.update(self_assign, "self_assign") | |||
with db_session: | |||
self_assign = SelfAssignSingle.get(guild_id=ctx.guild.id) | |||
if setting == "enable": | |||
self_assign.enabled = True | |||
await ctx.send("'self_assign' was enabled!") | |||
elif setting == "disable": | |||
self_assign.enabled = False | |||
await ctx.send("'self_assign' was disabled :cry:") | |||
elif setting == "add": | |||
try: | |||
SelfAssignRoles(role_id=role.id, guild_id=ctx.guild.id) | |||
await ctx.send('Role "{}" added'.format(str(role))) | |||
except AttributeError: | |||
raise commands.BadArgument("Could not find that role.") | |||
except TransactionIntegrityError: | |||
raise commands.BadArgument("{} is already a self-assignable role.".format(role.name)) | |||
elif setting == "remove": | |||
try: | |||
query = SelfAssignRoles.get(role_id=role.id) | |||
if query: | |||
query.delete() | |||
return await ctx.send('"{}" has been removed from the self-assignable roles.'.format(str(role))) | |||
else: | |||
return await ctx.send("That role was not in the list.") | |||
except AttributeError: | |||
raise commands.BadArgument("Could not find that role.") | |||
else: | |||
return await ctx.send("No valid option given.") | |||
@commands.guild_only() | |||
@commands.command(pass_context=True) | |||
@@ -105,18 +104,21 @@ class SelfAssign(commands.Cog): | |||
""" | |||
List's all roles that can be self-assigned on this server. | |||
""" | |||
settings = gs.get(ctx.guild) | |||
paginator = commands.Paginator(prefix="`", suffix="`") | |||
with db_session: | |||
self_assign = SelfAssignSingle.get(guild_id=ctx.guild.id) | |||
roles = select(r for r in SelfAssignRoles if r.guild_id == ctx.guild.id)[:] | |||
if not settings["self_assign"]["enabled"]: | |||
if not self_assign.enabled: | |||
embed = discord.Embed(colour=roxbot.EmbedColours.pink, description="SelfAssignable roles are not enabled on this server") | |||
return await ctx.send(embed=embed) | |||
paginator = commands.Paginator(prefix="`", suffix="`") | |||
paginator.add_line("The self-assignable roles for this server are: \n") | |||
for role in settings["self_assign"]["roles"]: | |||
for serverrole in ctx.guild.roles: | |||
if role == serverrole.id: | |||
paginator.add_line("- {}".format(serverrole.name)) | |||
for role in roles: | |||
r = ctx.guild.get_role(role.role_id) | |||
if r: | |||
paginator.add_line("- {}".format(r.name)) | |||
for page in paginator.pages: | |||
await ctx.send(page) | |||
@@ -130,9 +132,11 @@ class SelfAssign(commands.Cog): | |||
Example: | |||
.iam OverwatchPing | |||
""" | |||
settings = gs.get(ctx.guild) | |||
with db_session: | |||
self_assign = SelfAssignSingle.get(guild_id=ctx.guild.id) | |||
query = SelfAssignRoles.get(role_id=role.id) | |||
if not settings["self_assign"]["enabled"]: | |||
if not self_assign.enabled: | |||
embed = discord.Embed(colour=roxbot.EmbedColours.pink, description="SelfAssignable roles are not enabled on this server") | |||
return await ctx.send(embed=embed) | |||
@@ -141,7 +145,7 @@ class SelfAssign(commands.Cog): | |||
if role in member.roles: | |||
return await ctx.send("You already have that role.") | |||
if role.id in settings["self_assign"]["roles"]: | |||
if query: | |||
await member.add_roles(role, reason="'iam' command triggered.") | |||
return await ctx.send("Yay {}! You now have the {} role!".format(member.mention, role.name)) | |||
else: | |||
@@ -156,18 +160,20 @@ class SelfAssign(commands.Cog): | |||
Example: | |||
.iamn OverwatchPing | |||
""" | |||
settings = gs.get(ctx.guild) | |||
with db_session: | |||
self_assign = SelfAssignSingle.get(guild_id=ctx.guild.id) | |||
query = SelfAssignRoles.get(role_id=role.id) | |||
if not settings["self_assign"]["enabled"]: | |||
if not self_assign.enabled: | |||
embed = discord.Embed(colour=roxbot.EmbedColours.pink, description="SelfAssignable roles are not enabled on this server") | |||
return await ctx.send(embed=embed) | |||
member = ctx.author | |||
if role in member.roles and role.id in settings["self_assign"]["roles"]: | |||
if role in member.roles and query: | |||
await member.remove_roles(role, reason="'iamn' command triggered.") | |||
return await ctx.send("{} has been successfully removed.".format(role.name)) | |||
elif role not in member.roles and role.id in settings["self_assign"]["roles"]: | |||
elif role not in member.roles and query: | |||
return await ctx.send("You do not have {}.".format(role.name)) | |||
else: | |||
return await ctx.send("That role is not self-assignable.") |
@@ -33,6 +33,7 @@ import youtube_dl | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot.db import * | |||
# Suppress noise about console usage from errors | |||
youtube_dl.utils.bug_reports_message = lambda: '' | |||
@@ -58,14 +59,22 @@ ffmpeg_options = { | |||
ytdl = youtube_dl.YoutubeDL(ytdl_format_options) | |||
class VoiceSingle(db.Entity): | |||
need_perms = Required(bool, default=False) | |||
skip_voting = Required(bool, default=False) | |||
skip_ratio = Required(float, default=0.6, py_check=lambda v: 0 <= v <= 1) | |||
max_length = Required(int, default=600) | |||
guild_id = Required(int, size=64, unique=True) | |||
def need_perms(): | |||
def predicate(ctx): | |||
gs = roxbot.guild_settings.get(ctx.guild) | |||
if gs["voice"]["need_perms"]: | |||
with db_session: | |||
settings = VoiceSingle.get(guild_id=ctx.guild.id) | |||
if settings.need_perms: | |||
return roxbot.utils.has_permissions_or_owner(ctx, manage_channels=True) | |||
else: | |||
return True | |||
return commands.check(predicate) | |||
@@ -167,15 +176,7 @@ class Voice(commands.Cog): | |||
# Setup variables and then add dictionary entries for all guilds the bot can see on boot-up. | |||
self.bot = bot | |||
self.settings = { | |||
"voice": { | |||
"need_perms": 0, | |||
"skip_voting": 0, | |||
"skip_ratio": 0.6, | |||
"convert": {"need_perms": "bool", "skip_voting": "bool"}, | |||
"max_length": 600 | |||
} | |||
} | |||
self.autogen_db = VoiceSingle | |||
# TODO: Make this into a on roxbot joining voice thing instead of generating this for all servers on boot. | |||
self.refresh_rate = 1/60 # 60hz | |||
self._volume = {} | |||
@@ -290,7 +291,8 @@ class Voice(commands.Cog): | |||
;play https://www.youtube.com/watch?v=3uOPGkEJ56Q | |||
""" | |||
guild = ctx.guild | |||
voice = roxbot.guild_settings.get(guild)["voice"] | |||
with db_session: | |||
max_duration = VoiceSingle.get(guild_id=guild.id).max_length | |||
# Checks if invoker is in voice with the bot. Skips admins and mods and owner and if the song was queued previously. | |||
if not (roxbot.utils.has_permissions_or_owner(ctx, manage_channels=True) or from_queue): | |||
@@ -318,7 +320,7 @@ class Voice(commands.Cog): | |||
video = video["entries"][0] | |||
# Duration limiter handling | |||
if video.get("duration", 1) > voice["max_length"] and not roxbot.utils.has_permissions_or_owner(ctx, manage_channels=True): | |||
if video.get("duration", 1) > max_duration and not roxbot.utils.has_permissions_or_owner(ctx, manage_channels=True): | |||
raise commands.CommandError("Cannot play video, duration is bigger than the max duration allowed.") | |||
# Actual playing stuff section. | |||
@@ -420,8 +422,9 @@ class Voice(commands.Cog): | |||
# Force skip a video | |||
;skip --force | |||
""" | |||
voice = roxbot.guild_settings.get(ctx.guild)["voice"] | |||
if voice["skip_voting"] and not (option == "--force" and ctx.author.guild_permissions.manage_channels): # Admin force skipping | |||
with db_session: | |||
voice = VoiceSingle.get(guild_id=ctx.guild.id) | |||
if voice.skip_voting and not (option == "--force" and ctx.author.guild_permissions.manage_channels): # Admin force skipping | |||
if ctx.author in self.skip_votes[ctx.guild.id]: | |||
return await ctx.send("You have already voted to skip the current track.") | |||
else: | |||
@@ -429,7 +432,7 @@ class Voice(commands.Cog): | |||
# -1 due to the bot being counted in the members generator | |||
ratio = len(self.skip_votes[ctx.guild.id]) / (len(ctx.voice_client.channel.members) - 1) | |||
needed_users = ceil((len(ctx.voice_client.channel.members) - 1) * voice["skip_ratio"]) | |||
if ratio >= voice["skip_ratio"]: | |||
if ratio >= voice.skip_ratio: | |||
await ctx.send("{} voted the skip the video.".format(ctx.author)) | |||
await ctx.send("Votes to skip now playing has been met. Skipping video...") | |||
self.skip_votes[ctx.guild.id] = [] | |||
@@ -584,47 +587,46 @@ class Voice(commands.Cog): | |||
""" | |||
setting = setting.lower() | |||
change = change.lower() | |||
settings = roxbot.guild_settings.get(ctx.guild) | |||
voice = settings["voice"] | |||
if setting == "enable": | |||
if change in ("needperms", "need_perms"): | |||
voice["need_perms"] = 1 | |||
await ctx.send("'{}' has been enabled!".format(change)) | |||
elif change in ("skipvoting", "skip_voting"): | |||
voice["skip_voting"] = 1 | |||
await ctx.send("'{}' has been enabled!".format(change)) | |||
else: | |||
return await ctx.send("Not a valid change.") | |||
elif setting == "disable": | |||
if change == "needperms": | |||
voice["need_perms"] = 1 | |||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||
elif change == "skipvoting": | |||
voice["skip_voting"] = 1 | |||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||
else: | |||
return await ctx.send("Not a valid change.") | |||
elif setting in ("skipratio", "skip_ratio") : | |||
change = float(change) | |||
if 1 > change > 0: | |||
voice["skip_ratio"] = change | |||
elif 0 < change <= 100: | |||
change = change/10 | |||
voice["skip_ratio"] = change | |||
else: | |||
return await ctx.send("Valid ratio not given.") | |||
await ctx.send("Skip Ratio was set to {}".format(change)) | |||
elif setting in ("maxlength", "max_length"): | |||
change = int(change) | |||
if change >= 1: | |||
voice["max_length"] = change | |||
with db_session: | |||
voice = VoiceSingle.get(guild_id=ctx.guild.id) | |||
if setting == "enable": | |||
if change in ("needperms", "need_perms"): | |||
voice.need_perms = True | |||
await ctx.send("'{}' has been enabled!".format(change)) | |||
elif change in ("skipvoting", "skip_voting"): | |||
voice.skip_voting = True | |||
await ctx.send("'{}' has been enabled!".format(change)) | |||
else: | |||
return await ctx.send("Not a valid change.") | |||
elif setting == "disable": | |||
if change in ("skipvoting", "skip_voting"): | |||
voice.need_perms = False | |||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||
elif change in ("skipvoting", "skip_voting"): | |||
voice.skip_voting = False | |||
await ctx.send("'{}' was disabled :cry:".format(change)) | |||
else: | |||
return await ctx.send("Not a valid change.") | |||
elif setting in ("skipratio", "skip_ratio"): | |||
change = float(change) | |||
if 1 > change > 0: | |||
voice.skip_ratio = change | |||
elif 0 < change <= 100: | |||
change = change/10 | |||
voice.skip_ratio = change | |||
else: | |||
return await ctx.send("Valid ratio not given.") | |||
await ctx.send("Skip Ratio was set to {}".format(change)) | |||
elif setting in ("maxlength", "max_length"): | |||
change = int(change) | |||
if change >= 1: | |||
voice.max_length = change | |||
else: | |||
return await ctx.send("Valid max duration not given.") | |||
await ctx.send("Max Duration was set to {}".format(change)) | |||
else: | |||
return await ctx.send("Valid max duration not given.") | |||
await ctx.send("Max Duration was set to {}".format(change)) | |||
else: | |||
return await ctx.send("Valid option not given.") | |||
return settings.update(voice, "voice") | |||
return await ctx.send("Valid option not given.") | |||
def setup(bot_client): |
@@ -34,6 +34,17 @@ import youtube_dl | |||
from discord.ext import commands | |||
import roxbot | |||
from roxbot.db import * | |||
class LoggingSingle(db.Entity): | |||
enabled = Required(bool, default=False) | |||
logging_channel_id = Optional(int, nullable=True, size=64) | |||
guild_id = Required(int, unique=True, size=64) | |||
class Blacklist(db.Entity): | |||
user_id = Required(int, unique=True, size=64) | |||
class Roxbot(commands.Bot): | |||
@@ -51,11 +62,8 @@ class Roxbot(commands.Bot): | |||
Returns | |||
======= | |||
If the user is blacklisted: bool""" | |||
with open("roxbot/settings/blacklist.txt", "r") as fp: | |||
for line in fp.readlines(): | |||
if str(user.id) + "\n" == line: | |||
return True | |||
return False | |||
with db_session: | |||
return select(u for u in Blacklist if u.user_id == user.id).exists() | |||
async def delete_option(self, message, delete_emoji=None, timeout=20): | |||
"""Utility function that allows for you to add a delete option to the end of a command. | |||
@@ -107,9 +115,10 @@ class Roxbot(commands.Bot): | |||
""" | |||
if guild: | |||
logging = roxbot.guild_settings.get(guild)["logging"] | |||
channel = discord.utils.get(guild.channels, id=logging["channel"]) | |||
if logging["enabled"]: | |||
with db_session: | |||
logging = LoggingSingle.get(guild_id=guild.id) | |||
if logging.enabled and logging.logging_channel_id: | |||
channel = self.get_channel(logging.logging_channel_id) | |||
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) | |||
@@ -144,21 +153,15 @@ class Core(commands.Cog): | |||
self.bot.add_listener(self.log_member_join, "on_member_join") | |||
self.bot.add_listener(self.log_member_remove, "on_member_remove") | |||
self.settings = { | |||
"logging": { | |||
"enabled": 0, | |||
"convert": {"enabled": "bool", "channel": "channel"}, | |||
"channel": 0 | |||
} | |||
} | |||
self.autogen_db = LoggingSingle | |||
@staticmethod | |||
def command_not_found_check(ctx, error): | |||
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"]) | |||
with roxbot.db.db_session: | |||
is_custom_command = roxbot.db.db.exists('SELECT * FROM CCCommands WHERE name = "{}" AND type IN (1, 2) AND guild_id = {}'.format(ctx.invoked_with, ctx.guild.id)) | |||
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_emoticon_face: | |||
@@ -250,31 +253,40 @@ class Core(commands.Cog): | |||
@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") | |||
with db_session: | |||
settings = LoggingSingle.get(guild_id=channel.guild.id) | |||
if settings.logging_channel_id == channel.id: | |||
settings.logging_channel_id = None | |||
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"]) | |||
with db_session: | |||
settings = LoggingSingle.get(guild_id=member.guild.id) | |||
if settings.enabled: | |||
channel = member.guild.get_channel(settings.logging_channel_id) | |||
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.format(member.created_at)) | |||
embed.add_field(name="Date Joined", value=roxbot.datetime.format(member.joined_at)) | |||
embed.set_thumbnail(url=member.avatar_url) | |||
return await channel.send(embed=embed) | |||
try: | |||
return await channel.send(embed=embed) | |||
except AttributeError: | |||
pass | |||
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"]) | |||
if member == self.bot.user: | |||
return | |||
with db_session: | |||
settings = LoggingSingle.get(guild_id=member.guild.id) | |||
if settings.enabled: | |||
channel = member.guild.get_channel(settings.logging_channel_id) | |||
embed = discord.Embed(description="{} left the server".format(member), colour=roxbot.EmbedColours.pink) | |||
return await channel.send(embed=embed) | |||
try: | |||
return await channel.send(embed=embed) | |||
except AttributeError: | |||
pass | |||
@commands.has_permissions(manage_channels=True) | |||
@commands.guild_only() | |||
@@ -288,22 +300,22 @@ class Core(commands.Cog): | |||
""" | |||
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") | |||
with db_session: | |||
settings = LoggingSingle.get(guild_id=ctx.guild.id) | |||
if setting == "enable": | |||
settings.enabled = 1 | |||
return await ctx.send("'logging' was enabled!") | |||
elif setting == "disable": | |||
settings.enabled = 0 | |||
return await ctx.send("'logging' was disabled :cry:") | |||
elif setting == "channel": | |||
if not channel: | |||
channel = ctx.channel | |||
settings.enabled = channel.id | |||
return await ctx.send("{} has been set as the logging channel!".format(channel.mention)) | |||
else: | |||
return await ctx.send("No valid option given.") | |||
############# | |||
# Backups # | |||
@@ -311,19 +323,14 @@ class Core(commands.Cog): | |||
async def auto_backups(self): | |||
await self.bot.wait_until_ready() | |||
raw_settings = {} | |||
for guild in self.bot.guilds: | |||
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: | |||
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() | |||
roxbot.guild_settings.backup("{:%Y.%m.%d %H:%M:%S} Auto Backup".format(time)) | |||
time = datetime.datetime.now() | |||
filename = "{}/roxbot/settings/backups/{:%Y.%m.%d %H:%M:%S} Auto Backup.sql".format(os.getcwd(), time) | |||
con = sqlite3.connect(os.getcwd() + "/roxbot/settings/db.sqlite") | |||
with open(filename, 'w') as f: | |||
for line in con.iterdump(): | |||
f.write('%s\n' % line) | |||
con.close() | |||
await asyncio.sleep(roxbot.backup_rate) | |||
@commands.command(enabled=roxbot.backup_enabled) | |||
@@ -336,9 +343,13 @@ class Core(commands.Cog): | |||
Using only this and not the automatic backups is not recommend. | |||
""" | |||
time = datetime.datetime.now() | |||
filename = "{:%Y.%m.%d %H:%M:%S} Manual Backup".format(time) | |||
roxbot.guild_settings.backup(filename) | |||
return await ctx.send("Settings file backed up as a folder named '{}".format(filename)) | |||
filename = "{}/roxbot/settings/backups/{:%Y.%m.%d %H:%M:%S} Auto Backup.sql".format(os.getcwd(), time) | |||
con = sqlite3.connect(os.getcwd() + "/roxbot/settings/db.sqlite") | |||
with open(filename, 'w') as f: | |||
for line in con.iterdump(): | |||
f.write('%s\n' % line) | |||
con.close() | |||
return await ctx.send("Settings file backed up as a folder named '{}".format(filename.split("/")[-1])) | |||
############################ | |||
# Bot Managment Commands # | |||
@@ -369,32 +380,24 @@ class Core(commands.Cog): | |||
await ctx.send("The owner cannot be blacklisted.") | |||
users.remove(user) | |||
if option in ['+', 'add']: | |||
with open("roxbot/settings/blacklist.txt", "r") as fp: | |||
for user in users: | |||
for line in fp.readlines(): | |||
if user.id + "\n" in line: | |||
users.remove(user) | |||
with open("roxbot/settings/blacklist.txt", "a+") as fp: | |||
lines = fp.readlines() | |||
with db_session: | |||
if option in ['+', 'add']: | |||
for user in users: | |||
if user.id not in lines: | |||
fp.write("{}\n".format(user.id)) | |||
try: | |||
Blacklist(user_id=user.id) | |||
blacklist_amount += 1 | |||
return await ctx.send('{} user(s) have been added to the blacklist'.format(blacklist_amount)) | |||
except TransactionIntegrityError: | |||
await ctx.send("{} is already in the blacklist.".format(user)) | |||
return await ctx.send('{} user(s) have been added to the blacklist'.format(blacklist_amount)) | |||
elif option in ['-', 'remove']: | |||
with open("roxbot/settings/blacklist.txt", "r") as fp: | |||
lines = fp.readlines() | |||
with open("roxbot/settings/blacklist.txt", "w") as fp: | |||
elif option in ['-', 'remove']: | |||
for user in users: | |||
for line in lines: | |||
if str(user.id) + "\n" != line: | |||
fp.write(line) | |||
else: | |||
fp.write("") | |||
blacklist_amount += 1 | |||
u = Blacklist.get(user_id=user.id) | |||
if u: | |||
u.delete() | |||
blacklist_amount += 1 | |||
else: | |||
await ctx.send("{} isn't in the blacklist".format(user)) | |||
return await ctx.send('{} user(s) have been removed from the blacklist'.format(blacklist_amount)) | |||
@commands.command(aliases=["setavatar"]) | |||
@@ -488,55 +491,6 @@ class Core(commands.Cog): | |||
await self.bot.change_presence(status=discord_status) | |||
await ctx.send("**:ok:** Status set to {}".format(discord_status)) | |||
@staticmethod | |||
def _parse_setting(ctx, settings_to_copy, raw=False): | |||
settingcontent = "" | |||
setting = settings_to_copy.copy() | |||
convert = setting.get("convert", None) | |||
if convert is not None and not raw: | |||
for x in convert.keys(): | |||
converter = None | |||
if convert[x] == "bool": | |||
if setting[x] == 0: | |||
setting[x] = False | |||
else: | |||
setting[x] = True | |||
elif convert[x] == "channel": | |||
converter = ctx.guild.get_channel | |||
elif convert[x] == "role": | |||
converter = ctx.guild.get_role | |||
elif convert[x] in ("user", "member"): | |||
converter = ctx.guild.get_member | |||
elif convert[x] == "hide": | |||
converter = None | |||
setting[x] = "This is hidden. Please use other commands to get this data." | |||
else: | |||
converter = None | |||
if converter: | |||
if isinstance(setting[x], list): | |||
if len(setting[x]) >= 60: | |||
setting[x] = "There is too many {}s to display. Please use other commands to get this data.".format(convert[x]) | |||
else: | |||
new_entries = [] | |||
for entry in setting[x]: | |||
try: | |||
new_entries.append(str(converter(entry))) | |||
except AttributeError: | |||
new_entries.append(entry) | |||
setting[x] = new_entries | |||
else: | |||
try: | |||
setting[x] = converter(setting[x]) | |||
except AttributeError: | |||
pass | |||
for x in setting.items(): | |||
if x[0] != "convert": | |||
settingcontent += str(x).strip("()") + "\n" | |||
return settingcontent | |||
@commands.guild_only() | |||
@commands.command(aliases=["printsettingsraw"]) | |||
@commands.has_permissions(manage_guild=True) | |||
@@ -551,26 +505,39 @@ class Core(commands.Cog): | |||
# print settings just for the Admin cog. | |||
;printsettings Admin | |||
""" | |||
option = option.lower() | |||
config = roxbot.guild_settings.get(ctx.guild) | |||
settings = dict(config.settings.copy()) # Make a copy of settings so we don't change the actual settings. | |||
if option: | |||
option = option.lower() | |||
entities = {} | |||
for name, cog in self.bot.cogs.items(): | |||
try: | |||
entities[name.lower()] = cog.autogen_db | |||
except AttributeError: | |||
pass | |||
paginator = commands.Paginator(prefix="```py") | |||
paginator.add_line("{} settings for {}.\n".format(self.bot.user.name, ctx.message.guild.name)) | |||
if option in settings: | |||
raw = bool(ctx.invoked_with == "printsettingsraw") | |||
settingcontent = self._parse_setting(ctx, settings[option], raw=raw) | |||
if option in entities: | |||
#raw = bool(ctx.invoked_with == "printsettingsraw") | |||
with db_session: | |||
settings = entities[option].get(guild_id=ctx.guild.id).to_dict() | |||
settings.pop("id") | |||
settings.pop("guild_id") | |||
paginator.add_line("@{}".format(option)) | |||
paginator.add_line(settingcontent) | |||
paginator.add_line(str(settings)) | |||
for page in paginator.pages: | |||
await ctx.send(page) | |||
else: | |||
for setting in settings: | |||
raw = bool(ctx.invoked_with == "printsettingsraw") | |||
settingcontent = self._parse_setting(ctx, settings[setting], raw=raw) | |||
paginator.add_line("@{}".format(setting)) | |||
paginator.add_line(settingcontent) | |||
for page in paginator.pages: | |||
await ctx.send(page) | |||
with db_session: | |||
for name, entity in entities.items(): | |||
settings = entity.get(guild_id=ctx.guild.id).to_dict() | |||
settings.pop("id") | |||
settings.pop("guild_id") | |||
#raw = bool(ctx.invoked_with == "printsettingsraw") | |||
paginator.add_line("@{}".format(name)) | |||
paginator.add_line(str(settings)) | |||
for page in paginator.pages: | |||
await ctx.send(page) | |||
@commands.command() | |||
@commands.is_owner() |
@@ -0,0 +1,62 @@ | |||
# | |||
# 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 sqlite3 | |||
from os import getcwd | |||
from pony.orm import * | |||
db_dir = getcwd() + "/roxbot/settings/db.sqlite" | |||
db = Database() | |||
db.bind("sqlite", db_dir, create_db=True) | |||
# Entities are committed to the db in the main file during boot up | |||
async def populate_db(bot): | |||
db.generate_mapping(create_tables=True) | |||
await bot.wait_for("ready") | |||
populate_single_settings(bot) | |||
def populate_single_settings(bot): | |||
for guild in bot.guilds: | |||
for name, cog in bot.cogs.items(): | |||
try: | |||
if cog.autogen_db: | |||
with db_session: | |||
cog.autogen_db(guild_id=guild.id) | |||
except (AttributeError, TransactionIntegrityError): | |||
pass # No DB settings or already in place | |||
def delete_single_settings(guild): | |||
database = sqlite3.connect(db_dir) | |||
cursor = database.cursor() | |||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") | |||
for t in cursor.fetchall(): | |||
table = t[0] | |||
try: | |||
cursor.execute("DELETE FROM {} WHERE guild_id={}".format(table, guild.id)) | |||
except sqlite3.OperationalError: | |||
pass # Table doesn't store guild_id | |||
database.commit() | |||
database.close() |
@@ -1,230 +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 os | |||
import json | |||
import errno | |||
import shutil | |||
def _open_config(server, cogs): | |||
"""Opens the guild settings file | |||
servers: server id str | |||
cogs: list of cog names | |||
Returns | |||
======= | |||
servers.json: dict | |||
""" | |||
settings = {} | |||
for cog in cogs: | |||
with open('roxbot/settings/servers/{}/{}'.format(server, cog), 'r') as config_file: | |||
settings = {**settings, **json.load(config_file)} | |||
return settings | |||
def _write_changes(guild_id, cogs, config): | |||
""" | |||
:param guild_id: | |||
:param cogs: | |||
:param config: | |||
:return: | |||
""" | |||
for cog in cogs: | |||
with open('roxbot/settings/servers/{}/{}'.format(guild_id, cog), "r") as conf_file: | |||
file = json.load(conf_file) | |||
with open('roxbot/settings/servers/{}/{}'.format(guild_id, cog), "w") as conf_file: | |||
for key in config.keys(): | |||
if key in file.keys(): | |||
file[key] = config[key] | |||
json.dump(file, conf_file) | |||
def backup(name): | |||
try: | |||
shutil.copytree('roxbot/settings/servers', 'roxbot/settings/backups/{}'.format(name)) | |||
except OSError as e: | |||
# If the error was caused because the source wasn't a directory | |||
if e.errno == errno.ENOTDIR: | |||
shutil.copy('roxbot/settings/servers', 'roxbot/settings/backups/{}'.format(name)) | |||
else: | |||
print('Directory not copied. Error: %s' % e) | |||
def _make_cog_json_file(server_id, name, data): | |||
with open("roxbot/settings/servers/{}/{}.json".format(server_id, name), "w") as fp: | |||
return json.dump(data, fp) | |||
def _check_for_missing_cog(server_id, name, cog): | |||
try: | |||
if cog.settings: | |||
settings = cog.settings.copy() | |||
limited = settings.get("limited_to_guild") | |||
if limited: | |||
if limited != server_id: | |||
return False | |||
else: | |||
settings.pop("limited_to_guild") | |||
if "{}.json".format(name) not in os.listdir("roxbot/settings/servers/{}".format(server_id)): | |||
_make_cog_json_file(server_id, name, settings) | |||
return True | |||
except AttributeError: | |||
pass # If Cog has no settings | |||
return False | |||
def _make_server_folder(server, cogs): | |||
os.mkdir("roxbot/settings/servers/{}".format(str(server.id))) | |||
for name, cog in cogs.items(): | |||
_check_for_missing_cog(str(server.id), name, cog) | |||
def error_check(servers, cogs): | |||
# Check for missing servers folder | |||
if "servers" not in os.listdir("roxbot/settings/"): | |||
print("WARNING: Settings folder not found, making new default settings folder.") | |||
os.mkdir("roxbot/settings/servers") | |||
for server in servers: | |||
_make_server_folder(server, cogs) | |||
else: | |||
for server in servers: | |||
# Check for missing server | |||
if str(server.id) not in os.listdir("roxbot/settings/servers/"): | |||
_make_server_folder(server, cogs) | |||
print("WARNING: The settings folder for {} was not found. The defaults have been created.".format(str(server))) | |||
# Check for missing cog settings | |||
for name, cog in cogs.items(): | |||
resp = _check_for_missing_cog(str(server.id), name, cog) | |||
if resp: | |||
print("WARNING: The settings folder for {} is missing the file {}. The defaults have been created.".format(str(server), name)) | |||
def remove_guild(guild): | |||
"""Removes given guild from settings folders and saves changes.""" | |||
shutil.rmtree('roxbot/settings/server/{}'.format(guild.id)) | |||
def add_guild(guild, cogs): | |||
"""Adds given guild to settings folder saves changes.""" | |||
_make_server_folder(guild, cogs) | |||
def get(guild): | |||
""" | |||
Gets a single GuildSettings Object representing the settings of that guild | |||
:param guild: :type discord.Guild: | |||
:return Single GuildSettings Object: :type GuildSettings: | |||
""" | |||
return GuildSettings(guild) | |||
class GuildSettings(object): | |||
""" | |||
An Object to store all settings for one guild. | |||
The goal is to make editing settings a lot easier and make it so you don't have to handle things like ID's which caused a lot of issues when moving over to discord.py 1.0 | |||
""" | |||
__slots__ = ["settings", "id", "name", "cogs"] | |||
def __init__(self, guild): | |||
self.id = guild.id | |||
self.name = str(guild) | |||
self.cogs = os.listdir("roxbot/settings/servers/{}".format(self.id)) | |||
self.settings = self.refresh() | |||
def __str__(self): | |||
return self.name | |||
def __iter__(self): | |||
list_settings = list(self.settings) | |||
list_settings.sort() | |||
for setting in list_settings: | |||
yield setting | |||
def __getitem__(self, key): | |||
return self.settings[key] | |||
@staticmethod | |||
def _convert(settings, option="int"): | |||
""" | |||
Converts values between int and str in the settings dict/json. Required due to how ID's are ints in discord.py | |||
and we can't store int's that big in a json file. | |||
:param settings: | |||
:param option: | |||
:return: | |||
""" | |||
for key, setting in settings.items(): | |||
if setting.get("convert"): | |||
for x in setting["convert"].keys(): | |||
if setting["convert"][x] not in ("bool", "hide"): | |||
if isinstance(setting[x], list): | |||
for y, value in enumerate(setting[x]): | |||
if option == "str": | |||
setting[x][y] = str(value) | |||
else: | |||
setting[x][y] = int(value) | |||
else: | |||
if option == "str": | |||
setting[x] = str(setting[x]) | |||
else: | |||
setting[x] = int(setting[x]) | |||
settings[key] = setting | |||
return settings | |||
def refresh(self): | |||
""" | |||
Open the settings, convert them to a usable format, and return for roxbot usage. | |||
:return: | |||
""" | |||
settings = _open_config(self.id, self.cogs) | |||
self._convert(settings) | |||
return settings | |||
def update(self, changed_dict, setting = None): | |||
""" | |||
Get latest settings, and update them with a change. | |||
:param changed_dict: | |||
:param setting: Setting should be a str of the setting key. | |||
If nothing is passed, it is assumed changed_dict is the settings file for the whole server. | |||
THIS IS NOT RECOMMENED. Always try and just pass the cogs settings and not a whole settings file. | |||
:return: | |||
""" | |||
self.settings = self.refresh() | |||
settings = self.settings.copy() | |||
if setting is not None: | |||
settings[setting] = changed_dict | |||
elif isinstance(changed_dict, dict): | |||
settings = changed_dict | |||
elif isinstance(changed_dict, GuildSettings): | |||
settings = changed_dict.settings | |||
else: | |||
raise TypeError("changed_dict can only be a dict or GuildSettings object.") | |||
settings = self._convert(settings, "str") | |||
_write_changes(self.id, self.cogs, settings) |
@@ -0,0 +1,130 @@ | |||
#!/usr/bin/env python3 | |||
# -*- 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 os | |||
import json | |||
import hashlib | |||
import datetime | |||
from roxbot.db import * | |||
from roxbot.cogs.customcommands import CCCommands | |||
@db_session | |||
def admin_convert(guild_id, settings): | |||
warning_limit = settings.get("warning_limit", None) | |||
if warning_limit is not None: | |||
db.execute("UPDATE AdminSingle SET `warning_limit` = {} WHERE `guild_id` = {}".format(warning_limit, guild_id)) | |||
db.commit() | |||
warnings = settings.get("warnings", None) | |||
if warnings is None: | |||
return | |||
for user, warns in warnings.items(): | |||
user_id = int(user) | |||
for warn in warns: | |||
date = datetime.datetime.fromtimestamp(warn["date"]) | |||
try: | |||
db.insert("AdminWarnings", user_id=user_id, guild_id=guild_id, date=date, warning=warn["warning"], warned_by=warn["warned-by"]) | |||
db.commit() | |||
except (TransactionIntegrityError, IntegrityError): | |||
pass | |||
@db_session | |||
def custom_commands_convert(guild_id, settings): | |||
for com_type, commands in settings.items(): | |||
if com_type != "convert": | |||
for name, command in commands.items(): | |||
com_hash = hashlib.md5(name.encode() + str(guild_id).encode() + str(com_type).encode()).hexdigest() | |||
if isinstance(command, str): | |||
com = [command] | |||
else: | |||
com = command | |||
try: | |||
CCCommands(name=name, hash=com_hash, output=com, type=int(com_type), guild_id=guild_id) | |||
db.commit() | |||
except (TransactionIntegrityError, CacheIndexError, IntegrityError): | |||
pass | |||
@db_session | |||
def joinleave_convert(guild_id, settings): | |||
greet = settings["greets"] | |||
goodbye = settings["goodbyes"] | |||
db.execute("UPDATE `JoinLeaveSingle` SET `greets_enabled` = {} WHERE `guild_id` = {}".format(greet["enabled"], guild_id)) | |||
db.execute("UPDATE `JoinLeaveSingle` SET `goodbyes_enabled` = {} WHERE `guild_id` = {}".format(goodbye["enabled"], guild_id)) | |||
db.execute("UPDATE `JoinLeaveSingle` SET `greets_channel_id` = {} WHERE `guild_id` = {}".format(greet["welcome-channel"], guild_id)) | |||
db.execute("UPDATE `JoinLeaveSingle` SET `goodbyes_channel_id` = {} WHERE `guild_id` = {}".format(goodbye["goodbye-channel"], guild_id)) | |||
db.execute("UPDATE `JoinLeaveSingle` SET `greets_custom_message` = '{}' WHERE `guild_id` = {}".format(greet["custom-message"],guild_id)) | |||
@db_session | |||
def nsfw_convert(guild_id, settings): | |||
db.execute("UPDATE `NSFWSingle` SET `enabled` = {} WHERE `guild_id` = {}".format(settings["enabled"], guild_id)) | |||
db.execute('UPDATE `NSFWSingle` SET `blacklisted_tags` = "{}" WHERE `guild_id` = {}'.format(settings["blacklist"], guild_id)) | |||
@db_session | |||
def logging_convert(guild_id, settings): | |||
db.execute("UPDATE `LoggingSingle` SET `enabled` = {} WHERE `guild_id` = {}".format(settings["enabled"], guild_id)) | |||
db.execute('UPDATE `LoggingSingle` SET `logging_channel_id` = "{}" WHERE `guild_id` = {}'.format(settings["channel"], guild_id)) | |||
@db_session | |||
def voice_convert(guild_id, settings): | |||
db.execute("UPDATE `VoiceSingle` SET `need_perms` = {} WHERE `guild_id` = {}".format(settings["need_perms"], guild_id)) | |||
db.execute("UPDATE `VoiceSingle` SET `skip_voting` = {} WHERE `guild_id` = {}".format(settings["skip_voting"], guild_id)) | |||
db.execute("UPDATE `VoiceSingle` SET `skip_ratio` = {} WHERE `guild_id` = {}".format(settings["skip_ratio"], guild_id)) | |||
db.execute("UPDATE `VoiceSingle` SET `max_length` = {} WHERE `guild_id` = {}".format(settings["max_length"], guild_id)) | |||
@db_session | |||
def selfassign_convert(guild_id, settings): | |||
db.execute("UPDATE `SelfAssignSingle` SET `enabled` = {} WHERE `guild_id` = {}".format(settings["enabled"], guild_id)) | |||
for role in settings["roles"]: | |||
try: | |||
db.insert("SelfAssignRoles", role_id=role, guild_id=guild_id) | |||
except IntegrityError: | |||
pass | |||
def check_convert(guilds): | |||
if os.path.isdir(os.getcwd() + "/roxbot/settings/servers"): | |||
for guild in guilds: | |||
settings = {} | |||
for cog in ("Admin.json", "Core.json", "CustomCommands.json", "JoinLeave.json", "NFSW.json", "SelfAssign.json", "Voice.json"): | |||
with open('roxbot/settings/servers/{}/{}'.format(guild.id, cog), 'r') as config_file: | |||
settings = {**settings, **json.load(config_file)} | |||
admin_convert(guild.id, settings["admin"]) | |||
custom_commands_convert(guild.id, settings["custom_commands"]) | |||
joinleave = {} | |||
joinleave["greets"] = settings["greets"] | |||
joinleave["goodbyes"] = settings["goodbyes"] | |||
joinleave_convert(guild.id, joinleave) | |||
nsfw_convert(guild.id, settings["nsfw"]) | |||
logging_convert(guild.id, settings["logging"]) | |||
voice_convert(guild.id, settings["voice"]) | |||
selfassign_convert(guild.id, settings["self_assign"]) | |||
os.rename(os.getcwd() + "/roxbot/settings/servers", os.getcwd() + "/roxbot/settings/servers.old") |
@@ -20,4 +20,4 @@ Imgur=TokenHere | |||
; enabled: Whether or not backups should be enabled. This is heavily recommened to be kept on. | |||
; 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=5 | |||
rate=30 |