Merge branch 'master' into espy-gitignore
This commit is contained in:
commit
f03ac6dd68
20
.gitignore
vendored
20
.gitignore
vendored
@ -109,22 +109,4 @@ venv.bak/
|
|||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
/src/config/Config.json
|
/src/config/Config.json
|
||||||
/src/config/PrivateConfig.json
|
/src/config/PrivateConfig.json
|
||||||
|
|
||||||
# IntelliJ stuff
|
|
||||||
.idea/
|
|
||||||
*.iml
|
|
||||||
|
|
||||||
# Sublime stuff
|
|
||||||
# Cache files for Sublime Text
|
|
||||||
*.tmlanguage.cache
|
|
||||||
*.tmPreferences.cache
|
|
||||||
*.stTheme.cache
|
|
||||||
|
|
||||||
# Workspace files are user-specific
|
|
||||||
*.sublime-workspace
|
|
||||||
|
|
||||||
# Project files should be checked into the repository, unless a significant
|
|
||||||
# proportion of contributors will probably not be using Sublime Text
|
|
||||||
# *.sublime-project
|
|
||||||
|
|
||||||
41
README.md
41
README.md
@ -7,36 +7,57 @@ http://discord.gg/GWdhBSp
|
|||||||
|
|
||||||
This bot extends the rewrite version of discord.py. A couple of variables have been added to give you easy access to a couple of objects listed here.
|
This bot extends the rewrite version of discord.py. A couple of variables have been added to give you easy access to a couple of objects listed here.
|
||||||
|
|
||||||
> self.ownerlist
|
> self.bot.ownerlist
|
||||||
|
|
||||||
self.ownerlist can be used to retrieve a `list` of user ID's. (`int`). Those ID's belong to contributors.
|
self.ownerlist can be used to retrieve a `list` of user ID's. (`int`). Those ID's belong to contributors.
|
||||||
> self.defaultprefix
|
> self.bot.defaultprefix
|
||||||
|
|
||||||
self.defaultprefix can be used to retrieve a `str` object of the default prefix.
|
self.defaultprefix can be used to retrieve a `str` object of the default prefix.
|
||||||
> self.version
|
> self.bot.version
|
||||||
|
|
||||||
self.version can be used to retrieve a `float` which represent the version number of the bot.
|
self.version can be used to retrieve a `float` which represent the version number of the bot.
|
||||||
> self.display_name
|
> self.bot.display_name
|
||||||
|
|
||||||
self.display_name returns a `str` which represent the display_name of the bot.
|
self.display_name returns a `str` which represent the display_name of the bot.
|
||||||
> self.mainenance
|
> self.bot.mainenance
|
||||||
|
|
||||||
self.maintenance is equal to `True` or `False`. If you would like to exclude code in the master branch, use this.
|
self.maintenance is equal to `True` or `False`. If you would like to exclude code in the master branch, use this.
|
||||||
Make sure this one is installed.
|
Make sure this one is installed.
|
||||||
example:
|
example:
|
||||||
```py
|
```py
|
||||||
if self.mainenance:
|
if self.bot.mainenance:
|
||||||
print('I am in the development branch')
|
print('I am in the development branch')
|
||||||
|
|
||||||
if not self.mainenance:
|
if not self.bot.mainenance:
|
||||||
print('I am in the master branch)
|
print('I am in the master branch)
|
||||||
```
|
```
|
||||||
With other words. self.mainenance returns False in production and True in developer modus.
|
With other words. self.mainenance returns False in production and True in developer modus.
|
||||||
|
|
||||||
|
> self.bot.embed_color
|
||||||
|
|
||||||
|
self.embed_color can be used to use the default color of out embed theme.
|
||||||
|
```
|
||||||
|
discord.Embed(title='Foo', description='bar', color=self.bot.embed_color)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker environment
|
||||||
|
This bot is heavly based on docker. This means it will run in a container. Other words. The code will run in a jail. Dont be afraid for bugs that cause harm. or commands that could potential restarts the server. Its safe.
|
||||||
|
|
||||||
|
There are a couple of things to know about docker within this project.
|
||||||
|
1. Please read the docs of docker first before editing the docker files
|
||||||
|
2. If you need a pip package, place the name into requirements.txt, docker handles the rest.
|
||||||
|
3. Everything in project folder is the workfolder of the docker container
|
||||||
|
4. Initialize cogs by adding them into cogs.txt. one line is one cogfile
|
||||||
|
|
||||||
## Initialize a cog
|
## Initialize a cog
|
||||||
Cogs can be placed in `./src/cogs`. Overall the `src` folder is the place to put code in.
|
Put your cog in `src/cogs` and edit the `cogs.txt` file. Add the filename of your cog into `cogs.txt`. No absolute path, just the name.
|
||||||
Make sure to update the `requirements.txt` and it is important to add the name of your cog file into the `cogs.txt` list. Otherwise it may turn out that your cog wont load.
|
|
||||||
|
|
||||||
## Update source code
|
## Update source code
|
||||||
There is a git command available provided by Dusty. `S!git pull` should pull the latest commits into the docker container. Make sure afterwards to reload the cog.
|
There is a git command available provided by Dusty. `S!git pull` should pull the latest commits into the docker container. Make sure afterwards to reload the cog.
|
||||||
If you are stuck in any way shape or form you can always contact anyone who works on this project. Dont forget to check `S!help`.
|
If you are stuck in any way shape or form you can always contact anyone who works on this project. Dont forget to check `S!help`.
|
||||||
|
|
||||||
|
## Project links:
|
||||||
|
- http://discord.gg/GWdhBSp
|
||||||
|
- http://chillout.ueuo.com
|
||||||
|
- http://trello.com/b/x02goBbW/sebis-bot-tutorial-roadmap
|
||||||
|
|
||||||
|
|||||||
BIN
avatar.png
Normal file
BIN
avatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@ -1,2 +1,3 @@
|
|||||||
yarl<1.2
|
yarl<1.2
|
||||||
numpy==1.14.0
|
numpy==1.14.0
|
||||||
|
uvloop
|
||||||
|
|||||||
17
run.py
17
run.py
@ -2,6 +2,7 @@
|
|||||||
# -*- coding: utf8 -*-
|
# -*- coding: utf8 -*-
|
||||||
|
|
||||||
# Import packages
|
# Import packages
|
||||||
|
import asyncio
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
import json
|
import json
|
||||||
@ -11,6 +12,18 @@ import random
|
|||||||
# Import custom files
|
# Import custom files
|
||||||
from src.config.config import LoadConfig
|
from src.config.config import LoadConfig
|
||||||
|
|
||||||
|
# If uvloop is installed, change to that eventloop policy as it
|
||||||
|
# is more efficient
|
||||||
|
try:
|
||||||
|
import uvloop
|
||||||
|
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||||
|
del uvloop
|
||||||
|
except BaseException as ex:
|
||||||
|
print(f'Could not load uvloop. {type(ex).__name__}: {ex};',
|
||||||
|
'reverting to default impl.')
|
||||||
|
else:
|
||||||
|
print(f'Using uvloop for asyncio event loop policy.')
|
||||||
|
|
||||||
|
|
||||||
# Bot Class
|
# Bot Class
|
||||||
class SebiMachine(commands.Bot, LoadConfig):
|
class SebiMachine(commands.Bot, LoadConfig):
|
||||||
@ -19,7 +32,7 @@ class SebiMachine(commands.Bot, LoadConfig):
|
|||||||
# Initialize and attach config / settings
|
# Initialize and attach config / settings
|
||||||
LoadConfig.__init__(self)
|
LoadConfig.__init__(self)
|
||||||
commands.Bot.__init__(self, command_prefix=self.defaultprefix)
|
commands.Bot.__init__(self, command_prefix=self.defaultprefix)
|
||||||
self.embed_color = discord.Color(0x00FFFF)
|
|
||||||
|
|
||||||
# Load plugins
|
# Load plugins
|
||||||
# Add your cog file name in this list
|
# Add your cog file name in this list
|
||||||
@ -67,4 +80,4 @@ if __name__ == '__main__':
|
|||||||
with open('src/config/PrivateConfig.json') as fp:
|
with open('src/config/PrivateConfig.json') as fp:
|
||||||
PrivateConfig = json.load(fp)
|
PrivateConfig = json.load(fp)
|
||||||
fp.close()
|
fp.close()
|
||||||
client.run(PrivateConfig["bot-key"])
|
client.run(PrivateConfig["bot-key"])
|
||||||
|
|||||||
126
src/cogs/code.py
Normal file
126
src/cogs/code.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
from discord.ext import commands
|
||||||
|
import traceback
|
||||||
|
import textwrap
|
||||||
|
from contextlib import redirect_stdout
|
||||||
|
import io
|
||||||
|
|
||||||
|
|
||||||
|
class REPL:
|
||||||
|
"""Python in Discords"""
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self._last_result = None
|
||||||
|
self.sessions = set()
|
||||||
|
|
||||||
|
def cleanup_code(self, content):
|
||||||
|
"""
|
||||||
|
Automatically removes code blocks from the code.
|
||||||
|
"""
|
||||||
|
# remove ```py\n```
|
||||||
|
if content.startswith('```') and content.endswith('```'):
|
||||||
|
return '\n'.join(content.split('\n')[1:-1])
|
||||||
|
|
||||||
|
# remove `foo`
|
||||||
|
return content.strip('` \n')
|
||||||
|
|
||||||
|
def get_syntax_error(self, e):
|
||||||
|
if e.text is None:
|
||||||
|
return '{0.__class__.__name__}: {0}'.format(e)
|
||||||
|
return '{0.text}{1:>{0.offset}}\n{2}: {0}'.format(e, '^', type(e).__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@commands.command(name='exec')
|
||||||
|
async def _eval(self, ctx, *, body: str = None):
|
||||||
|
"""
|
||||||
|
Execute python code in discord chat.
|
||||||
|
Only the owner of this bot can use this command.
|
||||||
|
|
||||||
|
Alias:
|
||||||
|
- exec
|
||||||
|
Usage:
|
||||||
|
- exec < python code >
|
||||||
|
Example:
|
||||||
|
- exec print(546132)
|
||||||
|
"""
|
||||||
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
|
|
||||||
|
if body is None:
|
||||||
|
return await ctx.send(
|
||||||
|
'Please, use\n'
|
||||||
|
f'`{self.bot.config["prefix"]}exec`\n\n'
|
||||||
|
'\n`\\`\\`\\`py\n[python code]\n\\`\\`\\`\n'
|
||||||
|
'to get the most out of the command')
|
||||||
|
|
||||||
|
env = {
|
||||||
|
'bot': self.bot,
|
||||||
|
'ctx': ctx,
|
||||||
|
'channel': ctx.message.channel,
|
||||||
|
'author': ctx.message.author,
|
||||||
|
'server': ctx.message.guild,
|
||||||
|
'message': ctx.message,
|
||||||
|
'_': self._last_result
|
||||||
|
}
|
||||||
|
|
||||||
|
env.update(globals())
|
||||||
|
|
||||||
|
body = self.cleanup_code(body)
|
||||||
|
stdout = io.StringIO()
|
||||||
|
|
||||||
|
to_compile = 'async def func():\n%s' % textwrap.indent(body, ' ')
|
||||||
|
|
||||||
|
try:
|
||||||
|
exec(to_compile, env)
|
||||||
|
except SyntaxError as e:
|
||||||
|
try:
|
||||||
|
msg = await ctx.send(f'```py\n{self.get_syntax_error(e)}\n```')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error = [self.get_syntax_error(e)[i:i+2000] for i in range(0, len(self.get_syntax_error(e)), 2000)]
|
||||||
|
for i in error:
|
||||||
|
msg = await ctx.send(f'```py\n{i}\n```')
|
||||||
|
|
||||||
|
func = env['func']
|
||||||
|
try:
|
||||||
|
with redirect_stdout(stdout):
|
||||||
|
ret = await func()
|
||||||
|
except Exception as e:
|
||||||
|
value = stdout.getvalue()
|
||||||
|
try:
|
||||||
|
msg = await ctx.send(f'```py\n{value}{traceback.format_exc()}\n```')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error = [value[i:i + 2000] for i in range(0, len(value), 2000)]
|
||||||
|
for i in error:
|
||||||
|
await ctx.send(f'```py\n{i}\n```')
|
||||||
|
|
||||||
|
tracebackerror = [traceback.format_exc()[i:i + 2000] for i in range(0, len(traceback.format_exc()), 2000)]
|
||||||
|
for i in tracebackerror:
|
||||||
|
msg = await ctx.send(f'```py\n{i}\n```')
|
||||||
|
else:
|
||||||
|
value = stdout.getvalue()
|
||||||
|
if ret is None:
|
||||||
|
if value:
|
||||||
|
try:
|
||||||
|
msg = await ctx.send(f'```py\n{value}\n```')
|
||||||
|
except Exception as e:
|
||||||
|
code = [value[i:i + 1980] for i in range(0, len(value), 1980)]
|
||||||
|
for i in code:
|
||||||
|
msg = await ctx.send(f'```py\n{i}\n```')
|
||||||
|
else:
|
||||||
|
self._last_result = ret
|
||||||
|
try:
|
||||||
|
code = [value[i:i + 1980] for i in range(0, len(value), 1980)]
|
||||||
|
for i in code:
|
||||||
|
msg = await ctx.send(f'```py\n{i}\n```')
|
||||||
|
except Exception as e:
|
||||||
|
code = [value[i:i + 1980] for i in range(0, len(value), 1980)]
|
||||||
|
for i in code:
|
||||||
|
await ctx.send(f'```py\n{i}\n```')
|
||||||
|
modifyd_ret = [ret[i:i + 1980] for i in range(0, len(ret), 1980)]
|
||||||
|
for i in modifyd_ret:
|
||||||
|
msg = await ctx.send(f'```py\n{i}\n```')
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(REPL(bot))
|
||||||
@ -1,87 +1,92 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: <encoding name> -*-
|
# -*- coding: <encoding name> -*-
|
||||||
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
class Upload:
|
class Upload:
|
||||||
"""
|
"""
|
||||||
CogName should be the name of the cog
|
CogName should be the name of the cog
|
||||||
"""
|
"""
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
print('upload loaded')
|
print('upload loaded')
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
async def reload(self, ctx, *, extension: str):
|
async def reload(self, ctx, *, extension: str):
|
||||||
"""Reload an extension."""
|
"""Reload an extension."""
|
||||||
|
await ctx.trigger_typing()
|
||||||
if ctx.author.id not in self.bot.ownerlist:
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
return await ctx.send('Only my creator can use me like this :blush:', delete_after=10)
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
|
|
||||||
extension = extension.lower()
|
extension = extension.lower()
|
||||||
try:
|
try:
|
||||||
self.bot.unload_extension("src.cogs.{}".format(extension))
|
self.bot.unload_extension("src.cogs.{}".format(extension))
|
||||||
self.bot.load_extension("src.cogs.{}".format(extension))
|
self.bot.load_extension("src.cogs.{}".format(extension))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
await ctx.send(f'Could not reload `{extension}` -> `{e}`')
|
await ctx.send(f'Could not reload `{extension}` -> `{e}`')
|
||||||
else:
|
else:
|
||||||
await ctx.send(f'Reloaded `{extension}`.')
|
await ctx.send(f'Reloaded `{extension}`.')
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
async def reloadall(self, ctx):
|
async def reloadall(self, ctx):
|
||||||
"""Reload all extensions."""
|
"""Reload all extensions."""
|
||||||
if ctx.author.id not in self.bot.ownerlist:
|
await ctx.trigger_typing()
|
||||||
return await ctx.send('Only my creator can use me like this :blush:', delete_after=10)
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
try:
|
|
||||||
for extension in self.bot.extensions:
|
try:
|
||||||
self.bot.unload_extension(extension)
|
for extension in self.bot.extensions:
|
||||||
self.bot.load_extension(extension)
|
self.bot.unload_extension(extension)
|
||||||
await ctx.send(f"Reload success! :thumbsup:\n")
|
self.bot.load_extension(extension)
|
||||||
except Exception as e:
|
await ctx.send(f"Reload success! :thumbsup:\n")
|
||||||
await ctx.send(f"Could not reload `{extension}` -> `{e}`.\n")
|
except Exception as e:
|
||||||
|
await ctx.send(f"Could not reload `{extension}` -> `{e}`.\n")
|
||||||
@commands.command()
|
|
||||||
async def unload(self, ctx, *, extension: str):
|
@commands.command()
|
||||||
"""Unload an extension."""
|
async def unload(self, ctx, *, extension: str):
|
||||||
if ctx.author.id not in self.bot.ownerlist:
|
"""Unload an extension."""
|
||||||
return await ctx.send('Only my creator can use me like this :blush:', delete_after=10)
|
await ctx.trigger_typing()
|
||||||
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
extension = extension.lower()
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
try:
|
|
||||||
self.bot.unload_extension("src.cogs.{}".format(extension))
|
extension = extension.lower()
|
||||||
|
try:
|
||||||
except Exception as e:
|
self.bot.unload_extension("src.cogs.{}".format(extension))
|
||||||
traceback.print_exc()
|
|
||||||
if ctx.message.author.id not in self.bot.owner_list:
|
except Exception as e:
|
||||||
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
traceback.print_exc()
|
||||||
|
if ctx.message.author.id not in self.bot.owner_list:
|
||||||
else:
|
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
||||||
await ctx.send(f'Unloaded `{extension}`.')
|
|
||||||
|
else:
|
||||||
@commands.command()
|
await ctx.send(f'Unloaded `{extension}`.')
|
||||||
async def load(self, ctx, *, extension: str):
|
|
||||||
"""Load an extension."""
|
@commands.command()
|
||||||
if ctx.author.id not in self.bot.ownerlist:
|
async def load(self, ctx, *, extension: str):
|
||||||
return await ctx.send('Only my creator can use me like this :blush:', delete_after=10)
|
"""Load an extension."""
|
||||||
|
await ctx.trigger_typing()
|
||||||
extension = extension.lower()
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
try:
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
self.bot.load_extension("src.cogs.{}".format(extension))
|
|
||||||
|
extension = extension.lower()
|
||||||
except Exception as e:
|
try:
|
||||||
traceback.print_exc()
|
self.bot.load_extension("src.cogs.{}".format(extension))
|
||||||
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
|
||||||
else:
|
except Exception as e:
|
||||||
await ctx.send(f'Loaded `{extension}`.')
|
traceback.print_exc()
|
||||||
|
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
||||||
@commands.command()
|
else:
|
||||||
async def err(self, ctx):
|
await ctx.send(f'Loaded `{extension}`.')
|
||||||
"""triggers error to test traceback"""
|
|
||||||
await ctx.send(a)
|
@commands.command()
|
||||||
|
async def err(self, ctx):
|
||||||
def setup(bot):
|
"""triggers error to test traceback"""
|
||||||
|
await ctx.send(a)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
bot.add_cog(Upload(bot))
|
bot.add_cog(Upload(bot))
|
||||||
@ -1,20 +1,24 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: <encoding name> -*-
|
# -*- coding: <encoding name> -*-
|
||||||
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
class CogName:
|
class CogName:
|
||||||
"""
|
"""
|
||||||
CogName should be the name of the cog
|
CogName should be the name of the cog
|
||||||
"""
|
"""
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
async def ping(self, ctx):
|
async def ping(self, ctx):
|
||||||
"""Say pong"""
|
"""Say pong"""
|
||||||
await ctx.send('Pong')
|
now = ctx.message.created_at
|
||||||
|
msg = await ctx.send('Pong')
|
||||||
def setup(bot):
|
sub = msg.created_at - now
|
||||||
bot.add_cog(CogName(bot))
|
await msg.edit(content=f'Pong, {sub.total_seconds() * 1000}')
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(CogName(bot))
|
||||||
|
|||||||
44
src/cogs/fun.py
Normal file
44
src/cogs/fun.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: <encoding name> -*-
|
||||||
|
|
||||||
|
from discord.ext import commands
|
||||||
|
import discord
|
||||||
|
import random
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
|
class Fun:
|
||||||
|
"""
|
||||||
|
CogName should be the name of the cog
|
||||||
|
"""
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
@commands.command()
|
||||||
|
async def sebisauce(self, ctx):
|
||||||
|
"""
|
||||||
|
Get a image related to Sebi.
|
||||||
|
Sebi is a random guy with perfect code related jokes.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
- sebisauce
|
||||||
|
"""
|
||||||
|
await ctx.trigger_typing()
|
||||||
|
url = 'http://ikbengeslaagd.com/API/sebisauce.json'
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(url) as response:
|
||||||
|
source = await response.json(encoding='utf8')
|
||||||
|
|
||||||
|
total_sebi = 0
|
||||||
|
for key in dict.keys(source):
|
||||||
|
total_sebi += 1
|
||||||
|
|
||||||
|
im = random.randint(0, int(total_sebi) - 1)
|
||||||
|
|
||||||
|
await ctx.send(embed=discord.Embed(
|
||||||
|
title='\t',
|
||||||
|
description='\t',
|
||||||
|
color=self.bot.embed_color).set_image(
|
||||||
|
url=source[str(im)]))
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Fun(bot))
|
||||||
180
src/cogs/git.py
180
src/cogs/git.py
@ -1,90 +1,90 @@
|
|||||||
"""
|
"""
|
||||||
===
|
===
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
The above copyright notice and this permission notice shall be
|
||||||
included in all copies or substantial portions of the Software.
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
import logging
|
import logging
|
||||||
from ..shared_libs.utils import paginate, run_command
|
from ..shared_libs.utils import paginate, run_command
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
git_log = logging.getLogger('git')
|
git_log = logging.getLogger('git')
|
||||||
|
|
||||||
|
|
||||||
class Git:
|
class Git:
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@commands.group(case_insensitive=True)
|
@commands.group(case_insensitive=True)
|
||||||
async def git(self, ctx):
|
async def git(self, ctx):
|
||||||
"""Run help git for more info"""
|
"""Run help git for more info"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@git.command()
|
@git.command()
|
||||||
async def pull(self, ctx):
|
async def pull(self, ctx):
|
||||||
await ctx.trigger_typing()
|
await ctx.trigger_typing()
|
||||||
if ctx.author.id not in self.bot.ownerlist:
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
return await ctx.send('Only my creator can use me like this :blush:', delete_after=10)
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
em = discord.Embed(style='rich',
|
em = discord.Embed(style='rich',
|
||||||
title=f'Git Pull',
|
title=f'Git Pull',
|
||||||
color=self.bot.embed_color)
|
color=self.bot.embed_color)
|
||||||
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
||||||
|
|
||||||
result = await asyncio.wait_for(self.bot.loop.create_task(
|
result = await asyncio.wait_for(self.bot.loop.create_task(
|
||||||
run_command('git fetch --all')), 120) + '\n'
|
run_command('git fetch --all')), 120) + '\n'
|
||||||
result += await asyncio.wait_for(self.bot.loop.create_task(
|
result += await asyncio.wait_for(self.bot.loop.create_task(
|
||||||
run_command('git reset --hard origin/$(git rev-parse '
|
run_command('git reset --hard origin/$(git rev-parse '
|
||||||
'--symbolic-full-name --abbrev-ref HEAD)')),
|
'--symbolic-full-name --abbrev-ref HEAD)')),
|
||||||
120) + '\n\n'
|
120) + '\n\n'
|
||||||
result += await asyncio.wait_for(self.bot.loop.create_task(
|
result += await asyncio.wait_for(self.bot.loop.create_task(
|
||||||
run_command('git show --stat | sed "s/.*@.*[.].*/ /g"')), 10)
|
run_command('git show --stat | sed "s/.*@.*[.].*/ /g"')), 10)
|
||||||
|
|
||||||
results = paginate(result, maxlen=1014)
|
results = paginate(result, maxlen=1014)
|
||||||
for page in results[:5]:
|
for page in results[:5]:
|
||||||
em.add_field(name='\uFFF0', value=f'{page}')
|
em.add_field(name='\uFFF0', value=f'{page}')
|
||||||
await ctx.send(embed=em)
|
await ctx.send(embed=em)
|
||||||
|
|
||||||
@git.command()
|
@git.command()
|
||||||
async def status(self, ctx):
|
async def status(self, ctx):
|
||||||
await ctx.trigger_typing()
|
await ctx.trigger_typing()
|
||||||
if ctx.author.id not in self.bot.ownerlist:
|
if ctx.author.id not in self.bot.ownerlist:
|
||||||
return await ctx.send('Only my creator can use me like this :blush:', delete_after=10)
|
return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10)
|
||||||
em = discord.Embed(style='rich',
|
em = discord.Embed(style='rich',
|
||||||
title=f'Git Pull',
|
title=f'Git Status',
|
||||||
color=self.bot.embed_color)
|
color=self.bot.embed_color)
|
||||||
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
||||||
result = await asyncio.wait_for(self.bot.loop.create_task(
|
result = await asyncio.wait_for(self.bot.loop.create_task(
|
||||||
run_command('git status')), 10)
|
run_command('git status')), 10)
|
||||||
results = paginate(result, maxlen=1014)
|
results = paginate(result, maxlen=1014)
|
||||||
for page in results[:5]:
|
for page in results[:5]:
|
||||||
em.add_field(name='\uFFF0', value=f'{page}')
|
em.add_field(name='\uFFF0', value=f'{page}')
|
||||||
await ctx.send(embed=em)
|
await ctx.send(embed=em)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
bot.add_cog(Git(bot))
|
bot.add_cog(Git(bot))
|
||||||
|
|||||||
7
src/config/Config.json
Normal file
7
src/config/Config.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 0.1,
|
||||||
|
"display_name" : "[S!] Sebi-Machine",
|
||||||
|
"maintenance": "True",
|
||||||
|
"ownerlist": [],
|
||||||
|
"prefix": "S!"
|
||||||
|
}
|
||||||
3
src/config/PrivateConfig.json
Normal file
3
src/config/PrivateConfig.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"bot-key": ""
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
# -*- coding: <encoding name> -*-
|
# -*- coding: <encoding name> -*-
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import discord
|
||||||
|
|
||||||
class LoadConfig:
|
class LoadConfig:
|
||||||
"""
|
"""
|
||||||
@ -19,6 +19,7 @@ class LoadConfig:
|
|||||||
self.version = self.config["version"]
|
self.version = self.config["version"]
|
||||||
self.display_name = self.config["display_name"]
|
self.display_name = self.config["display_name"]
|
||||||
self.maintenance = self.config["maintenance"]
|
self.maintenance = self.config["maintenance"]
|
||||||
|
self.embed_color = discord.Color(0x00FFFF)
|
||||||
if self.maintenance == 'False':
|
if self.maintenance == 'False':
|
||||||
self.maintenance = False
|
self.maintenance = False
|
||||||
else:
|
else:
|
||||||
|
|||||||
6
src/shared_libs/aliases.json
Normal file
6
src/shared_libs/aliases.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"sar": "sar",
|
||||||
|
"selfrole": "sar",
|
||||||
|
"selfroles": "sar"
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,113 +1,113 @@
|
|||||||
"""
|
"""
|
||||||
===
|
===
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
The above copyright notice and this permission notice shall be
|
||||||
included in all copies or substantial portions of the Software.
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import sys
|
import sys
|
||||||
import asyncio
|
import asyncio
|
||||||
import discord
|
import discord
|
||||||
from discord.ext.commands.formatter import Paginator
|
from discord.ext.commands.formatter import Paginator
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class Capturing(list):
|
class Capturing(list):
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self._stdout = sys.stdout
|
self._stdout = sys.stdout
|
||||||
sys.stdout = self._stringio = StringIO()
|
sys.stdout = self._stringio = StringIO()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
self.extend(self._stringio.getvalue().splitlines())
|
self.extend(self._stringio.getvalue().splitlines())
|
||||||
del self._stringio # free up some memory
|
del self._stringio # free up some memory
|
||||||
sys.stdout = self._stdout
|
sys.stdout = self._stdout
|
||||||
|
|
||||||
|
|
||||||
def to_list_of_str(items, out: list=list(), level=1, recurse=0):
|
def to_list_of_str(items, out: list=list(), level=1, recurse=0):
|
||||||
def rec_loop(item, key, out, level):
|
def rec_loop(item, key, out, level):
|
||||||
quote = '"'
|
quote = '"'
|
||||||
if type(item) == list:
|
if type(item) == list:
|
||||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}[')
|
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}[')
|
||||||
new_level = level + 1
|
new_level = level + 1
|
||||||
out = to_list_of_str(item, out, new_level, 1)
|
out = to_list_of_str(item, out, new_level, 1)
|
||||||
out.append(f'{" "*level}]')
|
out.append(f'{" "*level}]')
|
||||||
elif type(item) == dict:
|
elif type(item) == dict:
|
||||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{{')
|
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{{')
|
||||||
new_level = level + 1
|
new_level = level + 1
|
||||||
out = to_list_of_str(item, out, new_level, 1)
|
out = to_list_of_str(item, out, new_level, 1)
|
||||||
out.append(f'{" "*level}}}')
|
out.append(f'{" "*level}}}')
|
||||||
else:
|
else:
|
||||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{repr(item)},')
|
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{repr(item)},')
|
||||||
|
|
||||||
if type(items) == list:
|
if type(items) == list:
|
||||||
if not recurse:
|
if not recurse:
|
||||||
out = list()
|
out = list()
|
||||||
out.append('[')
|
out.append('[')
|
||||||
for item in items:
|
for item in items:
|
||||||
rec_loop(item, None, out, level)
|
rec_loop(item, None, out, level)
|
||||||
if not recurse:
|
if not recurse:
|
||||||
out.append(']')
|
out.append(']')
|
||||||
elif type(items) == dict:
|
elif type(items) == dict:
|
||||||
if not recurse:
|
if not recurse:
|
||||||
out = list()
|
out = list()
|
||||||
out.append('{')
|
out.append('{')
|
||||||
for key in items:
|
for key in items:
|
||||||
rec_loop(items[key], key, out, level)
|
rec_loop(items[key], key, out, level)
|
||||||
if not recurse:
|
if not recurse:
|
||||||
out.append('}')
|
out.append('}')
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def paginate(text, maxlen=1990):
|
def paginate(text, maxlen=1990):
|
||||||
paginator = Paginator(prefix='```py', max_size=maxlen+10)
|
paginator = Paginator(prefix='```py', max_size=maxlen+10)
|
||||||
if type(text) == list:
|
if type(text) == list:
|
||||||
data = to_list_of_str(text)
|
data = to_list_of_str(text)
|
||||||
elif type(text) == dict:
|
elif type(text) == dict:
|
||||||
data = to_list_of_str(text)
|
data = to_list_of_str(text)
|
||||||
else:
|
else:
|
||||||
data = str(text).split('\n')
|
data = str(text).split('\n')
|
||||||
for line in data:
|
for line in data:
|
||||||
if len(line) > maxlen:
|
if len(line) > maxlen:
|
||||||
n = maxlen
|
n = maxlen
|
||||||
for l in [line[i:i+n] for i in range(0, len(line), n)]:
|
for l in [line[i:i+n] for i in range(0, len(line), n)]:
|
||||||
paginator.add_line(l)
|
paginator.add_line(l)
|
||||||
else:
|
else:
|
||||||
paginator.add_line(line)
|
paginator.add_line(line)
|
||||||
return paginator.pages
|
return paginator.pages
|
||||||
|
|
||||||
|
|
||||||
async def run_command(args):
|
async def run_command(args):
|
||||||
# Create subprocess
|
# Create subprocess
|
||||||
process = await asyncio.create_subprocess_shell(
|
process = await asyncio.create_subprocess_shell(
|
||||||
args,
|
args,
|
||||||
# stdout must a pipe to be accessible as process.stdout
|
# stdout must a pipe to be accessible as process.stdout
|
||||||
stdout=asyncio.subprocess.PIPE)
|
stdout=asyncio.subprocess.PIPE)
|
||||||
# Wait for the subprocess to finish
|
# Wait for the subprocess to finish
|
||||||
stdout, stderr = await process.communicate()
|
stdout, stderr = await process.communicate()
|
||||||
# Return stdout
|
# Return stdout
|
||||||
return stdout.decode().strip()
|
return stdout.decode().strip()
|
||||||
Loading…
x
Reference in New Issue
Block a user