@@ -79,7 +79,6 @@ async def on_ready(): | |||
bot.load_extension("roxbot.err_handle") | |||
bot.load_extension("roxbot.logging") | |||
bot.load_extension("roxbot.system") | |||
bot.settings = gs.get_all(bot.guilds) | |||
print("Discord.py version: " + discord.__version__) | |||
print("Client logged in\n") |
@@ -29,6 +29,7 @@ from discord.ext import commands | |||
import roxbot | |||
from roxbot import guild_settings as gs | |||
# TODO: Clean up this file. | |||
def is_owner_or_admin(): | |||
def predicate(ctx): |
@@ -56,7 +56,8 @@ class UserConverter(commands.UserConverter): | |||
class EmojiConverter(commands.EmojiConverter): | |||
"""Just like the normla EmojiConverter class but with a custom error message and planned extra feature.""" | |||
"""The Emoji conveter from discord.py but instead it returns the argument if an error is raised | |||
It's messier than using the EmojiConverter proper but the issue is you can try converters.""" | |||
async def convert(self, ctx, argument): | |||
try: | |||
return await super().convert(ctx, argument) |
@@ -95,17 +95,18 @@ guild_template = { | |||
def _open_config(): | |||
""" | |||
Opens the guild settings file | |||
:return settings file: :type dict: | |||
"""Opens the guild settings file | |||
Returns | |||
======= | |||
servers.json: dict | |||
""" | |||
with open('roxbot/settings/servers.json', 'r') as config_file: | |||
return json.load(config_file) | |||
def _write_changes(config): | |||
""" | |||
Writes given config to disk. | |||
"""Writes given config to disk. MUST BE THE ENTIRE SERVER.JSON FILE. | |||
:param config: :type dict: | |||
:return: | |||
""" | |||
@@ -119,12 +120,14 @@ def backup(config, name): | |||
def remove_guild(guild): | |||
"""Removes given guild from settings file and saves changes.""" | |||
settings = _open_config() | |||
settings.pop(str(guild.id)) | |||
_write_changes(settings) | |||
def add_guild(guild): | |||
"""Adds given guild from settings file and saves changes.""" | |||
settings = _open_config() | |||
settings[str(guild.id)] = guild_template["example"] | |||
_write_changes(settings) | |||
@@ -133,7 +136,7 @@ def add_guild(guild): | |||
def error_check(servers): | |||
settings = _open_config() | |||
for server in servers: | |||
# Server ID needs to be made a string for this statement because keys have to be strings in JSON. Which is annoying now we use int for ids. | |||
# Server ID needs to be made a string for this statement because keys have to be strings in JSON. | |||
server_id = str(server.id) | |||
if str(server_id) not in settings: | |||
settings[server_id] = guild_template["example"] | |||
@@ -160,36 +163,15 @@ def error_check(servers): | |||
server.name.upper(), setting.upper(), cog_setting.upper())) | |||
def get_all(guilds): | |||
""" | |||
Returns a list of GuildSettings for all guilds the bot can see. | |||
:param guilds: | |||
:return list of GuildSettings: :type list: | |||
""" | |||
error_check(guilds) | |||
guild_list = [] | |||
for guild in guilds: | |||
guild = GuildSettings(guild) | |||
guild_list.append(guild) | |||
return guild_list | |||
def get(guild): | |||
""" | |||
Gets a single GuildSettings Object representing the settings of that guild | |||
:param guild: | |||
:param guild: :type discord.Guild: | |||
:return Single GuildSettings Object: :type GuildSettings: | |||
""" | |||
return GuildSettings(guild) | |||
def get_guild(guilds, wanted_guild): | |||
for guild in guilds: | |||
if guild.id == wanted_guild.id: | |||
return guild | |||
return None | |||
class GuildSettings(object): | |||
""" | |||
An Object to store all settings for one guild. |
@@ -30,23 +30,33 @@ import aiohttp | |||
async def request(url, *, headers=None, **kwargs): | |||
""" | |||
Base GET request. | |||
:param url: | |||
:param headers: | |||
:param kwargs: | |||
:return: | |||
"""Base GET request in case you need more control over GET requests. | |||
Params | |||
======= | |||
headers: dict (Optional) | |||
kwarg: kwargs (Optional) | |||
Returns | |||
======= | |||
Response: aiohttp Response object | |||
""" | |||
async with aiohttp.ClientSession() as session: | |||
return await session.get(url, headers=headers, **kwargs) | |||
async def api_request(url, *, headers=None, **kwargs): | |||
""" | |||
Returns a JSON dict object for most api calls in RoxBot. | |||
:param url: URL Should be a api endpoint that will return | |||
:param headers: There is no need to pass the user agent, this is done for you. | |||
:return: dict of JSON or None if a JSON was not returned from the call. | |||
"""Returns JSON from an API request. Should be used for all Roxbot API requests. | |||
Params | |||
======= | |||
url: str | |||
headers: dict (Optional) | |||
kwargs: kwargs (Optional) | |||
Returns | |||
======= | |||
JSON response: dict | |||
""" | |||
if headers is None: | |||
headers = {'User-agent': 'RoxBot Discord Bot'} | |||
@@ -61,10 +71,18 @@ async def api_request(url, *, headers=None, **kwargs): | |||
async def download_file(url, filename=None): | |||
""" | |||
Downloads the file at the given url and then saves it under the filename given to disk. | |||
:param filename: | |||
:param url: | |||
"""Downloads the file at the given url and then saves it under the filename given to disk. | |||
Params | |||
======= | |||
url: str | |||
filename: str (Optional) | |||
if not given, the function will try and determine filename from url. | |||
Returns | |||
======= | |||
filename: str | |||
Handy if no filename given | |||
""" | |||
if filename is None: | |||
filename = url.split("/")[-1].split("?")[0] | |||
@@ -76,7 +94,7 @@ async def download_file(url, filename=None): | |||
async def upload_file(url, file): | |||
""" | |||
"""Uploads a file using a POST request. Broke for pomf clones so idk. Might have to revert it to requests. | |||
:param url: url to POST to. | |||
:param file: Byes-like object to upload. | |||
@@ -89,10 +107,15 @@ async def upload_file(url, file): | |||
async def get_page(url, *, headers=None, **kwargs): | |||
""" | |||
Returns the page at the given url | |||
:param url: the url of the page you want to get | |||
:return: the html page | |||
"""Returns the html of the given url. Will need to run it through BS4 to parse it. | |||
Params | |||
======= | |||
url: str | |||
Returns | |||
======= | |||
HTML Page: str | |||
""" | |||
async with aiohttp.ClientSession() as session: | |||
async with session.get(url, headers=headers, **kwargs) as page: |
@@ -30,6 +30,21 @@ from roxbot import guild_settings, EmbedColours | |||
async def log(guild, channel, command_name, **kwargs): | |||
"""Logs activity internally for Roxbot. Will only do anything if the server enables internal logging. | |||
This is mostly used for logging when certain commands are used that can be an issue for admins. Esp when Roxbot outputs | |||
something that could break the rules, then deletes their message. | |||
Params | |||
======= | |||
guild: discord.Guild | |||
Used to check if the guild has logging enabled | |||
channel: discord.TextChannel | |||
command_name: str | |||
kwargs: dict | |||
All kwargs and two other params will be added to the logging embed as fields, allowing you to customise the output | |||
""" | |||
logging = guild_settings.get(guild).logging | |||
if logging["enabled"]: | |||
embed = discord.Embed(title="{} command logging".format(command_name), colour=EmbedColours.pink) |
@@ -30,7 +30,22 @@ import asyncio | |||
async def delete_option(bot, ctx, message, delete_emoji, timeout=20): | |||
"""Utility function that allows for you to add a delete option to the end of a command. | |||
This makes it easier for users to control the output of commands, esp handy for random output ones.""" | |||
This makes it easier for users to control the output of commands, esp handy for random output ones. | |||
Params | |||
======= | |||
bot: discord.ext.commands.Bot | |||
The current bot client | |||
ctx: discord.ext.commands.Context | |||
The context of the command | |||
message: discord.Message | |||
Output message from Roxbot | |||
delete_emoji: discord.Emoji or str if unicode emoji | |||
Used as the reaction for the user to click on. | |||
timeout: int (Optional) | |||
Amount of time in seconds for the bot to wait for the reaction. Deletes itself after the timer runes out. | |||
Set to 20 by default | |||
""" | |||
await message.add_reaction(delete_emoji) | |||
def check(r, u): | |||
@@ -40,12 +55,20 @@ async def delete_option(bot, ctx, message, delete_emoji, timeout=20): | |||
await bot.wait_for("reaction_add", timeout=timeout, check=check) | |||
await message.remove_reaction(delete_emoji, bot.user) | |||
await message.remove_reaction(delete_emoji, ctx.author) | |||
return await message.edit(content="{} requested output be deleted.".format(ctx.author), embed=None) | |||
await message.edit(content="{} requested output be deleted.".format(ctx.author), embed=None) | |||
except asyncio.TimeoutError: | |||
await message.remove_reaction(delete_emoji, bot.user) | |||
def blacklisted(user): | |||
"""Checks if given user is blacklisted from the bot. | |||
Params | |||
======= | |||
user: discord.User | |||
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: |