initial working update

This commit is contained in:
Will Tekulve 2016-02-27 04:02:32 -05:00
parent d565849a35
commit 563d7bb395
8 changed files with 205 additions and 133 deletions

View File

@ -1,6 +1,5 @@
import discord import discord
from discord.ext import commands from discord.ext import commands
from .utils import checks
from .utils.chat_formatting import * from .utils.chat_formatting import *
from .utils.dataIO import fileIO from .utils.dataIO import fileIO
from .utils import checks from .utils import checks

View File

@ -2,7 +2,6 @@ import discord
from discord.ext import commands from discord.ext import commands
import asyncio import asyncio
import threading import threading
import youtube_dl
import os import os
from random import choice as rndchoice from random import choice as rndchoice
from random import shuffle from random import shuffle
@ -15,8 +14,16 @@ import aiohttp
import json import json
import time import time
if not discord.opus.is_loaded(): try:
import youtube_dl
except:
youtube_dl = None
try:
if not discord.opus.is_loaded():
discord.opus.load_opus('libopus-0.dll') discord.opus.load_opus('libopus-0.dll')
except:
opus = None
youtube_dl_options = { youtube_dl_options = {
'format': 'bestaudio/best', 'format': 'bestaudio/best',
@ -775,6 +782,12 @@ def check_files():
def setup(bot): def setup(bot):
check_folders() check_folders()
check_files() 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() loop = asyncio.get_event_loop()
n = Audio(bot) n = Audio(bot)
loop.create_task(n.queue_manager()) loop.create_task(n.queue_manager())

View File

@ -1,9 +1,9 @@
import discord import discord
from discord.ext import commands from discord.ext import commands
from .utils.dataIO import fileIO from .utils.dataIO import fileIO
from .utils import checks
from random import randint from random import randint
from copy import deepcopy from copy import deepcopy
from .utils import checks
from __main__ import send_cmd_help from __main__ import send_cmd_help
import os import os
import time import time

View File

@ -1,7 +1,7 @@
import discord import discord
from discord.ext import commands from discord.ext import commands
from .utils import checks
from .utils.dataIO import fileIO from .utils.dataIO import fileIO
from .utils import checks
from __main__ import send_cmd_help, settings from __main__ import send_cmd_help, settings
import os import os
import logging import logging
@ -23,49 +23,31 @@ class Mod:
# THEN # THEN
# 2) Use checks.save_bot_settings(modified_bot_settings) # 2) Use checks.save_bot_settings(modified_bot_settings)
# 3) Don't blame me (Will), blame the other guy (not 26) # 3) Don't blame me (Will), blame the other guy (not 26)
@property
def bot_settings(self):
settings = {}
with open("data/red/settings.json", "r") as f:
settings = json.loads(f.read())
if settings == {}:
raise RuntimeError("Settings not found.")
return settings
@commands.group(pass_context=True) @commands.group(pass_context=True)
@checks.admin_or_permissions(manage_server=True) @checks.admin_or_permissions(manage_server=True)
async def modset(self,ctx): async def modset(self,ctx):
"""Manages server administration settings.""" """Manages server administration settings."""
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
send_cmd_help(ctx) await send_cmd_help(ctx)
@modset.command(name="adminrole",pass_context=True) @modset.command(name="adminrole",pass_context=True,no_pm=True)
async def _modset_adminrole(self,ctx,role_name : str): async def _modset_adminrole(self,ctx,role_name : str):
"""Sets the admin role for this server, case insensitive.""" """Sets the admin role for this server, case insensitive."""
sid = ctx.message.server.id server = ctx.message.server
settings = self.bot_settings if server.id not in settings.servers:
if sid in settings:
settings[sid]["ADMIN_ROLE"] = role_name
else:
settings[sid] = {"ADMIN_ROLE":role_name,"MOD_ROLE":""}
settings[sid]["MOD_ROLE"] = settings["default"]["MOD_ROLE"]
await self.bot.say("Remember to set modrole too.") 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)) await self.bot.say("Admin role set to '{}'".format(role_name))
checks.save_bot_settings(settings)
@modset.command(name="modrole",pass_context=True) @modset.command(name="modrole",pass_context=True,no_pm=True)
async def _modset_modrole(self,ctx,role_name : str): async def _modset_modrole(self,ctx,role_name : str):
"""Sets the mod role for this server, case insensitive.""" """Sets the mod role for this server, case insensitive."""
sid = ctx.message.server.id server = ctx.message.server
settings = self.bot_settings if server.id not in settings.servers:
if sid in settings:
settings[sid]["MOD_ROLE"] = role_name
else:
settings[sid] = {"MOD_ROLE":role_name,"ADMIN_ROLE":""}
settings[sid]["ADMIN_ROLE"] = settings["default"]["ADMIN_ROLE"]
await self.bot.say("Remember to set adminrole too.") 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)) await self.bot.say("Mod role set to '{}'".format(role_name))
checks.save_bot_settings(settings)
@commands.command(no_pm=True, pass_context=True) @commands.command(no_pm=True, pass_context=True)
@checks.admin_or_permissions(kick_members=True) @checks.admin_or_permissions(kick_members=True)
@ -449,11 +431,15 @@ class Mod:
def immune_from_filter(self, message): def immune_from_filter(self, message):
user = message.author 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 return True
elif discord.utils.get(user.roles, name=checks.settings["ADMIN_ROLE"]): elif discord.utils.get(user.roles, name=admin_role):
return True return True
elif discord.utils.get(user.roles, name=checks.settings["MOD_ROLE"]): elif discord.utils.get(user.roles, name=mod_role):
return True return True
else: else:
return False return False

