diff options
author | 2018-03-08 02:00:24 +0100 | |
---|---|---|
committer | 2018-03-08 02:00:24 +0100 | |
commit | 50434dad7926ec3ee285791306af1c0015916d21 (patch) | |
tree | 98de2b0ffbe4de09fe77d46385f84dc6fded741c | |
parent | how do I keep forgetting the api. part (diff) |
Improving autocodeblocks (#23)
* adding better detection for misformatted python code, using the tags api instead of hardcoded hints and mentioning the user in the hint
* use a seperate string instead of msg.content
* Better comments and formatting
Own function for codeblock stripping
splitlines instead of split("\n"), because of readability
re.search instead of re.match, because re.match is too strict
if content.lower().startswith("python") instead of case sensitive
checking, because of readabilty
Reformatted hint
* More readability
Changed hint sentence
More descriptive variables
* Even more descriptive variable names
Fixed small cooldown bug
* forgot to save descriptive variable names
* i dont believe this
* typo at import
* reworked getting the tag, not sure if it works
* fixed old code
* oversaw one
* reworked the howto again
better stripping
* making the hint look better
* get_tag_data returns a dict ==> change .description to ['tag_content']
* if the codeblcok tag isnt found do nothing
* reformat of hint
* removed not needed f
* more changes to the hint
* lemon lied about fstrings
* order of arguments
* formatting
* logic error
* more foooormatting
and a debug note
* linter...
* still blank
-rw-r--r-- | bot/cogs/bot.py | 104 |
1 files changed, 66 insertions, 38 deletions
diff --git a/bot/cogs/bot.py b/bot/cogs/bot.py index 2663b79a8..a29aff9d5 100644 --- a/bot/cogs/bot.py +++ b/bot/cogs/bot.py @@ -1,5 +1,6 @@ # coding=utf-8 import ast +import re import time from discord import Embed, Message @@ -22,11 +23,11 @@ class Bot: self.bot = bot # Stores allowed channels plus unix timestamp from last call - self.previous_format_times = {HELP1_CHANNEL: 0, - HELP2_CHANNEL: 0, - HELP3_CHANNEL: 0, - PYTHON_CHANNEL: 0, - DEVTEST_CHANNEL: 0 + self.channel_cooldowns = {HELP1_CHANNEL: 0, + HELP2_CHANNEL: 0, + HELP3_CHANNEL: 0, + PYTHON_CHANNEL: 0, + DEVTEST_CHANNEL: 0 } # noqa. E124 @group(invoke_without_command=True, name="bot", hidden=True) @@ -73,40 +74,67 @@ class Bot: await ctx.invoke(self.info) + def codeblock_stripping(self, msg: str): + """ + Strip msg in order to find Python code. + + Tries to strip out Python code out of msg and returns the stripped block or + None if the block is a valid Python codeblock. + """ + if msg.count("\n") >= 3: + # Filtering valid Python codeblocks and exiting if a valid Python codeblock is found + if re.search("```(python|py)\n((?:.*\n*)+)```", msg, re.IGNORECASE): + return None + else: + # Stripping backticks from every line of the message. + content = "" + for line in msg.splitlines(): + content += line.strip("`") + "\n" + + content = content.strip() + + # Remove "Python" or "Py" from top of the message if exists + if content.lower().startswith("python"): + content = content[6:] + elif content.lower().startswith("py"): + content = content[2:] + + # Strip again to remove the whitespace(s) left before the code + # If the msg looked like "Python <code>" before removing Python + content = content.strip() + return content + async def on_message(self, msg: Message): - if msg.channel.id in self.previous_format_times: - if time.time()-self.previous_format_times[msg.channel.id] > 300 or msg.channel.id == DEVTEST_CHANNEL: - if msg.content.count("\n") >= 3: - try: - # Some users formatted multi-line code using `'sip(" - # This fixes that by treating them as nothing. - if "`" in msg.content: - msg.content = msg.content[:-1][1:] - tree = ast.parse(msg.content) - - # Attempts to parse the message into an AST node. - # Invalid Python code will raise a SyntaxError. - if not all(isinstance(node, ast.Expr) for node in tree.body): - - # Multiple lines of single words could be interpreted as expressions. - # This check is to avoid all nodes being parsed as expressions. - # (e.g. words over multiple lines) - howto = ("Please use syntax highlighted blocks, as it makes " - "your code more legible for other users.\n" - "\nTo do this, you should input your content like this:\n" - "\n\`\`\`python\n" - "print(\"Hello world!\")\n" - "\`\`\`\n" - "\nThis will result in the following:\n" - "```python\n" - "print(\"Hello world!\")" - "```" - ) # noqa. E124 - information = Embed(title="Code formatting", description=howto) - await msg.channel.send(embed=information) - self.previous_format_times[msg.channel.id] = time.time() - except SyntaxError: - pass + if msg.channel.id in self.channel_cooldowns: + on_cooldown = time.time() - self.channel_cooldowns[msg.channel.id] < 300 + if not on_cooldown or msg.channel.id == DEVTEST_CHANNEL: + try: + content = self.codeblock_stripping(msg.content) + if not content: + return + + # Attempts to parse the message into an AST node. + # Invalid Python code will raise a SyntaxError. + tree = ast.parse(content) + + # Multiple lines of single words could be interpreted as expressions. + # This check is to avoid all nodes being parsed as expressions. + # (e.g. words over multiple lines) + if not all(isinstance(node, ast.Expr) for node in tree.body): + codeblock_tag = await self.bot.get_cog("Tags").get_tag_data("codeblock") + if codeblock_tag == {}: + # todo: add logging + return + howto = (f"Hey {msg.author.mention}!\n\n" + "I noticed you were trying to paste code into this channel.\n\n" + f"{codeblock_tag['tag_content']}") + + howto_embed = Embed(description=howto) + await msg.channel.send(embed=howto_embed) + self.channel_cooldowns[msg.channel.id] = time.time() + except SyntaxError: + # todo: add logging + pass def setup(bot): |