mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
Startup flags: can be started and configured without ever doing the interactive setup Changed default settings format so that all unset values are None Removed new cogs prompt Removed `LOGIN_TYPE` from settings.json. It now defaults to token and fallbacks to email/password Smarter initial setup: only asks for the settings that are actually missing For the first installation all default cogs are loaded Startup flag that allows settings to be memory-only Initial selfbot support Only reset login credentials (on confirmation) instead of deleting the whole file in case of login failure Revamped main screen Made sure that nothing blows up when you run Red on Windows without `chcp 65001` Possibility of setting credentials in the environment variables `RED_TOKEN` / `RED_EMAIL` `RED_PASSWORD`. They will take priority over the configuration stored on disk.
282 lines
9.6 KiB
Python
282 lines
9.6 KiB
Python
from .dataIO import dataIO
|
|
from copy import deepcopy
|
|
import discord
|
|
import os
|
|
import argparse
|
|
|
|
|
|
default_path = "data/red/settings.json"
|
|
|
|
|
|
class Settings:
|
|
|
|
def __init__(self, path=default_path):
|
|
self.path = path
|
|
self.check_folders()
|
|
self.default_settings = {
|
|
"TOKEN": None,
|
|
"EMAIL": None,
|
|
"PASSWORD": None,
|
|
"OWNER": None,
|
|
"PREFIXES": [],
|
|
"default": {"ADMIN_ROLE": "Transistor",
|
|
"MOD_ROLE": "Process",
|
|
"PREFIXES": []}
|
|
}
|
|
self.memory_only = False
|
|
|
|
if not dataIO.is_valid_json(self.path):
|
|
self.bot_settings = deepcopy(self.default_settings)
|
|
self.save_settings()
|
|
else:
|
|
current = dataIO.load_json(self.path)
|
|
if current.keys() != self.default_settings.keys():
|
|
for key in self.default_settings.keys():
|
|
if key not in current.keys():
|
|
current[key] = self.default_settings[key]
|
|
print("Adding " + str(key) +
|
|
" field to red settings.json")
|
|
dataIO.save_json(self.path, current)
|
|
self.bot_settings = dataIO.load_json(self.path)
|
|
|
|
if "default" not in self.bot_settings:
|
|
self.update_old_settings_v1()
|
|
|
|
if "LOGIN_TYPE" in self.bot_settings:
|
|
self.update_old_settings_v2()
|
|
|
|
self.parse_cmd_arguments()
|
|
|
|
def parse_cmd_arguments(self):
|
|
parser = argparse.ArgumentParser(description="Red - Discord Bot")
|
|
parser.add_argument("--owner", help="ID of the owner. Only who hosts "
|
|
"Red should be owner, this has "
|
|
"security implications")
|
|
parser.add_argument("--prefix", "-p", action="append",
|
|
help="Global prefix. Can be multiple")
|
|
parser.add_argument("--admin-role", help="Role seen as admin role by "
|
|
"Red")
|
|
parser.add_argument("--mod-role", help="Role seen as mod role by Red")
|
|
parser.add_argument("--no-prompt",
|
|
action="store_true",
|
|
help="Disables console inputs. Features requiring "
|
|
"console interaction could be disabled as a "
|
|
"result")
|
|
parser.add_argument("--self-bot",
|
|
action='store_true',
|
|
help="Specifies if Red should log in as selfbot")
|
|
parser.add_argument("--memory-only",
|
|
action="store_true",
|
|
help="Arguments passed and future edits to the "
|
|
"settings will not be saved to disk")
|
|
parser.add_argument("--debug",
|
|
action="store_true",
|
|
help="Enables debug mode")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.owner:
|
|
self.owner = args.owner
|
|
if args.prefix:
|
|
self.prefixes = sorted(args.prefix, reverse=True)
|
|
if args.admin_role:
|
|
self.default_admin = args.admin_role
|
|
if args.mod_role:
|
|
self.default_mod = args.mod_role
|
|
|
|
self.no_prompt = args.no_prompt
|
|
self.self_bot = args.self_bot
|
|
self.memory_only = args.memory_only
|
|
self.debug = args.debug
|
|
|
|
self.save_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):
|
|
if not self.memory_only:
|
|
dataIO.save_json(self.path, self.bot_settings)
|
|
|
|
def update_old_settings_v1(self):
|
|
# This converts the old settings format
|
|
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,
|
|
"PREFIXES": []
|
|
}
|
|
self.save_settings()
|
|
|
|
def update_old_settings_v2(self):
|
|
# The joys of backwards compatibility
|
|
settings = self.bot_settings
|
|
if settings["EMAIL"] == "EmailHere":
|
|
settings["EMAIL"] = None
|
|
if settings["PASSWORD"] == "":
|
|
settings["PASSWORD"] = None
|
|
if settings["LOGIN_TYPE"] == "token":
|
|
settings["TOKEN"] = settings["EMAIL"]
|
|
settings["EMAIL"] = None
|
|
settings["PASSWORD"] = None
|
|
else:
|
|
settings["TOKEN"] = None
|
|
del settings["LOGIN_TYPE"]
|
|
self.save_settings()
|
|
|
|
@property
|
|
def owner(self):
|
|
return self.bot_settings["OWNER"]
|
|
|
|
@owner.setter
|
|
def owner(self, value):
|
|
self.bot_settings["OWNER"] = value
|
|
|
|
@property
|
|
def token(self):
|
|
return os.environ.get("RED_TOKEN", self.bot_settings["TOKEN"])
|
|
|
|
@token.setter
|
|
def token(self, value):
|
|
self.bot_settings["TOKEN"] = value
|
|
self.bot_settings["EMAIL"] = None
|
|
self.bot_settings["PASSWORD"] = None
|
|
|
|
@property
|
|
def email(self):
|
|
return os.environ.get("RED_EMAIL", self.bot_settings["EMAIL"])
|
|
|
|
@email.setter
|
|
def email(self, value):
|
|
self.bot_settings["EMAIL"] = value
|
|
self.bot_settings["TOKEN"] = None
|
|
|
|
@property
|
|
def password(self):
|
|
return os.environ.get("RED_PASSWORD", self.bot_settings["PASSWORD"])
|
|
|
|
@password.setter
|
|
def password(self, value):
|
|
self.bot_settings["PASSWORD"] = value
|
|
|
|
@property
|
|
def login_credentials(self):
|
|
if self.token:
|
|
return (self.token,)
|
|
elif self.email and self.password:
|
|
return (self.email, self.password)
|
|
else:
|
|
return tuple()
|
|
|
|
@property
|
|
def prefixes(self):
|
|
return self.bot_settings["PREFIXES"]
|
|
|
|
@prefixes.setter
|
|
def prefixes(self, value):
|
|
assert isinstance(value, list)
|
|
self.bot_settings["PREFIXES"] = value
|
|
|
|
@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
|
|
|
|
@property
|
|
def default_mod(self):
|
|
if "default" not in self.bot_settings:
|
|
self.update_old_settings_v1()
|
|
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_v1()
|
|
self.bot_settings["default"]["MOD_ROLE"] = value
|
|
|
|
@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):
|
|
if server is None:
|
|
return self.bot_settings["default"].copy()
|
|
assert isinstance(server, discord.Server)
|
|
return self.bot_settings.get(server.id,
|
|
self.bot_settings["default"]).copy()
|
|
|
|
def get_server_admin(self, server):
|
|
if server is None:
|
|
return self.default_admin
|
|
assert isinstance(server, discord.Server)
|
|
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):
|
|
if server is None:
|
|
return
|
|
assert isinstance(server, discord.Server)
|
|
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):
|
|
if server is None:
|
|
return self.default_mod
|
|
assert isinstance(server, discord.Server)
|
|
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):
|
|
if server is None:
|
|
return
|
|
assert isinstance(server, discord.Server)
|
|
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 get_server_prefixes(self, server):
|
|
if server is None or server.id not in self.bot_settings:
|
|
return self.prefixes
|
|
return self.bot_settings[server.id].get("PREFIXES", [])
|
|
|
|
def set_server_prefixes(self, server, prefixes):
|
|
if server is None:
|
|
return
|
|
assert isinstance(server, discord.Server)
|
|
if server.id not in self.bot_settings:
|
|
self.add_server(server.id)
|
|
self.bot_settings[server.id]["PREFIXES"] = prefixes
|
|
self.save_settings()
|
|
|
|
def get_prefixes(self, server):
|
|
"""Returns server's prefixes if set, otherwise global ones"""
|
|
p = self.get_server_prefixes(server)
|
|
return p if p else self.prefixes
|
|
|
|
def add_server(self, sid):
|
|
self.bot_settings[sid] = self.bot_settings["default"].copy()
|
|
self.save_settings()
|