View File

@ -1,7 +1,8 @@
from discord.ext import commands from discord.ext import commands
import discord.utils import discord.utils
import os.path from cogs.utils.settings import Settings
import json from cogs.utils.dataIO import fileIO
from __main__ import settings
# #
# This is a modified version of checks.py, originally made by Rapptz # This is a modified version of checks.py, originally made by Rapptz
@ -10,15 +11,8 @@ import json
# https://github.com/Rapptz/RoboDanny/tree/async # https://github.com/Rapptz/RoboDanny/tree/async
# #
try:
with open("data/red/settings.json", "r") as f:
settings = json.loads(f.read())
except Exception as e:
print(e)
settings = {"OWNER" : False, "default":{"ADMIN_ROLE" : False, "MOD_ROLE" : False}}
def is_owner_check(ctx): def is_owner_check(ctx):
return ctx.message.author.id == settings["OWNER"] return ctx.message.author.id == settings.owner
def is_owner(): def is_owner():
return commands.check(is_owner_check) return commands.check(is_owner_check)
@ -33,17 +27,6 @@ def is_owner():
# the permissions required for them. # the permissions required for them.
# Of course, the owner will always be able to execute commands. # Of course, the owner will always be able to execute commands.
def save_bot_settings(bot_settings=settings):
with open("data/red/settings.json", "w") as f:
f.write(json.dumps(bot_settings,sort_keys=True,indent=4,separators=(',',':')))
def update_old_settings():
mod = settings["MOD_ROLE"]
admin = settings["ADMIN_ROLE"]
del settings["MOD_ROLE"]
del settings["ADMIN_ROLE"]
settings["default"] = {"MOD_ROLE":mod,"ADMIN_ROLE":admin}
def check_permissions(ctx, perms): def check_permissions(ctx, perms):
if is_owner_check(ctx): if is_owner_check(ctx):
return True return True
@ -67,30 +50,17 @@ def role_or_permissions(ctx, check, **perms):
def mod_or_permissions(**perms): def mod_or_permissions(**perms):
def predicate(ctx): def predicate(ctx):
if "default" not in settings: server = ctx.message.server
update_old_settings() mod_role = settings.get_server_mod(server)
if admin_or_permissions(**perms): admin_role = settings.get_server_admin(server)
return True
sid = ctx.message.server.id
if sid not in settings:
mod_role = settings["default"]["MOD_ROLE"].lower()
admin_role = settings["default"]["ADMIN_ROLE"].lower()
else:
mod_role = settings[sid]["MOD_ROLE"].lower()
admin_role = settings[sid]["ADMIN_ROLE"].lower()
return role_or_permissions(ctx, lambda r: r.name.lower() in (mod_role,admin_role), **perms) return role_or_permissions(ctx, lambda r: r.name.lower() in (mod_role,admin_role), **perms)
return commands.check(predicate) return commands.check(predicate)
def admin_or_permissions(**perms): def admin_or_permissions(**perms):
def predicate(ctx): def predicate(ctx):
if "default" not in settings: server = ctx.message.server
update_old_settings() admin_role = settings.get_server_admin(server)
sid = ctx.message.server.id
if sid not in settings:
admin_role = settings["default"]["ADMIN_ROLE"]
else:
admin_role = settings[sid]["ADMIN_ROLE"]
return role_or_permissions(ctx, lambda r: r.name.lower() == admin_role.lower(), **perms) return role_or_permissions(ctx, lambda r: r.name.lower() == admin_role.lower(), **perms)
return commands.check(predicate) return commands.check(predicate)

