From dbde5c34a71157707e82bc52b0c671d7dadc741a Mon Sep 17 00:00:00 2001 From: romangraef Date: Mon, 10 Sep 2018 20:51:36 +0200 Subject: Rextester api --- README.md | 8 ++---- compile_api.py | 70 ++++++++++++++++++++++++++--------------------- config.py | 6 ----- modules/execute.py | 79 +++++++++++++++++++++++++++--------------------------- 4 files changed, 80 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 4a2034d..c268404 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ EVALBOT ------ -Discord Code eval bot using the [Compilebot][compilebot] API. +Discord Code eval bot using the [Rextester][rextester] API. ### SETUP - Create a discord bot account at [the discord developers page][discord-devs]. **IMPORTANT** Create a bot user as well. - - Go to the [Compilebot][compilebot] website and subscribe to a plan. - clone the repository and create a [Virtual Environment][venv] - Install all the requirements via `pip install -r requirements.txt` - Create a `config.ini` in the following format: @@ -13,12 +12,9 @@ Discord Code eval bot using the [Compilebot][compilebot] API. [discord] token = YOURDISCORDTOKEN. DISCORD! TOKEN! NOT ID OR SECRET -[jdoodle] -id = yourcompilebotid -secret = yourcompilebotsecret ``` - Launch the bot via `python main.py`. If you want to run the bot permanently i recommend using `tmux` or `screen`. -[compilebot]: https://www.jdoodle.com/compiler-api/ [discord-devs]: https://discordapp.com/developers/applications/me [venv]: https://docs.python.org/3/library/venv.html +[rextester]: http://rextester.com/main diff --git a/compile_api.py b/compile_api.py index 82ac440..019df74 100644 --- a/compile_api.py +++ b/compile_api.py @@ -1,49 +1,57 @@ -import asyncio +import base64 +from io import BytesIO +from typing import Optional, List, Union import aiohttp +from discord import File -from config import jdoodle_id, jdoodle_secret - -EXECUTE_ENDPOINT = "https://api.jdoodle.com/v1/execute" +EXECUTE_ENDPOINT = "http://rextester.com/rundotnet/api" def get_parameters(**kwargs): - return dict( - clientId=jdoodle_id, - clientSecret=jdoodle_secret, - **kwargs, - ) + return kwargs + +class ExecuteResponse(object): -def post(url, data=None, json=None, **kwargs): - return asyncio.get_event_loop().run_in_executor(None, lambda *_: requests.post(url, data, json, **kwargs)) + def __init__(self, warnings: Optional[str], errors: Optional[str], output: str, stats, files): + self.output: Optional[str] = output + self.warnings: Optional[str] = warnings + self.errors: Optional[str] = errors + self.stats: str = stats + self.files: Optional[List[str]] = files + @property + def discord_files(self) -> List[File]: + if not self.files: + return [] -class ExecuteResponse(object): - output: str - cpu_time: float - memory: int - status_code: int + def convert_file(b64, i): + bytesio = BytesIO() + bytesio.write(base64.b64decode(b64)) + bytesio.seek(0) + return File(bytesio, filename=f'output{i}.png') - def __init__(self, output: str, cpu_time: float, memory: int, status_code: int): - self.output: str = output - self.cpu_time: float = cpu_time - self.memory: int = memory - self.status_code: int = status_code + return [convert_file(b64, i) for i, b64 in enumerate(self.files)] def parse_execute_response(response: dict) -> ExecuteResponse: - memory = response['memory'] - output = response['output'] - cpu_time = response['cpuTime'] - status_code = response['statusCode'] - return ExecuteResponse(output, cpu_time, memory, status_code) + warnings = response['Warnings'] + errors = response['Errors'] + output = response['Result'] + stats = response['Stats'] + files = response['Files'] + return ExecuteResponse(warnings, errors, output, stats, files) -async def execute(code: str, language: str, version: str) -> ExecuteResponse: +async def execute(code: str, language: Union[str, int]) -> ExecuteResponse: async with aiohttp.ClientSession() as session: - response = await session.post(EXECUTE_ENDPOINT, json=get_parameters( - script=code, - language=language, - versionIndex=version)) + print(code) + print(language) + response = await session.post(EXECUTE_ENDPOINT, data=get_parameters( + Program=code, + LanguageChoice=language, + Input="", + CompilerArgs="", + )) return parse_execute_response(await response.json()) diff --git a/config.py b/config.py index 6595e98..08b3193 100644 --- a/config.py +++ b/config.py @@ -6,9 +6,3 @@ config.read('config.ini') discord = config['discord'] token = discord['token'] - - -jdoodle = config['jdoodle'] - -jdoodle_secret = jdoodle['secret'] -jdoodle_id = jdoodle['id'] diff --git a/modules/execute.py b/modules/execute.py index ce45e12..bfef437 100644 --- a/modules/execute.py +++ b/modules/execute.py @@ -3,7 +3,7 @@ from collections import defaultdict from datetime import datetime, timedelta from typing import Pattern -from discord import Embed, Color, Message, Guild, TextChannel, Member +from discord import Embed, Message, Guild, TextChannel, Member from discord.ext.commands import Bot from compile_api import execute @@ -11,29 +11,29 @@ from compile_api import execute CODE_BLOCK_REGEX: Pattern = re.compile("```(?P.*)\n(?P[\\s\\S]*?)```") INPUT_BLOCK_REGEX: Pattern = re.compile("input[: \t\n]*```(?P.*)?\n(?P[\\s\\S]*?)```", re.IGNORECASE) -PYTHON_3 = ('python3', 2) -NODEJS = ('nodejs', 2) -C_LANG = ('c', 3) -CPP = ('cpp14', 2) -PHP = ('php', 2) -PYTHON_2 = ('python2', 1) -RUBY = ('ruby', 2) -GO_LANG = ('go', 2) -SCALA = ('scala', 2) -BASH = ('bash', 2) -CSHARP = ('csharp', 2) -HASKELL = ('haskell', 2) -BRAINFUCK = ('brainfuck', 0) -LUA = ('lua', 1) -DART = ('dart', 2) -KOTLIN = ('kotlin', 1) -JAVA = ('java', 0) +PYTHON_3 = 24 +NODEJS = 17 +C_LANG = 6 +CPP = 7 +PHP = 8 +PYTHON_2 = 5 +RUBY = 12 +GO_LANG = 20 +SCALA = 21 +BASH = 38 +CSHARP = 1 +HASKELL = 11 +BRAINFUCK = 44 +LUA = 14 +KOTLIN = 43 +JAVA = 4 +R_LANG = 31 languages = { + 'r': R_LANG, + 'rlang': R_LANG, 'kt': KOTLIN, 'kotlin': KOTLIN, - 'dart': DART, - 'dt': DART, 'lua': LUA, 'py': PYTHON_3, 'python': PYTHON_3, @@ -88,29 +88,28 @@ class ExecuteCog(object): embed=Embed( description=f"You are not allowed to eval code again. Check again in " f"{(timedelta(seconds=30)-delta).seconds}secs")) - if not author.guild_permissions.manage_messages: + if not author.guild_permissions.manage_messages and not author.id == 310702108997320705: self.last_messaged[author.id] = datetime.now() - language, version = languages[lang] - response = await execute(code, language, version) - if response.status_code == 429: - return await channel.send( - embed=Embed( - color=Color.blurple(), - description="The daily ratelimit for our API is reached. A great alternative is [Ideone](" - "https://ideone.com/) or [Repl.it](https://repl.it/)")) - if response.status_code == 401: - return await channel.send( - embed=Embed( - color=Color.red(), - description="Our API credentials are invalid. Please contact the bot owner")) - memory = response.memory + language = languages[lang] + print(language) + response = await execute(code, language) output = response.output - cpu_time = response.cpu_time + stats = response.stats + warnings = response.warnings + errors = response.errors + files = response.discord_files + em = Embed( + title="Executed your code", + description=f"```\n{output}```" + ).set_footer(text=stats) + if warnings: + em.add_field(name="Warnings", value=f'```\n{warnings}```') + if errors: + em.add_field(name="Errors", value=f'```\n{errors}```') await channel.send( - embed=Embed( - title="Executed your code", - description=f"```\n{output}```" - ).set_footer(text=f"Executed in {cpu_time}s. Memory: {memory}")) + embed=em, + files=files if len(files) > 0 else None + ) def setup(bot: Bot): -- cgit