aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--discord/__main__.py280
1 files changed, 280 insertions, 0 deletions
diff --git a/discord/__main__.py b/discord/__main__.py
new file mode 100644
index 00000000..54b244f3
--- /dev/null
+++ b/discord/__main__.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-2017 Rapptz
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+"""
+
+import discord
+import argparse
+import sys
+from pathlib import Path
+import os
+import re
+
+def core(parser, args):
+ pass
+
+bot_template = """#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from discord.ext import commands
+import discord
+import config
+
+class Bot(commands.{base}):
+ def __init__(self, **kwargs):
+ super().__init__(command_prefix=commands.when_mentioned_or('{prefix}'), **kwargs)
+ for cog in config.cogs:
+ try:
+ self.load_extension(cog)
+ except Exception as e:
+ print('Could not load extension {{0}} due to {{1.__class__.__name__}}: {{1}}'.format(cog, e))
+
+ async def on_ready(self):
+ print('Logged on as {{0}} (ID: {{0.id}})'.format(self))
+
+
+bot = Bot()
+
+# write general commands here
+
+bot.run(config.token)
+"""
+
+gitignore_template = """# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# Our configuration files
+config.py
+"""
+
+cog_template = '''# -*- coding: utf-8 -*-
+
+from discord.ext import commands
+import discord
+
+class {name}:
+ """The description for {name} goes here."""
+
+ def __init__(self, bot):
+ self.bot = bot
+{extra}
+def setup(bot):
+ bot.add_cog({name}(bot))
+'''
+
+cog_extras = '''
+ def __unload(self):
+ # clean up logic goes here
+ pass
+
+ async def __local_check(self, ctx):
+ # checks that apply to every command in here
+ return True
+
+ async def __global_check(self, ctx):
+ # checks that apply to every command to the bot
+ return True
+
+ async def __error(self, ctx, error):
+ # error handling to every command in here
+ pass
+
+ async def __before_invoke(self, ctx):
+ # called before a command is called here
+ pass
+
+ async def __after_invoke(self, ctx):
+ # called after a command is called here
+ pass
+
+'''
+
+
+# certain file names and directory names are forbidden
+# see: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
+# although some of this doesn't apply to Linux, we might as well be consistent
+_base_table = {
+ '<': '-',
+ '>': '-',
+ ':': '-',
+ '"': '-',
+ # '/': '-', these are fine
+ # '\\': '-',
+ '|': '-',
+ '?': '-',
+ '*': '-',
+}
+
+#
+_base_table.update((chr(i), None) for i in range(32))
+
+translation_table = str.maketrans(_base_table)
+
+def to_path(parser, name, *, replace_spaces=False):
+ if isinstance(name, Path):
+ return name
+
+ if sys.platform == 'win32':
+ forbidden = ('CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', \
+ 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9')
+ if len(name) <= 4 and name.upper() in forbidden:
+ parser.error('invalid directory name given, use a different one')
+
+ name = name.translate(translation_table)
+ if replace_spaces:
+ name = name.replace(' ', '-')
+ return Path(name)
+
+def newbot(parser, args):
+ if sys.version_info < (3, 5):
+ parser.error('python version is older than 3.5, consider upgrading.')
+
+ new_directory = to_path(parser, args.directory) / to_path(parser, args.name)
+
+ # as a note exist_ok for Path is a 3.5+ only feature
+ # since we already checked above that we're >3.5
+ try:
+ new_directory.mkdir(exist_ok=True, parents=True)
+ except OSError as e:
+ parser.error('could not create our bot directory ({})'.format(e))
+
+ cogs = new_directory / 'cogs'
+
+ try:
+ cogs.mkdir(exist_ok=True)
+ init = cogs / '__init__.py'
+ init.touch()
+ except OSError as e:
+ print('warning: could not create cogs directory ({})'.format(e))
+
+ try:
+ with open(str(new_directory / 'config.py'), 'w', encoding='utf-8') as fp:
+ fp.write('token = "place your token here"\ncogs = []\n')
+ except OSError as e:
+ parser.error('could not create config file ({})'.format(e))
+
+ try:
+ with open(str(new_directory / 'bot.py'), 'w', encoding='utf-8') as fp:
+ base = 'Bot' if not args.sharded else 'AutoShardedBot'
+ fp.write(bot_template.format(base=base, prefix=args.prefix))
+ except OSError as e:
+ parser.error('could not create bot file ({})'.format(e))
+
+ if not args.no_git:
+ try:
+ with open(str(new_directory / '.gitignore'), 'w', encoding='utf-8') as fp:
+ fp.write(gitignore_template)
+ except OSError as e:
+ print('warning: could not create .gitignore file ({})'.format(e))
+
+ print('successfully made bot at', new_directory)
+
+def newcog(parser, args):
+ if sys.version_info < (3, 5):
+ parser.error('python version is older than 3.5, consider upgrading.')
+
+ cog_dir = to_path(parser, args.directory)
+ try:
+ cog_dir.mkdir(exist_ok=True)
+ except OSError as e:
+ print('warning: could not create cogs directory ({})'.format(e))
+
+ directory = cog_dir / to_path(parser, args.name)
+ directory = directory.with_suffix('.py')
+ try:
+ with open(str(directory), 'w', encoding='utf-8') as fp:
+ extra = cog_extras if args.full else ''
+ if args.class_name:
+ name = args.class_name
+ else:
+ name = str(directory.stem)
+ if '-' in name:
+ name = name.replace('-', ' ').title().replace(' ', '')
+ else:
+ name = name.title()
+ fp.write(cog_template.format(name=name, extra=extra))
+ except OSError as e:
+ parser.error('could not create cog file ({})'.format(e))
+ else:
+ print('successfully made cog at', directory)
+
+def add_newbot_args(subparser):
+ parser = subparser.add_parser('newbot', help='creates a command bot project quickly')
+ parser.set_defaults(func=newbot)
+
+ parser.add_argument('name', help='the bot project name')
+ parser.add_argument('directory', help='the directory to place it in (default: .)', nargs='?', default=Path.cwd())
+ parser.add_argument('--prefix', help='the bot prefix (default: $)', default='$', metavar='<prefix>')
+ parser.add_argument('--sharded', help='whether to use AutoShardedBot', action='store_true')
+ parser.add_argument('--no-git', help='do not create a .gitignore file', action='store_true', dest='no_git')
+
+def add_newcog_args(subparser):
+ parser = subparser.add_parser('newcog', help='creates a new cog template quickly')
+ parser.set_defaults(func=newcog)
+
+ parser.add_argument('name', help='the cog name')
+ parser.add_argument('directory', help='the directory to place it in (default: cogs)', nargs='?', default=Path('cogs'))
+ parser.add_argument('--class-name', help='the class name of the cog (default: <name>)', dest='class_name')
+ parser.add_argument('--full', help='add all special methods as well', action='store_true')
+
+def parse_args():
+ parser = argparse.ArgumentParser(prog='discord', description='Tools for helping with discord.py')
+
+ version = 'discord.py v{0.__version__} for Python {1[0]}.{1[1]}.{1[2]}'.format(discord, sys.version_info)
+ parser.add_argument('-v', '--version', action='version', version=version, help='shows the library version')
+ parser.set_defaults(func=core)
+
+ subparser = parser.add_subparsers(dest='subcommand', title='subcommands')
+ add_newbot_args(subparser)
+ add_newcog_args(subparser)
+ return parser, parser.parse_args()
+
+def main():
+ parser, args = parse_args()
+ args.func(parser, args)
+
+main()