diff --git a/.gitignore b/.gitignore index f4ca4c697..c39171c95 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ __pycache__ data !data/trivia/* !data/audio/playlists/* +*.exe +*.dll \ No newline at end of file diff --git a/cogs/alias.py b/cogs/alias.py new file mode 100644 index 000000000..7d2889415 --- /dev/null +++ b/cogs/alias.py @@ -0,0 +1,121 @@ +import discord +from discord.ext import commands +from .utils.chat_formatting import * +from .utils.dataIO import fileIO +from .utils import checks +from __main__ import send_cmd_help +import os + +class Alias: + def __init__(self,bot): + self.bot = bot + self.aliases = fileIO("data/alias/aliases.json","load") + + @commands.group(pass_context=True) + @checks.mod_or_permissions(manage_server=True) + async def alias(self,ctx): + """Manage per-server aliases for commands""" + if ctx.invoked_subcommand is None: + await send_cmd_help(ctx) + + @alias.command(name="add",pass_context=True) + async def _add_alias(self,ctx,command : str,*,to_execute): + """Add an alias for a command + + Example: !alias add test penis @TwentySix""" + server = ctx.message.server + if self.get_prefix(to_execute) == False: + to_execute = self.bot.command_prefix[0] + to_execute + if server.id not in self.aliases: + self.aliases[server.id] = {} + #curr_aliases = self.aliases[server.id] + if command not in self.bot.commands: + self.aliases[server.id][command] = to_execute + fileIO("data/alias/aliases.json","save",self.aliases) + await self.bot.say("Alias '{}' added.".format(command)) + else: + await self.bot.say("Cannot add '{}' because it's a real bot command.".format(command)) + + @alias.command(name="help",pass_context=True) + async def _help_alias(self,ctx,command): + """Tries to execute help for the base command of the alias""" + server = ctx.message.server + if server.id in self.aliases: + server_aliases = self.aliases[server.id] + if command in server_aliases: + help_cmd = server_aliases[command].split(" ")[0] + new_content = self.bot.command_prefix[0] + new_content += "help " + new_content += help_cmd[len(self.get_prefix(help_cmd)):] + message = ctx.message + message.content = new_content + await self.bot.process_commands(message) + else: + await self.bot.say("That alias doesn't exist.") + + @alias.command(name="show",pass_context=True) + async def _show_alias(self,ctx,command): + """Shows what command the alias executes.""" + server = ctx.message.server + if server.id in self.aliases: + server_aliases = self.aliases[server.id] + if command in server_aliases: + await self.bot.say(box(server_aliases[command])) + else: + await self.bot.say("That alias doesn't exist.") + + @alias.command(name="del",pass_context=True) + async def _del_alias(self,ctx,command : str): + """Deletes an alias""" + server = ctx.message.server + if server.id in self.aliases: + self.aliases[server.id].pop(command,None) + fileIO("data/alias/aliases.json","save",self.aliases) + await self.bot.say("Alias '{}' deleted.".format(command)) + + async def check_aliases(self,message): + if message.author.id == self.bot.user.id or len(message.content) < 2 or message.channel.is_private: + return + + msg = message.content + server = message.server + prefix = self.get_prefix(msg) + + if prefix and server.id in self.aliases: + aliaslist = self.aliases[server.id] + alias = msg[len(prefix):].split(" ")[0] + args = msg[len(self.first_word(message.content)):] + if alias in aliaslist.keys(): + content = aliaslist[alias] + args + new_message = message + new_message.content = content + await self.bot.process_commands(new_message) + + def first_word(self,msg): + return msg.split(" ")[0] + + def get_prefix(self, msg): + for p in self.bot.command_prefix: + if msg.startswith(p): + return p + return False + +def check_folder(): + if not os.path.exists("data/alias"): + print("Creating data/alias folder...") + os.makedirs("data/alias") + +def check_file(): + aliases = {} + + f = "data/alias/aliases.json" + if not fileIO(f, "check"): + print("Creating default alias's aliases.json...") + fileIO(f, "save", aliases) + +def setup(bot): + check_folder() + check_file() + n = Alias(bot) + bot.add_listener(n.check_aliases, "on_message") + bot.add_cog(n) \ No newline at end of file diff --git a/cogs/audio.py b/cogs/audio.py index c374c6f06..0ed425271 100644 --- a/cogs/audio.py +++ b/cogs/audio.py @@ -2,21 +2,31 @@ import discord from discord.ext import commands import asyncio import threading -import youtube_dl import os from random import choice as rndchoice from random import shuffle from .utils.dataIO import fileIO from .utils import checks from __main__ import send_cmd_help +from __main__ import settings as bot_settings import glob import re import aiohttp import json import time -if not discord.opus.is_loaded(): - discord.opus.load_opus('libopus-0.dll') +try: + import youtube_dl +except: + youtube_dl = None + +try: + if not discord.opus.is_loaded(): + discord.opus.load_opus('libopus-0.dll') +except: + opus = None +else: + opus = True youtube_dl_options = { 'format': 'bestaudio/best', @@ -60,7 +70,7 @@ class Audio: msg = ctx.message if await self.check_voice(msg.author, msg): if self.is_playlist_valid([link]): # reusing a function - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): self.queue = [] self.current = -1 self.playlist = [] @@ -119,7 +129,7 @@ class Audio: """ msg = ctx.message if self.music_player.is_playing(): - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): self.music_player.paused = False self.music_player.stop() else: @@ -168,7 +178,7 @@ class Audio: files.extend(glob.glob("data/audio/localtracks/" + name + "/*.mp3")) if glob.glob("data/audio/localtracks/" + name + "/*.flac"): files.extend(glob.glob("data/audio/localtracks/" + name + "/*.flac")) - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): if await self.check_voice(msg.author, ctx.message): self.queue = [] self.current = -1 @@ -188,7 +198,7 @@ class Audio: """ msg = ctx.message if self.music_player.is_playing(): - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): self.current = -1 self.playlist = [self.downloader["URL"]] await self.bot.say("I will play this song on repeat.") @@ -201,7 +211,7 @@ class Audio: """ msg = ctx.message if self.music_player.is_playing(): - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): if self.playlist: shuffle(self.playlist) await self.bot.say("The order of this playlist has been mixed") @@ -214,7 +224,7 @@ class Audio: """ msg = ctx.message if self.music_player.is_playing() and self.playlist: - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): self.current -= 2 if self.current == -1: self.current = len(self.playlist) -3 @@ -231,7 +241,7 @@ class Audio: """ msg = ctx.message if self.music_player.is_playing(): - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): await self.close_audio() else: await self.bot.say("You can't stop music when there are other people in the channel! Vote to skip instead.") @@ -273,14 +283,16 @@ class Audio: else: await self.bot.say("That link is now allowed.") - async def is_alone_or_admin(self, author): #Direct control. fix everything + async def is_alone_or_admin(self, message): #Direct control. fix everything + author = message.author + server = message.server if not self.settings["QUEUE_MODE"]: return True - elif author.id == checks.settings["OWNER"]: + elif author.id == bot_settings.owner: return True - elif discord.utils.get(author.roles, name=checks.settings["ADMIN_ROLE"]) is not None: + elif discord.utils.get(author.roles, name=bot_settings.get_server_admin(server)) is not None: return True - elif discord.utils.get(author.roles, name=checks.settings["MOD_ROLE"]) is not None: + elif discord.utils.get(author.roles, name=bot_settings.get_server_mod(server)) is not None: return True elif len(author.voice_channel.voice_members) in (1, 2): return True @@ -299,7 +311,7 @@ class Audio: self.queue = [] await self.play_video(rndchoice(self.sing)) else: - if await self.is_alone_or_admin(msg.author): + if await self.is_alone_or_admin(msg): self.queue = [] await self.play_video(rndchoice(self.sing)) else: @@ -775,6 +787,12 @@ def check_files(): def setup(bot): check_folders() check_files() + if youtube_dl is None: + raise RuntimeError("You need to run `pip3 install youtube_dl`") + return + if opus is None: + raise RuntimeError("You need to get the *.exe's and opus.dll from 26's github.") + return loop = asyncio.get_event_loop() n = Audio(bot) loop.create_task(n.queue_manager()) diff --git a/cogs/customcom.py b/cogs/customcom.py index 7abe7c881..42629387d 100644 --- a/cogs/customcom.py +++ b/cogs/customcom.py @@ -24,8 +24,9 @@ class CustomCommands: await send_cmd_help(ctx) return server = ctx.message.server - to_replace = ctx.prefix + "addcom " + command + " " - text = ctx.message.content.replace(to_replace, "") + to_replace = ctx.message.content.find(text[0]) + text = ctx.message.content[to_replace:] + command = command.lower() if not server.id in self.c_commands: self.c_commands[server.id] = {} cmdlist = self.c_commands[server.id] @@ -49,8 +50,9 @@ class CustomCommands: await send_cmd_help(ctx) return server = ctx.message.server - to_replace = ctx.prefix + "editcom " + command + " " - text = ctx.message.content.replace(to_replace, "") + to_replace = ctx.message.content.find(text[0]) + text = ctx.message.content[to_replace:] + command = command.lower() if server.id in self.c_commands: cmdlist = self.c_commands[server.id] if command in cmdlist: @@ -71,6 +73,7 @@ class CustomCommands: Example: !delcom yourcommand""" server = ctx.message.server + command = command.lower() if server.id in self.c_commands: cmdlist = self.c_commands[server.id] if command in cmdlist: diff --git a/cogs/economy.py b/cogs/economy.py index b731e2eca..4a3d67e5d 100644 --- a/cogs/economy.py +++ b/cogs/economy.py @@ -1,9 +1,9 @@ import discord from discord.ext import commands from .utils.dataIO import fileIO -from .utils import checks from random import randint from copy import deepcopy +from .utils import checks from __main__ import send_cmd_help import os import time diff --git a/cogs/general.py b/cogs/general.py index 852e31dab..a3de88c93 100644 --- a/cogs/general.py +++ b/cogs/general.py @@ -21,6 +21,11 @@ class General: "Don't count on it", "My reply is no", "My sources say no", "Outlook not so good", "Very doubtful"] self.poll_sessions = [] + @commands.command() + async def ping(self): + """Pong.""" + self.bot.say("Pong.") + @commands.command() async def choose(self, *choices): """Chooses between multiple choices. diff --git a/cogs/mod.py b/cogs/mod.py index dd9685991..b1c7a6691 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -1,10 +1,11 @@ import discord from discord.ext import commands -from .utils import checks from .utils.dataIO import fileIO -from __main__ import send_cmd_help +from .utils import checks +from __main__ import send_cmd_help, settings import os import logging +import json class Mod: """Moderation tools.""" @@ -16,6 +17,36 @@ class Mod: self.ignore_list = fileIO("data/mod/ignorelist.json", "load") self.filter = fileIO("data/mod/filter.json", "load") + @commands.group(pass_context=True,no_pm=True) + @checks.serverowner_or_permissions(manage_server=True) + async def modset(self,ctx): + """Manages server administration settings.""" + if ctx.invoked_subcommand is None: + await send_cmd_help(ctx) + msg = "```" + for k, v in settings.get_server(ctx.message.server).items(): + msg += str(k) + ": " + str(v) + "\n" + msg += "```" + await self.bot.say(msg) + + @modset.command(name="adminrole",pass_context=True,no_pm=True) + async def _modset_adminrole(self,ctx,role_name : str): + """Sets the admin role for this server, case insensitive.""" + server = ctx.message.server + if server.id not in settings.servers: + await self.bot.say("Remember to set modrole too.") + settings.set_server_admin(server,role_name) + await self.bot.say("Admin role set to '{}'".format(role_name)) + + @modset.command(name="modrole",pass_context=True,no_pm=True) + async def _modset_modrole(self,ctx,role_name : str): + """Sets the mod role for this server, case insensitive.""" + server = ctx.message.server + if server.id not in settings.servers: + await self.bot.say("Remember to set adminrole too.") + settings.set_server_mod(server,role_name) + await self.bot.say("Mod role set to '{}'".format(role_name)) + @commands.command(no_pm=True, pass_context=True) @checks.admin_or_permissions(kick_members=True) async def kick(self, ctx, user : discord.Member): @@ -32,17 +63,17 @@ class Mod: @commands.command(no_pm=True, pass_context=True) @checks.admin_or_permissions(ban_members=True) - async def ban(self, ctx, user : discord.Member, purge_msg : int=0): + async def ban(self, ctx, user : discord.Member, days : int=0): """Bans user and deletes last X days worth of messages. Minimum 0 days, maximum 7. Defaults to 0.""" author = ctx.message.author - if purge_msg < 0 or purge_msg > 7: + if days < 0 or days > 7: await self.bot.say("Invalid days. Must be between 0 and 7.") return try: await self.bot.ban(user, days) - logger.info("{}({}) banned {}({}), deleting {} days worth of messages".format(author.name, author.id, user.name, user.id, str(purge_msg))) + logger.info("{}({}) banned {}({}), deleting {} days worth of messages".format(author.name, author.id, user.name, user.id, str(days))) await self.bot.say("Done. It was about time.") except discord.errors.Forbidden: await self.bot.say("I'm not allowed to do that.") @@ -398,11 +429,15 @@ class Mod: def immune_from_filter(self, message): user = message.author - if user.id == checks.settings["OWNER"]: + server = message.server + admin_role = settings.get_server_admin(server) + mod_role = settings.get_server_mod(server) + + if user.id == settings.owner: return True - elif discord.utils.get(user.roles, name=checks.settings["ADMIN_ROLE"]): + elif discord.utils.get(user.roles, name=admin_role): return True - elif discord.utils.get(user.roles, name=checks.settings["MOD_ROLE"]): + elif discord.utils.get(user.roles, name=mod_role): return True else: return False diff --git a/cogs/utils/chat_formatting.py b/cogs/utils/chat_formatting.py new file mode 100644 index 000000000..79631b77f --- /dev/null +++ b/cogs/utils/chat_formatting.py @@ -0,0 +1,17 @@ +def bold(text): + return "**"+str(text)+"**" + +def italics(text): + return "*"+str(text)+"*" + +def strikethrough(text): + return "~~"+str(text)+"~~" + +def underline(text): + return "__"+str(text)+"__" + +def box(text): + return "```"+str(text)+"```" + +def inline(text): + return "`"+str(text)+"`" \ No newline at end of file diff --git a/cogs/utils/checks.py b/cogs/utils/checks.py index d480579ce..3e8c59828 100644 --- a/cogs/utils/checks.py +++ b/cogs/utils/checks.py @@ -1,7 +1,8 @@ from discord.ext import commands import discord.utils -import os.path -import json +from cogs.utils.settings import Settings +from cogs.utils.dataIO import fileIO +from __main__ import settings # # This is a modified version of checks.py, originally made by Rapptz @@ -10,14 +11,8 @@ import json # https://github.com/Rapptz/RoboDanny/tree/async # -try: - with open("data/red/settings.json", "r") as f: - settings = json.loads(f.read()) -except: - settings = {"OWNER" : False, "ADMIN_ROLE" : False, "MOD_ROLE" : False} - def is_owner_check(ctx): - return ctx.message.author.id == settings["OWNER"] + return ctx.message.author.id == settings.owner def is_owner(): return commands.check(is_owner_check) @@ -55,12 +50,28 @@ def role_or_permissions(ctx, check, **perms): def mod_or_permissions(**perms): def predicate(ctx): - return role_or_permissions(ctx, lambda r: r.name in (settings["MOD_ROLE"], settings["ADMIN_ROLE"]), **perms) + server = ctx.message.server + mod_role = settings.get_server_mod(server).lower() + admin_role = settings.get_server_admin(server).lower() + return role_or_permissions(ctx, lambda r: r.name.lower() in (mod_role,admin_role), **perms) return commands.check(predicate) def admin_or_permissions(**perms): def predicate(ctx): - return role_or_permissions(ctx, lambda r: r.name == settings["ADMIN_ROLE"], **perms) + server = ctx.message.server + admin_role = settings.get_server_admin(server) + return role_or_permissions(ctx, lambda r: r.name.lower() == admin_role.lower(), **perms) return commands.check(predicate) + +def serverowner_or_permissions(**perms): + def predicate(ctx): + server = ctx.message.server + owner = server.owner + + if ctx.message.author.id == owner.id: + return True + + return check_permissions(ctx,perms) + return commands.check(predicate) diff --git a/cogs/utils/dataIO.py b/cogs/utils/dataIO.py index f84312607..e2d1ece05 100644 --- a/cogs/utils/dataIO.py +++ b/cogs/utils/dataIO.py @@ -3,7 +3,7 @@ import json def fileIO(filename, IO, data=None): if IO == "save" and data != None: with open(filename, encoding='utf-8', mode="w") as f: - f.write(json.dumps(data)) + f.write(json.dumps(data,indent=4,sort_keys=True,separators=(',',' : '))) elif IO == "load" and data == None: with open(filename, encoding='utf-8', mode="r") as f: return json.loads(f.read()) diff --git a/cogs/utils/settings.py b/cogs/utils/settings.py new file mode 100644 index 000000000..06cbdbfed --- /dev/null +++ b/cogs/utils/settings.py @@ -0,0 +1,149 @@ +from .dataIO import fileIO +import discord +import os + +default_path = "data/red/settings.json" + +class Settings: + def __init__(self,path=default_path): + self.path = path + self.check_folders() + self.default_settings = {"EMAIL" : "EmailHere", "PASSWORD" : "PasswordHere", "OWNER" : "id_here", "PREFIXES" : [], "default":{"ADMIN_ROLE" : "Transistor", "MOD_ROLE" : "Process"}} + if not fileIO(self.path,"check"): + self.bot_settings = self.default_settings + self.save_settings() + else: + self.bot_settings = fileIO(self.path,"load") + if "default" not in self.bot_settings: + self.update_old_settings() + + def check_folders(self): + folders = ("data", os.path.dirname(self.path), "cogs", "cogs/utils") + for folder in folders: + if not os.path.exists(folder): + print("Creating " + folder + " folder...") + os.makedirs(folder) + + def save_settings(self): + fileIO(self.path,"save",self.bot_settings) + + def update_old_settings(self): + mod = self.bot_settings["MOD_ROLE"] + admin = self.bot_settings["ADMIN_ROLE"] + del self.bot_settings["MOD_ROLE"] + del self.bot_settings["ADMIN_ROLE"] + self.bot_settings["default"] = {"MOD_ROLE":mod,"ADMIN_ROLE":admin} + self.save_settings() + + @property + def owner(self): + return self.bot_settings["OWNER"] + + @owner.setter + def owner(self,value): + self.bot_settings["OWNER"] = value + self.save_settings() + + @property + def email(self): + return self.bot_settings["EMAIL"] + + @email.setter + def email(self,value): + self.bot_settings["EMAIL"] = value + self.save_settings() + + @property + def password(self): + return self.bot_settings["PASSWORD"] + + @password.setter + def password(self,value): + self.bot_settings["PASSWORD"] = value + self.save_settings() + + @property + def prefixes(self): + return self.bot_settings["PREFIXES"] + + @prefixes.setter + def prefixes(self,value): + assert isinstance(value,list) + self.bot_settings["PREFIXES"] = value + self.save_settings() + + @property + def default_admin(self): + if "default" not in self.bot_settings: + self.update_old_settings() + return self.bot_settings["default"].get("ADMIN_ROLE","") + + @default_admin.setter + def default_admin(self,value): + if "default" not in self.bot_settings: + self.update_old_settings() + self.bot_settings["default"]["ADMIN_ROLE"] = value + self.save_settings() + + @property + def default_mod(self): + if "default" not in self.bot_settings: + self.update_old_settings() + return self.bot_settings["default"].get("MOD_ROLE","") + + @default_mod.setter + def default_mod(self,value): + if "default" not in self.bot_settings: + self.update_old_settings() + self.bot_settings["default"]["MOD_ROLE"] = value + self.save_settings() + + @property + def servers(self): + ret = {} + server_ids = list(filter(lambda x: str(x).isdigit(),self.bot_settings)) + for server in server_ids: + ret.update({server:self.bot_settings[server]}) + return ret + + def get_server(self,server): + assert isinstance(server,discord.Server) + return self.bot_settings.get(server.id,self.bot_settings["default"]).copy() + + def get_server_admin(self,server): + assert isinstance(server,discord.Server) + if server is None: + return + if server.id not in self.bot_settings: + return self.default_admin + return self.bot_settings[server.id].get("ADMIN_ROLE","") + + def set_server_admin(self,server,value): + assert isinstance(server,discord.Server) + if server is None: + return + if server.id not in self.bot_settings: + self.add_server(server.id) + self.bot_settings[server.id]["ADMIN_ROLE"] = value + self.save_settings() + + def get_server_mod(self,server): + assert isinstance(server,discord.Server) + if server is None: + return + if server.id not in self.bot_settings: + return self.default_mod + return self.bot_settings[server.id].get("MOD_ROLE","") + + def set_server_mod(self,server,value): + assert isinstance(server,discord.Server) + if server is None: + return + if server.id not in self.bot_settings: + self.add_server(server.id) + self.bot_settings[server.id]["MOD_ROLE"] = value + self.save_settings() + + def add_server(self,sid): + self.bot_settings[sid] = self.bot_settings["default"].copy() + self.save_settings() diff --git a/red.py b/red.py index 90d162ace..2b50dc209 100644 --- a/red.py +++ b/red.py @@ -1,6 +1,6 @@ from discord.ext import commands import discord -from cogs.utils import checks +from cogs.utils.settings import Settings from random import choice as rndchoice import threading import datetime, re @@ -31,6 +31,10 @@ formatter = commands.HelpFormatter(show_check_failure=False) bot = commands.Bot(command_prefix=["_"], formatter=formatter, description=description, pm_help=None) +settings = Settings() + +from cogs.utils import checks + lock = False @bot.event @@ -150,7 +154,7 @@ async def debug(ctx, *, code : str): result = python.format(result) if not ctx.message.channel.is_private: - censor = (settings["EMAIL"], settings["PASSWORD"]) + censor = (settings.email, settings.password) r = "[EXPUNGED]" for w in censor: result = result.replace(w, r) @@ -169,8 +173,7 @@ async def owner(ctx): """Sets owner""" global lock msg = ctx.message - data = load_settings() - if data["OWNER"] != "id_here": + if settings.owner != "id_here": await bot.say("Owner ID has already been set.") return if lock: @@ -192,10 +195,7 @@ async def prefix(*prefixes): await bot.say("Example: setprefix [ ! ^ .") return bot.command_prefix = list(prefixes) - data = load_settings() - data["PREFIXES"] = list(prefixes) - with open("data/red/settings.json", "w") as f: - f.write(json.dumps(data)) + settings.prefixes = list(prefixes) if len(prefixes) > 1: await bot.say("Prefixes set") else: @@ -207,7 +207,7 @@ async def name(ctx, *name : str): """Sets Red's name""" if name == (): await send_cmd_help(ctx) - await bot.edit_profile(settings["PASSWORD"], username=" ".join(name)) + await bot.edit_profile(settings.password, username=" ".join(name)) await bot.say("Done.") @_set.command(pass_context=True) @@ -227,7 +227,7 @@ async def avatar(url : str): try: async with aiohttp.get(url) as r: data = await r.read() - await bot.edit_profile(settings["PASSWORD"], avatar=data) + await bot.edit_profile(settings.password, avatar=data) await bot.say("Done.") except: await bot.say("Error.") @@ -277,12 +277,12 @@ def user_allowed(message): mod = bot.get_cog('Mod') if mod is not None: - if checks.settings["OWNER"] == author.id: + if settings.owner == author.id: return True if not message.channel.is_private: - if discord.utils.get(author.roles, name=checks.settings["ADMIN_ROLE"]) is not None: - return True - if discord.utils.get(author.roles, name=checks.settings["MOD_ROLE"]) is not None: + server = message.server + names = (settings.get_server_admin(server),settings.get_server_mod(server)) + if None not in map(lambda name: discord.utils.get(author.roles,name=name),names): return True if author.id in mod.blacklist_list: @@ -310,24 +310,13 @@ def wait_for_answer(author): while choice.lower() != "yes" and choice == "None": choice = input("> ") if choice == "yes": - data = load_settings() - data["OWNER"] = author.id - with open("data/red/settings.json", "w") as f: - f.write(json.dumps(data)) - checks.owner = data["OWNER"] - print(author.name + " has been set as owner. A restart is required.") + settings.owner = author.id + print(author.name + " has been set as owner. A restart is required, maybe?") lock = False else: print("setowner request has been ignored.") lock = False -def load_settings(): - try: - with open('data/red/settings.json', "r") as f: - return json.load(f) - except: - raise("Couldn't load credentials.") - def list_cogs(): cogs = glob.glob("cogs/*.py") clean = [] @@ -344,60 +333,47 @@ def check_folders(): os.makedirs(folder) def check_configs(): - settings_path = "data/red/settings.json" - settings = {"EMAIL" : "EmailHere", "PASSWORD" : "PasswordHere", "OWNER" : "id_here", "PREFIXES" : [], "ADMIN_ROLE" : "Transistor", "MOD_ROLE" : "Process"} - if not os.path.isfile(settings_path): - + if settings.bot_settings == settings.default_settings: print("Red - First run configuration") print("If you don't have one, create a NEW ACCOUNT for Red. Do *not* use yours. (https://discordapp.com)") - settings["EMAIL"] = input("\nEmail> ") - settings["PASSWORD"] = input("\nPassword> ") + settings.email = input("\nEmail> ") + settings.password = input("\nPassword> ") - if not settings["EMAIL"] or not settings["PASSWORD"]: + if not settings.email or not settings.password: input("Email and password cannot be empty. Restart Red and repeat the configuration process.") exit(1) - if "@" not in settings["EMAIL"]: + if "@" not in settings.email: input("You didn't enter a valid email. Restart Red and repeat the configuration process.") exit(1) print("\nChoose a prefix (or multiple ones, one at once) for the commands. Type exit when you're done. Example prefix: !") - settings["PREFIXES"] = [] + prefixes = [] new_prefix = "" - while new_prefix.lower() != "exit" or settings["PREFIXES"] == []: + while new_prefix.lower() != "exit" or prefixes == []: new_prefix = input("Prefix> ") if new_prefix.lower() != "exit" and new_prefix != "": - settings["PREFIXES"].append(new_prefix) + prefixes.append(new_prefix) + #Remember we're using property's here, oh well... + settings.prefixes = prefixes print("\nInput *your own* ID. You can type \@Yourname in chat to see it (copy only the numbers).") print("If you want, you can also do it later with [prefix]set owner. Leave empty in that case.") - settings["OWNER"] = input("\nID> ") - if settings["OWNER"] == "": settings["OWNER"] = "id_here" - if not settings["OWNER"].isdigit() and settings["OWNER"] != "id_here": + settings.owner = input("\nID> ") + if settings.owner == "": settings["OWNER"] = "id_here" + if not settings.owner.isdigit() and settings["OWNER"] != "id_here": print("\nERROR: What you entered is not a valid ID. Set yourself as owner later with [prefix]set owner") - settings["OWNER"] = "id_here" + settings.owner = "id_here" print("\nInput the admin role's name. Anyone with this role will be able to use the bot's admin commands") print("Leave blank for default name (Transistor)") - settings["ADMIN_ROLE"] = input("\nAdmin role> ") - if settings["ADMIN_ROLE"] == "": settings["ADMIN_ROLE"] = "Transistor" + settings.default_admin = input("\nAdmin role> ") + if settings.default_admin == "": settings.default_admin = "Transistor" print("\nInput the moderator role's name. Anyone with this role will be able to use the bot's mod commands") print("Leave blank for default name (Process)") - settings["MOD_ROLE"] = input("\nAdmin role> ") - if settings["MOD_ROLE"] == "": settings["MOD_ROLE"] = "Process" - - with open(settings_path, "w") as f: - f.write(json.dumps(settings)) - else: # Undoing the changes made by the broken pull request - data = load_settings() - if "default" in data: - data["ADMIN_ROLE"] = data["default"]["ADMIN_ROLE"] - data["MOD_ROLE"] = data["default"]["MOD_ROLE"] - del data["default"] - print("Rolling back settings to previous format...") - with open(settings_path, "w") as f: - f.write(json.dumps(data, indent=4,sort_keys=True,separators=(',',' : '))) + settings.default_mod = input("\nModerator role> ") + if settings.default_mod == "": settings.default_mod = "Process" cogs_s_path = "data/red/cogs.json" cogs = {} @@ -482,14 +458,14 @@ def load_cogs(): def main(): global settings + global checks + check_folders() check_configs() set_logger() - settings = load_settings() - checks.settings["OWNER"] = settings["OWNER"] load_cogs() - bot.command_prefix = settings["PREFIXES"] - yield from bot.login(settings["EMAIL"], settings["PASSWORD"]) + bot.command_prefix = settings.prefixes + yield from bot.login(settings.email, settings.password) yield from bot.connect() if __name__ == '__main__':