diff --git a/dockerfile b/dockerfile index 3cce367..87c38ca 100644 --- a/dockerfile +++ b/dockerfile @@ -16,4 +16,4 @@ RUN python3.6 -m pip install --upgrade pip && \ python3.6 -m pip install -r requirements.txt && \ python3.6 -m pip install -U git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice] -cmd ["python3.6","run.py"] +cmd ["python3.6","-m","src"] diff --git a/run.py b/src/__main__.py similarity index 65% rename from run.py rename to src/__main__.py index 3c16799..468225c 100644 --- a/run.py +++ b/src/__main__.py @@ -1,21 +1,28 @@ # !/usr/bin/python # -*- coding: utf8 -*- +""" +App entry point. -# Import packages +Something meaningful here, eventually. +""" import asyncio -import discord -from discord.ext import commands import json import logging -import traceback import random +import traceback + +import discord +from discord.ext import commands -# Import custom files from src.config.config import LoadConfig from src.shared_libs.loggable import Loggable +from src.shared_libs.ioutil import in_here + +# Init logging to output on INFO level to stderr. logging.basicConfig(level='INFO') + # If uvloop is installed, change to that eventloop policy as it # is more efficient try: @@ -23,13 +30,14 @@ try: asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) del uvloop except BaseException as ex: - logging.warning(f'Could not load uvloop. {type(ex).__name__}: {ex};', - 'reverting to default impl.') + logging.warning(f'Could not load uvloop. {type(ex).__qualname__}: {ex};', + 'reverting to default impl.') else: logging.info(f'Using uvloop for asyncio event loop policy.') # Bot Class +# Might be worth moving this to it's own file? class SebiMachine(commands.Bot, LoadConfig, Loggable): """This discord is dedicated to http://www.discord.gg/GWdhBSp""" def __init__(self): @@ -39,13 +47,13 @@ class SebiMachine(commands.Bot, LoadConfig, Loggable): # Load plugins # Add your cog file name in this list - with open('cogs.txt', 'r') as cog_file: + with open(in_here('cogs.txt')) as cog_file: cogs = cog_file.readlines() for cog in cogs: # Could this just be replaced with `strip()`? cog = cog.replace('\n', '') - self.load_extension(f'src.cogs.{cog}') + self.load_extension(f'{__name__}.cogs.{cog}') self.logger.info(f'Loaded: {cog}') async def on_ready(self): @@ -59,16 +67,18 @@ class SebiMachine(commands.Bot, LoadConfig, Loggable): error : Exception """ jokes = ["I\'m a bit tipsy, I took to many screenshots...", - "I am rushing to the 24/7 store to get myself anti-bug spray...", - "Organizing turtle race...", - "There is no better place then 127.0.0.1...", - "Recycling Hex Decimal...", - "No worry, I get fixed :^)...", - "R.I.P, press F for respect...", - "The bug repellent dit not work...", - "You found a bug in the program. Unfortunately the joke did not fit here, better luck next time..."] + "I am rushing to the 24/7 store to get myself anti-bug spray...", + "Organizing turtle race...", + "There is no better place then 127.0.0.1...", + "Recycling Hex Decimal...", + "No worry, I get fixed :^)...", + "R.I.P, press F for respect...", + "The bug repellent dit not work...", + "You found a bug in the program. Unfortunately the joke did not fit here, better luck next time..."] - # catch error + # CommandErrors triggered by other propagating errors tend to get wrapped. This means + # if we have a cause, we should probably consider unwrapping that so we get a useful + # message. error = error.__cause__ or error tb = traceback.format_exception(type(error), error, error.__traceback__, limit=2, chain=False) tb = ''.join(tb) @@ -86,7 +96,8 @@ class SebiMachine(commands.Bot, LoadConfig, Loggable): if __name__ == '__main__': client = SebiMachine() # Make sure the key stays private. - with open('src/config/PrivateConfig.json') as fp: + # I am 99% certain this is valid! + with open(f'{__name__}/config/PrivateConfig.json') as fp: PrivateConfig = json.load(fp) client.run(PrivateConfig["bot-key"]) diff --git a/avatar.png b/src/avatar.png similarity index 100% rename from avatar.png rename to src/avatar.png diff --git a/cogs.txt b/src/cogs.txt similarity index 88% rename from cogs.txt rename to src/cogs.txt index 9529ab0..cbb47e8 100644 --- a/cogs.txt +++ b/src/cogs.txt @@ -2,4 +2,4 @@ example contributors code git -fun \ No newline at end of file +fun diff --git a/src/shared_libs/ioutils.py b/src/shared_libs/ioutils.py new file mode 100644 index 0000000..c0642fb --- /dev/null +++ b/src/shared_libs/ioutils.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3.6 +# -*- coding: utf-8 -*- +""" +IO stuff. +""" +import inspect +import os + + +__all__ = ('in_here',) + + +def in_here(first_path_bit: str, *path_bits: str, stack_depth: int=0) -> str: + """ + A somewhat voodooish and weird piece of code. This enables us to + directly refer to a file in the same directory as the code that + calls this method, without any due regard for where in the file + system tree it is. + + Apart from that, this will behave just like os.path.join, meaning + that varaidic strings will be joined with the appropriate + directory separator for the current platform. + + This works by inspecting the stack frame for the caller. + If you are planning on nesting this call in another utility and wish + for the stack to refer to that caller, you should increment + the ``stack_depth`` arg for each nested call you make. By default, + you can ignore this and it will default to 0. + + :param first_path_bit: the initial path bit to operate with. This is + required. + :param path_bits: additional bits of path to construct relative to here. + These are entirely optional. + :param stack_depth: optional, defaults to 0. How many nested calls + we expect this to be called in. Affects the relative directory + that is used. + :returns: the absolute path to the given relative path provided. + """ + try: + frame = inspect.stack()[1 + nested_by] + except IndexError: + raise RuntimeError('Could not find a stack record. Interpreter has ' + 'been shot.') + else: + module = inspect.getmodule(frame[0]) + assert hasattr(module, '__file__'), 'No `__file__\' attr, welp.' + + file = module.__file__ + + dir_name = os.path.dirname(file) + abs_dir_name = os.path.abspath(dir_name) + + pathish = os.path.join(abs_dir_name, first_path_bit, *path_bits) + return pathish diff --git a/src/shared_libs/loggable.py b/src/shared_libs/loggable.py index 10e9e59..a32b3b3 100644 --- a/src/shared_libs/loggable.py +++ b/src/shared_libs/loggable.py @@ -14,6 +14,9 @@ boast faster lookups. import logging +__all__ = ('Loggable',) + + class Loggable: __slots__ = ('logger',)