Rebase project v0.1
This commit is contained in:
parent
5f9368e037
commit
b8f5f0da0c
5
.gitignore
vendored
5
.gitignore
vendored
@ -103,7 +103,4 @@ venv.bak/
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
/src/config/Config.json
|
||||
/src/config/PrivateConfig.json
|
||||
.idea/
|
||||
.vscode/
|
||||
.idea/
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
||||
{
|
||||
"python.pythonPath": "/usr/bin/python3.6"
|
||||
}
|
||||
19
README.md
19
README.md
@ -39,14 +39,25 @@ 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
|
||||
Cogs can be placed in `./src/cogs`. Overall the `src` folder is the place to put code in.
|
||||
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.
|
||||
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.
|
||||
|
||||
## 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.
|
||||
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`.
|
||||
|
||||
## Trello
|
||||
We do make use of Trello which can be found here: https://trello.com/b/x02goBbW/sebis-bot-tutorial-roadmap
|
||||
## Project links:
|
||||
- http://discord.gg/GWdhBSp
|
||||
- http://chillout.ueuo.com
|
||||
- http://trello.com/b/x02goBbW/sebis-bot-tutorial-roadmap
|
||||
|
||||
|
||||
@ -12,12 +12,8 @@ RUN add-apt-repository ppa:deadsnakes/ppa && \
|
||||
apt-get update && apt-get install python3.6 && \
|
||||
apt-get install python3-pip -y
|
||||
RUN apt install git -y
|
||||
RUN apt install curl -y
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - && \
|
||||
apt install nodejs -y
|
||||
RUN npm install discord.js
|
||||
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 ['bash', '-c', 'entrypoint.sh']
|
||||
cmd ["python3.6","run.py"]
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
python3.6 run.py > bot-log.txt 2>&1 &
|
||||
nodejs run.js > node-log.txt 2>&1 &
|
||||
|
||||
for job in $(jobs -p); do
|
||||
echo Waiting for ${job} to terminate.
|
||||
wait ${job}
|
||||
done
|
||||
47
run.js
47
run.js
@ -1,47 +0,0 @@
|
||||
const Discord = require("discord.js");
|
||||
const client = new Discord.Client();
|
||||
|
||||
const config = require("./src/config/Config.json");
|
||||
const prefix = config.prefix;
|
||||
|
||||
const aliases = require("./src/shared_libs/aliases.json");
|
||||
const privateConfig = require("./src/config/PrivateConfig.json");
|
||||
|
||||
const fs = require("fs");
|
||||
const commands = fs.readdirSync("./src/cogs").filter(function(e) {
|
||||
return e.endsWith(".js");
|
||||
});
|
||||
|
||||
|
||||
client.on("message", function(message) {
|
||||
|
||||
if (message.guild.id != "265828729970753537") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.content.startsWith(config.prefix) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const msg = message.content.replace(prefix, "");
|
||||
|
||||
let command = msg.split(" ")[0];
|
||||
const args = msg.split(" ").slice(1);
|
||||
|
||||
command = aliases[command];
|
||||
|
||||
try {
|
||||
|
||||
if (commands.includes(`${command}.js`)) {
|
||||
require(`./src/cogs/${command}.js`).run(client, message, args);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
// handling errors
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
client.login(privateConfig["bot-key"]);
|
||||
3
run.py
3
run.py
@ -70,8 +70,7 @@ class SebiMachine(commands.Bot, LoadConfig):
|
||||
tb = ''.join(tb)
|
||||
joke = random.choice(jokes)
|
||||
fmt = f'**`{self.defaultprefix}{ctx.command}`**\n{joke}\n\n**{type(error).__name__}:**:\n```py\n{tb}\n```'
|
||||
# unused variable
|
||||
# simple_fmt = f'**`{self.defaultprefix}{ctx.command}`**\n{joke}\n\n**{type(error).__name__}:**:\n**`{error}`**'
|
||||
simple_fmt = f'**`{self.defaultprefix}{ctx.command}`**\n{joke}\n\n**{type(error).__name__}:**:\n**`{error}`**'
|
||||
await ctx.send(fmt)
|
||||
|
||||
|
||||
|
||||
250
src/cogs/code.py
250
src/cogs/code.py
@ -1,126 +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):
|
||||
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,92 +1,92 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: <encoding name> -*-
|
||||
|
||||
from discord.ext import commands
|
||||
import os
|
||||
import traceback
|
||||
|
||||
class Upload:
|
||||
"""
|
||||
CogName should be the name of the cog
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
print('upload loaded')
|
||||
|
||||
@commands.command()
|
||||
async def reload(self, ctx, *, extension: str):
|
||||
"""Reload an extension."""
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
|
||||
extension = extension.lower()
|
||||
try:
|
||||
self.bot.unload_extension("src.cogs.{}".format(extension))
|
||||
self.bot.load_extension("src.cogs.{}".format(extension))
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
await ctx.send(f'Could not reload `{extension}` -> `{e}`')
|
||||
else:
|
||||
await ctx.send(f'Reloaded `{extension}`.')
|
||||
|
||||
@commands.command()
|
||||
async def reloadall(self, ctx):
|
||||
"""Reload all extensions."""
|
||||
await ctx.trigger_typing()
|
||||
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:
|
||||
self.bot.unload_extension(extension)
|
||||
self.bot.load_extension(extension)
|
||||
await ctx.send(f"Reload success! :thumbsup:\n")
|
||||
except Exception as e:
|
||||
await ctx.send(f"Could not reload `{extension}` -> `{e}`.\n")
|
||||
|
||||
@commands.command()
|
||||
async def unload(self, ctx, *, extension: str):
|
||||
"""Unload an extension."""
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
|
||||
extension = extension.lower()
|
||||
try:
|
||||
self.bot.unload_extension("src.cogs.{}".format(extension))
|
||||
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
if ctx.message.author.id not in self.bot.owner_list:
|
||||
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
||||
|
||||
else:
|
||||
await ctx.send(f'Unloaded `{extension}`.')
|
||||
|
||||
@commands.command()
|
||||
async def load(self, ctx, *, extension: str):
|
||||
"""Load an extension."""
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
|
||||
extension = extension.lower()
|
||||
try:
|
||||
self.bot.load_extension("src.cogs.{}".format(extension))
|
||||
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
||||
else:
|
||||
await ctx.send(f'Loaded `{extension}`.')
|
||||
|
||||
@commands.command()
|
||||
async def err(self, ctx):
|
||||
"""triggers error to test traceback"""
|
||||
await ctx.send(a)
|
||||
|
||||
|
||||
|
||||
def setup(bot):
|
||||
#!/usr/bin/python
|
||||
# -*- coding: <encoding name> -*-
|
||||
|
||||
from discord.ext import commands
|
||||
import os
|
||||
import traceback
|
||||
|
||||
class Upload:
|
||||
"""
|
||||
CogName should be the name of the cog
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
print('upload loaded')
|
||||
|
||||
@commands.command()
|
||||
async def reload(self, ctx, *, extension: str):
|
||||
"""Reload an extension."""
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
|
||||
extension = extension.lower()
|
||||
try:
|
||||
self.bot.unload_extension("src.cogs.{}".format(extension))
|
||||
self.bot.load_extension("src.cogs.{}".format(extension))
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
await ctx.send(f'Could not reload `{extension}` -> `{e}`')
|
||||
else:
|
||||
await ctx.send(f'Reloaded `{extension}`.')
|
||||
|
||||
@commands.command()
|
||||
async def reloadall(self, ctx):
|
||||
"""Reload all extensions."""
|
||||
await ctx.trigger_typing()
|
||||
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:
|
||||
self.bot.unload_extension(extension)
|
||||
self.bot.load_extension(extension)
|
||||
await ctx.send(f"Reload success! :thumbsup:\n")
|
||||
except Exception as e:
|
||||
await ctx.send(f"Could not reload `{extension}` -> `{e}`.\n")
|
||||
|
||||
@commands.command()
|
||||
async def unload(self, ctx, *, extension: str):
|
||||
"""Unload an extension."""
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
|
||||
extension = extension.lower()
|
||||
try:
|
||||
self.bot.unload_extension("src.cogs.{}".format(extension))
|
||||
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
if ctx.message.author.id not in self.bot.owner_list:
|
||||
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
||||
|
||||
else:
|
||||
await ctx.send(f'Unloaded `{extension}`.')
|
||||
|
||||
@commands.command()
|
||||
async def load(self, ctx, *, extension: str):
|
||||
"""Load an extension."""
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
|
||||
extension = extension.lower()
|
||||
try:
|
||||
self.bot.load_extension("src.cogs.{}".format(extension))
|
||||
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
await ctx.send(f'Could not unload `{extension}` -> `{e}`')
|
||||
else:
|
||||
await ctx.send(f'Loaded `{extension}`.')
|
||||
|
||||
@commands.command()
|
||||
async def err(self, ctx):
|
||||
"""triggers error to test traceback"""
|
||||
await ctx.send(a)
|
||||
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Upload(bot))
|
||||
@ -1,24 +1,24 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: <encoding name> -*-
|
||||
|
||||
from discord.ext import commands
|
||||
import discord
|
||||
|
||||
class CogName:
|
||||
"""
|
||||
CogName should be the name of the cog
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command()
|
||||
async def ping(self, ctx):
|
||||
"""Say pong"""
|
||||
now = ctx.message.created_at
|
||||
msg = await ctx.send('Pong')
|
||||
sub = msg.created_at - now
|
||||
await msg.edit(content=f'Pong, {sub.total_seconds() * 1000}')
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(CogName(bot))
|
||||
#!/usr/bin/python
|
||||
# -*- coding: <encoding name> -*-
|
||||
|
||||
from discord.ext import commands
|
||||
import discord
|
||||
|
||||
class CogName:
|
||||
"""
|
||||
CogName should be the name of the cog
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command()
|
||||
async def ping(self, ctx):
|
||||
"""Say pong"""
|
||||
now = ctx.message.created_at
|
||||
msg = await ctx.send('Pong')
|
||||
sub = msg.created_at - now
|
||||
await msg.edit(content=f'Pong, {sub.total_seconds() * 1000}')
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(CogName(bot))
|
||||
|
||||
@ -1,44 +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))
|
||||
#!/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
|
||||
|
||||
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
||||
|
||||
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
|
||||
from discord.ext import commands
|
||||
import logging
|
||||
from ..shared_libs.utils import paginate, run_command
|
||||
import asyncio
|
||||
|
||||
git_log = logging.getLogger('git')
|
||||
|
||||
|
||||
class Git:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.group(case_insensitive=True)
|
||||
async def git(self, ctx):
|
||||
"""Run help git for more info"""
|
||||
pass
|
||||
|
||||
@git.command()
|
||||
async def pull(self, ctx):
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
em = discord.Embed(style='rich',
|
||||
title=f'Git Pull',
|
||||
color=self.bot.embed_color)
|
||||
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
||||
|
||||
result = await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git fetch --all')), 120) + '\n'
|
||||
result += await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git reset --hard origin/$(git rev-parse '
|
||||
'--symbolic-full-name --abbrev-ref HEAD)')),
|
||||
120) + '\n\n'
|
||||
result += await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git show --stat | sed "s/.*@.*[.].*/ /g"')), 10)
|
||||
|
||||
results = paginate(result, maxlen=1014)
|
||||
for page in results[:5]:
|
||||
em.add_field(name='\uFFF0', value=f'{page}')
|
||||
await ctx.send(embed=em)
|
||||
|
||||
@git.command()
|
||||
async def status(self, ctx):
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
em = discord.Embed(style='rich',
|
||||
title=f'Git Status',
|
||||
color=self.bot.embed_color)
|
||||
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
||||
result = await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git status')), 10)
|
||||
results = paginate(result, maxlen=1014)
|
||||
for page in results[:5]:
|
||||
em.add_field(name='\uFFF0', value=f'{page}')
|
||||
await ctx.send(embed=em)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Git(bot))
|
||||
"""
|
||||
===
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
||||
|
||||
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
|
||||
from discord.ext import commands
|
||||
import logging
|
||||
from ..shared_libs.utils import paginate, run_command
|
||||
import asyncio
|
||||
|
||||
git_log = logging.getLogger('git')
|
||||
|
||||
|
||||
class Git:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.group(case_insensitive=True)
|
||||
async def git(self, ctx):
|
||||
"""Run help git for more info"""
|
||||
pass
|
||||
|
||||
@git.command()
|
||||
async def pull(self, ctx):
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
em = discord.Embed(style='rich',
|
||||
title=f'Git Pull',
|
||||
color=self.bot.embed_color)
|
||||
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
||||
|
||||
result = await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git fetch --all')), 120) + '\n'
|
||||
result += await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git reset --hard origin/$(git rev-parse '
|
||||
'--symbolic-full-name --abbrev-ref HEAD)')),
|
||||
120) + '\n\n'
|
||||
result += await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git show --stat | sed "s/.*@.*[.].*/ /g"')), 10)
|
||||
|
||||
results = paginate(result, maxlen=1014)
|
||||
for page in results[:5]:
|
||||
em.add_field(name='\uFFF0', value=f'{page}')
|
||||
await ctx.send(embed=em)
|
||||
|
||||
@git.command()
|
||||
async def status(self, ctx):
|
||||
await ctx.trigger_typing()
|
||||
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)
|
||||
em = discord.Embed(style='rich',
|
||||
title=f'Git Status',
|
||||
color=self.bot.embed_color)
|
||||
em.set_thumbnail(url=f'{ctx.guild.me.avatar_url}')
|
||||
result = await asyncio.wait_for(self.bot.loop.create_task(
|
||||
run_command('git status')), 10)
|
||||
results = paginate(result, maxlen=1014)
|
||||
for page in results[:5]:
|
||||
em.add_field(name='\uFFF0', value=f'{page}')
|
||||
await ctx.send(embed=em)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Git(bot))
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
const Discord = require("discord.js");
|
||||
|
||||
exports.run = async function(client, message, args) {
|
||||
|
||||
/*
|
||||
aliases: sar, selfrole, selfroles
|
||||
|
||||
examples:
|
||||
- S!selfrole get 1 (adds async helper role)
|
||||
- S!sar remove 4 (removes rewrite helper role)
|
||||
- S!sar list (shows all roles)
|
||||
*/
|
||||
|
||||
function roleFinder(query) {
|
||||
return message.guild.roles.find(function(r) {
|
||||
return r.name.includes(query)
|
||||
}).id;
|
||||
}
|
||||
|
||||
const type = args[0]; // can be get, remove or list
|
||||
|
||||
if (type == "list") {
|
||||
|
||||
const embed = new Discord.RichEmbed()
|
||||
.setTitle("List of Self Assigned Roles")
|
||||
.setDescription("Usage: `S!sar [ get | remove | list ] [ number ]`")
|
||||
.addField("1. Async Helper", "S!sar get 1", true)
|
||||
.addField("2. Heroku Helper", "S!sar get 2", true)
|
||||
.addField("3. JS Helper", "S!sar get 3", true)
|
||||
.addField("4. Rewrite Helper", "S!sar get 4", true);
|
||||
|
||||
return message.channel.send({
|
||||
embed: embed
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const roles = [roleFinder("Async"), roleFinder("Heroku"), roleFinder("JS"), roleFinder("Rewrite")];
|
||||
|
||||
let choice = args[1]; // can be 1, 2, 3 or 4
|
||||
|
||||
// if the choice is not 1, 2, 3 or 4
|
||||
if (/^[1234]$/.test(choice) == false) {
|
||||
return message.channel.send("Enter a valid role number!"); // returns error message
|
||||
} else {
|
||||
choice -= 1; // because array indexing starts from 0. when they choose 1 it should be roles[0]
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
||||
case "get":
|
||||
message.member.addRole(roles[choice]);
|
||||
break;
|
||||
|
||||
case "remove":
|
||||
message.member.removeRole(roles[choice]);
|
||||
break;
|
||||
|
||||
default:
|
||||
return; // when it is neither get nor remove
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
message.channel.send("Added the role you wanted!"); // confirmation message
|
||||
|
||||
}
|
||||
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": ""
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"sar": "sar",
|
||||
"selfrole": "sar",
|
||||
"selfroles": "sar"
|
||||
|
||||
{
|
||||
"sar": "sar",
|
||||
"selfrole": "sar",
|
||||
"selfroles": "sar"
|
||||
|
||||
}
|
||||
@ -1,113 +1,113 @@
|
||||
"""
|
||||
===
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from io import StringIO
|
||||
import sys
|
||||
import asyncio
|
||||
import discord
|
||||
from discord.ext.commands.formatter import Paginator
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Capturing(list):
|
||||
def __enter__(self):
|
||||
self._stdout = sys.stdout
|
||||
sys.stdout = self._stringio = StringIO()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.extend(self._stringio.getvalue().splitlines())
|
||||
del self._stringio # free up some memory
|
||||
sys.stdout = self._stdout
|
||||
|
||||
|
||||
def to_list_of_str(items, out: list=list(), level=1, recurse=0):
|
||||
def rec_loop(item, key, out, level):
|
||||
quote = '"'
|
||||
if type(item) == list:
|
||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}[')
|
||||
new_level = level + 1
|
||||
out = to_list_of_str(item, out, new_level, 1)
|
||||
out.append(f'{" "*level}]')
|
||||
elif type(item) == dict:
|
||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{{')
|
||||
new_level = level + 1
|
||||
out = to_list_of_str(item, out, new_level, 1)
|
||||
out.append(f'{" "*level}}}')
|
||||
else:
|
||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{repr(item)},')
|
||||
|
||||
if type(items) == list:
|
||||
if not recurse:
|
||||
out = list()
|
||||
out.append('[')
|
||||
for item in items:
|
||||
rec_loop(item, None, out, level)
|
||||
if not recurse:
|
||||
out.append(']')
|
||||
elif type(items) == dict:
|
||||
if not recurse:
|
||||
out = list()
|
||||
out.append('{')
|
||||
for key in items:
|
||||
rec_loop(items[key], key, out, level)
|
||||
if not recurse:
|
||||
out.append('}')
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def paginate(text, maxlen=1990):
|
||||
paginator = Paginator(prefix='```py', max_size=maxlen+10)
|
||||
if type(text) == list:
|
||||
data = to_list_of_str(text)
|
||||
elif type(text) == dict:
|
||||
data = to_list_of_str(text)
|
||||
else:
|
||||
data = str(text).split('\n')
|
||||
for line in data:
|
||||
if len(line) > maxlen:
|
||||
n = maxlen
|
||||
for l in [line[i:i+n] for i in range(0, len(line), n)]:
|
||||
paginator.add_line(l)
|
||||
else:
|
||||
paginator.add_line(line)
|
||||
return paginator.pages
|
||||
|
||||
|
||||
async def run_command(args):
|
||||
# Create subprocess
|
||||
process = await asyncio.create_subprocess_shell(
|
||||
args,
|
||||
# stdout must a pipe to be accessible as process.stdout
|
||||
stdout=asyncio.subprocess.PIPE)
|
||||
# Wait for the subprocess to finish
|
||||
stdout, stderr = await process.communicate()
|
||||
# Return stdout
|
||||
"""
|
||||
===
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Dusty.P https://github.com/dustinpianalto
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from io import StringIO
|
||||
import sys
|
||||
import asyncio
|
||||
import discord
|
||||
from discord.ext.commands.formatter import Paginator
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Capturing(list):
|
||||
def __enter__(self):
|
||||
self._stdout = sys.stdout
|
||||
sys.stdout = self._stringio = StringIO()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.extend(self._stringio.getvalue().splitlines())
|
||||
del self._stringio # free up some memory
|
||||
sys.stdout = self._stdout
|
||||
|
||||
|
||||
def to_list_of_str(items, out: list=list(), level=1, recurse=0):
|
||||
def rec_loop(item, key, out, level):
|
||||
quote = '"'
|
||||
if type(item) == list:
|
||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}[')
|
||||
new_level = level + 1
|
||||
out = to_list_of_str(item, out, new_level, 1)
|
||||
out.append(f'{" "*level}]')
|
||||
elif type(item) == dict:
|
||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{{')
|
||||
new_level = level + 1
|
||||
out = to_list_of_str(item, out, new_level, 1)
|
||||
out.append(f'{" "*level}}}')
|
||||
else:
|
||||
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{repr(item)},')
|
||||
|
||||
if type(items) == list:
|
||||
if not recurse:
|
||||
out = list()
|
||||
out.append('[')
|
||||
for item in items:
|
||||
rec_loop(item, None, out, level)
|
||||
if not recurse:
|
||||
out.append(']')
|
||||
elif type(items) == dict:
|
||||
if not recurse:
|
||||
out = list()
|
||||
out.append('{')
|
||||
for key in items:
|
||||
rec_loop(items[key], key, out, level)
|
||||
if not recurse:
|
||||
out.append('}')
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def paginate(text, maxlen=1990):
|
||||
paginator = Paginator(prefix='```py', max_size=maxlen+10)
|
||||
if type(text) == list:
|
||||
data = to_list_of_str(text)
|
||||
elif type(text) == dict:
|
||||
data = to_list_of_str(text)
|
||||
else:
|
||||
data = str(text).split('\n')
|
||||
for line in data:
|
||||
if len(line) > maxlen:
|
||||
n = maxlen
|
||||
for l in [line[i:i+n] for i in range(0, len(line), n)]:
|
||||
paginator.add_line(l)
|
||||
else:
|
||||
paginator.add_line(line)
|
||||
return paginator.pages
|
||||
|
||||
|
||||
async def run_command(args):
|
||||
# Create subprocess
|
||||
process = await asyncio.create_subprocess_shell(
|
||||
args,
|
||||
# stdout must a pipe to be accessible as process.stdout
|
||||
stdout=asyncio.subprocess.PIPE)
|
||||
# Wait for the subprocess to finish
|
||||
stdout, stderr = await process.communicate()
|
||||
# Return stdout
|
||||
return stdout.decode().strip()
|
||||
Loading…
x
Reference in New Issue
Block a user