View File

@ -3,7 +3,7 @@ import json
def fileIO(filename, IO, data=None): def fileIO(filename, IO, data=None):
if IO == "save" and data != None: if IO == "save" and data != None:
with open(filename, encoding='utf-8', mode="w") as f: 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: elif IO == "load" and data == None:
with open(filename, encoding='utf-8', mode="r") as f: with open(filename, encoding='utf-8', mode="r") as f:
return json.loads(f.read()) return json.loads(f.read())

125
cogs/utils/settings.py Normal file
View File

@ -0,0 +1,125 @@
from .dataIO import fileIO
import discord
default_path = "data/red/settings.json"
class Settings:
def __init__(self,path=default_path):
self.path = path
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 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"]
@property
def password(self):
return self.bot_settings["PASSWORD"]
@property
def prefixes(self):
return self.bot_settings["PREFIXES"]
@prefixes.setter
def prefixes(self,value):
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_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()

93
red.py
View File

@ -1,6 +1,6 @@
from discord.ext import commands from discord.ext import commands
import discord import discord
from cogs.utils import checks from cogs.utils.settings import Settings
from random import choice as rndchoice from random import choice as rndchoice
import threading import threading
import datetime, re import datetime, re
@ -31,6 +31,10 @@ formatter = commands.HelpFormatter(show_check_failure=False)
bot = commands.Bot(command_prefix=["_"], formatter=formatter, bot = commands.Bot(command_prefix=["_"], formatter=formatter,
description=description, pm_help=None) description=description, pm_help=None)
settings = Settings()
from cogs.utils import checks
lock = False lock = False
@bot.event @bot.event
@ -150,7 +154,7 @@ async def debug(ctx, *, code : str):
result = python.format(result) result = python.format(result)
if not ctx.message.channel.is_private: if not ctx.message.channel.is_private:
censor = (settings["EMAIL"], settings["PASSWORD"]) censor = (settings.email, settings.password)
r = "[EXPUNGED]" r = "[EXPUNGED]"
for w in censor: for w in censor:
result = result.replace(w, r) result = result.replace(w, r)
@ -169,8 +173,7 @@ async def owner(ctx):
"""Sets owner""" """Sets owner"""
global lock global lock
msg = ctx.message msg = ctx.message
data = load_settings() if settings.owner != "id_here":
if data["OWNER"] != "id_here":
await bot.say("Owner ID has already been set.") await bot.say("Owner ID has already been set.")
return return
if lock: if lock:
@ -192,10 +195,7 @@ async def prefix(*prefixes):
await bot.say("Example: setprefix [ ! ^ .") await bot.say("Example: setprefix [ ! ^ .")
return return
bot.command_prefix = list(prefixes) bot.command_prefix = list(prefixes)
data = load_settings() settings.prefixes = list(prefixes)
data["PREFIXES"] = list(prefixes)
with open("data/red/settings.json", "w") as f:
f.write(json.dumps(data))
if len(prefixes) > 1: if len(prefixes) > 1:
await bot.say("Prefixes set") await bot.say("Prefixes set")
else: else:
@ -207,7 +207,7 @@ async def name(ctx, *name : str):
"""Sets Red's name""" """Sets Red's name"""
if name == (): if name == ():
await send_cmd_help(ctx) 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.") await bot.say("Done.")
@_set.command(pass_context=True) @_set.command(pass_context=True)
@ -227,7 +227,7 @@ async def avatar(url : str):
try: try:
async with aiohttp.get(url) as r: async with aiohttp.get(url) as r:
data = await r.read() data = await r.read()
await bot.edit_profile(settings["PASSWORD"], avatar=data) await bot.edit_profile(settings.password, avatar=data)
await bot.say("Done.") await bot.say("Done.")
except: except:
await bot.say("Error.") await bot.say("Error.")
@ -277,15 +277,11 @@ def user_allowed(message):
mod = bot.get_cog('Mod') mod = bot.get_cog('Mod')
if mod is not None: if mod is not None:
if checks.settings["OWNER"] == author.id: if settings.owner == author.id:
return True return True
if not message.channel.is_private: if not message.channel.is_private:
sid = message.server.id server = message.server
if sid in checks.settings: names = (settings.get_server_admin(server),settings.get_server_mod(server))
names = (checks.settings[sid]["ADMIN_ROLE"],checks.settings[sid]["MOD_ROLE"])
else:
names = (checks.settings["default"]["ADMIN_ROLE"],checks.settings["default"]["MOD_ROLE"])
if None not in map(lambda name: discord.utils.get(author.roles,name=name),names): if None not in map(lambda name: discord.utils.get(author.roles,name=name),names):
return True return True
@ -314,24 +310,13 @@ def wait_for_answer(author):
while choice.lower() != "yes" and choice == "None": while choice.lower() != "yes" and choice == "None":
choice = input("> ") choice = input("> ")
if choice == "yes": if choice == "yes":
data = load_settings() settings.owner = author.id
data["OWNER"] = author.id print(author.name + " has been set as owner. A restart is required, maybe?")
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.")
lock = False lock = False
else: else:
print("setowner request has been ignored.") print("setowner request has been ignored.")
lock = False 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(): def list_cogs():
cogs = glob.glob("cogs/*.py") cogs = glob.glob("cogs/*.py")
clean = [] clean = []
@ -348,51 +333,46 @@ def check_folders():
os.makedirs(folder) os.makedirs(folder)
def check_configs(): def check_configs():
settings_path = "data/red/settings.json" if settings.bot_settings == settings.default_settings:
settings = {"EMAIL" : "EmailHere", "PASSWORD" : "PasswordHere", "OWNER" : "id_here", "PREFIXES" : [], "default":{"ADMIN_ROLE" : "Transistor", "MOD_ROLE" : "Process"}}
if not os.path.isfile(settings_path):
print("Red - First run configuration") 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)") 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.email = input("\nEmail> ")
settings["PASSWORD"] = input("\nPassword> ") 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.") input("Email and password cannot be empty. Restart Red and repeat the configuration process.")
exit(1) 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.") input("You didn't enter a valid email. Restart Red and repeat the configuration process.")
exit(1) exit(1)
print("\nChoose a prefix (or multiple ones, one at once) for the commands. Type exit when you're done. Example prefix: !") print("\nChoose a prefix (or multiple ones, one at once) for the commands. Type exit when you're done. Example prefix: !")
settings["PREFIXES"] = [] settings.prefixes = []
new_prefix = "" new_prefix = ""
while new_prefix.lower() != "exit" or settings["PREFIXES"] == []: while new_prefix.lower() != "exit" or settings.prefixes == []:
new_prefix = input("Prefix> ") new_prefix = input("Prefix> ")
if new_prefix.lower() != "exit" and new_prefix != "": if new_prefix.lower() != "exit" and new_prefix != "":
settings["PREFIXES"].append(new_prefix) settings.prefixes = settings.prefixes.append(new_prefix)
#Remember we're using property's here, oh well...
print("\nInput *your own* ID. You can type \@Yourname in chat to see it (copy only the numbers).") 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.") print("If you want, you can also do it later with [prefix]set owner. Leave empty in that case.")
settings["OWNER"] = input("\nID> ") settings.owner = input("\nID> ")
if settings["OWNER"] == "": settings["OWNER"] = "id_here" if settings.owner == "": settings["OWNER"] = "id_here"
if not settings["OWNER"].isdigit() and 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") 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("\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)") print("Leave blank for default name (Transistor)")
settings["default"]["ADMIN_ROLE"] = input("\nAdmin role> ") settings.default_admin = input("\nAdmin role> ")
if settings["default"]["ADMIN_ROLE"] == "": settings["default"]["ADMIN_ROLE"] = "Transistor" 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("\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)") print("Leave blank for default name (Process)")
settings["default"]["MOD_ROLE"] = input("\nAdmin role> ") settings.default_mod = input("\nModerator role> ")
if settings["default"]["MOD_ROLE"] == "": settings["default"]["MOD_ROLE"] = "Process" if settings.default_mod == "": settings.default_mod = "Process"
with open(settings_path, "w") as f:
f.write(json.dumps(settings))
cogs_s_path = "data/red/cogs.json" cogs_s_path = "data/red/cogs.json"
cogs = {} cogs = {}
@ -477,15 +457,14 @@ def load_cogs():
def main(): def main():
global settings global settings
global checks
check_folders() check_folders()
check_configs() check_configs()
set_logger() set_logger()
settings = load_settings()
checks.settings["OWNER"] = settings["OWNER"]
checks.save_bot_settings(checks.settings)
load_cogs() load_cogs()
bot.command_prefix = settings["PREFIXES"] bot.command_prefix = settings.prefixes
yield from bot.login(settings["EMAIL"], settings["PASSWORD"]) yield from bot.login(settings.email, settings.password)
yield from bot.connect() yield from bot.connect()
if __name__ == '__main__': if __name__ == '__main__':