-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
130 lines (98 loc) · 4.42 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import os
import asyncio
import discord
import docker
from discord.ext import commands, tasks
from dotenv import load_dotenv
load_dotenv() # take environment variables from .env
client = docker.from_env()
client.images.build(path=".", tag="shortlang_image", rm=True)
class MyBot(commands.Bot):
def __init__(self, **kwargs):
super().__init__(
command_prefix=commands.when_mentioned_or("-"),
case_insensitive=True,
intents=kwargs.pop("intents", discord.Intents.all()),
allowed_mentions=discord.AllowedMentions(
roles=False, users=False, everyone=False),
)
async def is_owner(self, user: discord.User):
return user.id == 655020762796654592
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
"""The event triggered when an error is raised while invoking a command."""
try:
await ctx.reply(str(error))
except:
print(error)
async def setup_hook(self) -> None:
self.presence.start()
@tasks.loop(hours=1)
async def presence(self):
await self.wait_until_ready()
await self.change_presence(activity=discord.Game(name="Use -help for usage!"))
intents = discord.Intents.default()
intents.message_content = True
bot = MyBot(intents=intents)
class CustomHelpCommand(commands.MinimalHelpCommand):
def get_command_signature(self, command):
return f'{command.qualified_name} {command.signature}'
async def send_bot_help(self, _mapping):
embed = discord.Embed(title='Commands', color=discord.Color.blue(),
description="For help with a specific command, type `-help <command>`")
for command in self.context.bot.commands:
if command.qualified_name == "jishaku":
continue
if not command.hidden:
embed.add_field(name=f'{self.get_command_signature(command)}',
value=f"```{command.help or 'No description'}```", inline=False)
await self.get_destination().send(embed=embed)
bot.help_command = CustomHelpCommand()
def run_container(code):
container = client.containers.run("shortlang_image", [
"sh", "-c", f"echo '{code}' | shortlang"], detach=True, stderr=True)
try:
result = container.wait(timeout=5)
except:
return "Error: The program took too long to execute."
if result['StatusCode'] != 0:
container.stop()
return container
@bot.event
async def on_ready():
await bot.load_extension("jishaku")
print(f'Logged in as {bot.user} (ID: {bot.user.id})')
print('------')
@bot.command()
async def run(ctx, *, code: str = None):
"""Runs the given ShortLang code"""
# Add a reaction to the message to indicate that the bot is processing the command
await ctx.message.add_reaction('⏳')
if ctx.message.attachments:
# If a file was sent, download it and read its content
file = await ctx.message.attachments[0].read()
code = file.decode()
else:
# If no file was sent, use the provided code
code = code.replace('```', '').replace("'", '"')
# Run the container in a separate thread to avoid blocking
loop = asyncio.get_event_loop()
container = await loop.run_in_executor(None, run_container, code)
if isinstance(container, str):
# If the container returned a string, it's an error message
embed = discord.Embed(color=discord.colour.parse_hex_number("FF0000"))
embed.add_field(name="Error Output", value="```" + container + "```", inline=False)
await ctx.message.remove_reaction('⏳', bot.user)
return await ctx.reply(embed=embed)
# Fetch the stdout and stderr
stdout = container.logs(stdout=True, stderr=False).decode()
stderr = container.logs(stdout=False, stderr=True).decode()
# Create the embed
embed = discord.Embed(color=discord.colour.parse_hex_number("8080FF"))
output = f"```{stdout[:1010]}```" if len(stdout) != 0 else "*No output.*"
embed.add_field(name="Program Output", value=output, inline=False)
if len(stderr) != 0:
embed.add_field(name="Error Output", value=f"```{stderr[:1010]}```", inline=False)
embed.color = discord.colour.parse_hex_number("FF0000")
await ctx.reply(embed=embed)
await ctx.message.remove_reaction('⏳', bot.user)
bot.run(os.getenv("DISCORD_TOKEN"))