Skip to content

Commit de3f7a4

Browse files
Merge pull request #16 from Terrain123456/main
ANSI Formatted Github Code-Blocks
2 parents d4923c0 + 610dd4d commit de3f7a4

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

modules/github.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
"""
2323
from __future__ import annotations
2424

25+
import asyncio
2526
import re
2627
from typing import TYPE_CHECKING
2728

29+
import aiohttp
2830
import discord
2931

3032
import core
@@ -35,6 +37,9 @@
3537
GITHUB_ISSUE_URL = "https://github.com/{}/issues/{}"
3638
LIB_ISSUE_REGEX = re.compile(r"(?P<lib>[a-z]+)?##(?P<number>[0-9]+)", flags=re.IGNORECASE)
3739

40+
GITHUB_BASE_URL = "https://github.com/"
41+
GITHUB_RAW_CONTENT_URL = "https://raw.githubusercontent.com/"
42+
3843
aliases = [
3944
(("wavelink", "wave", "wl"), "PythonistaGuild/Wavelink"),
4045
(("discordpy", "discord", "dpy"), "Rapptz/discord.py"),
@@ -46,6 +51,76 @@
4651
class GitHub(core.Cog):
4752
def __init__(self, bot: Bot) -> None:
4853
self.bot: Bot = bot
54+
self.code_highlight_emoji = "📃"
55+
self.highlight_timeout = 10
56+
57+
def _strip_content_path(self, url: str) -> str:
58+
file_path = url[len(GITHUB_BASE_URL):]
59+
return file_path
60+
61+
async def format_highlight_block(self, url: str, line_adjustment: int = 10):
62+
try:
63+
highlighted_line = int(url.split("#L")[1]) # seperate the #L{n} highlight
64+
except IndexError:
65+
return
66+
67+
file_path = self._strip_content_path(url)
68+
raw_url = GITHUB_RAW_CONTENT_URL + file_path.replace("blob/", "") # Convert it to a raw user content URL
69+
70+
code = ""
71+
async with self.bot.session.get(raw_url) as resp:
72+
if resp.status == 404:
73+
return
74+
75+
code += await resp.text()
76+
77+
code = code.splitlines()
78+
79+
code_block_dict = {"lines": {}}
80+
j = 0
81+
for i in code:
82+
# populate the dict
83+
code_block_dict["lines"][j] = i
84+
j += 1
85+
86+
code_block_dict["lines"][j] = "\n"
87+
88+
line_list = code_block_dict["lines"]
89+
90+
if highlighted_line - 1 not in line_list:
91+
return None
92+
93+
bound_adj = line_adjustment # adjustment for upper and lower bound display
94+
_minBoundary = (highlighted_line - 1 - bound_adj)
95+
_maxBoundary = (highlighted_line - 1 + bound_adj)
96+
97+
# loop through all the lines, and adjust the formatting
98+
msg = "```ansi\n"
99+
key = _minBoundary
100+
while key <= _maxBoundary:
101+
currLineNum = str(key + 1)
102+
# insert a space if there is no following char before the first character...
103+
if key + 1 == highlighted_line:
104+
highlighted_msg_format = "\u001b[0;37m\u001b[4;31m{} {}\u001b[0;0m\n".format(
105+
currLineNum, line_list[key]
106+
)
107+
108+
msg += highlighted_msg_format
109+
else:
110+
display_str = "{} {}\n" if line_list.get(
111+
key) is not None else "" # if we hit the end of the file, just write an empty string
112+
msg += display_str.format(currLineNum, line_list.get(key))
113+
key += 1
114+
115+
msg += "\n```"
116+
117+
github_dict = {
118+
"path": file_path,
119+
"min": _minBoundary if _minBoundary > 0 else highlighted_line, # Do not display negative numbers if <0
120+
"max": _maxBoundary,
121+
"msg": msg
122+
}
123+
return github_dict
49124

50125
@core.Cog.listener()
51126
async def on_message(self, message: discord.Message) -> None:
@@ -60,6 +135,31 @@ async def on_message(self, message: discord.Message) -> None:
60135

61136
await message.channel.send(GITHUB_ISSUE_URL.format(lib, issue))
62137

138+
code_segment = await self.format_highlight_block(message.content)
139+
140+
if code_segment is None:
141+
return
142+
143+
await message.add_reaction(self.code_highlight_emoji)
144+
145+
path = code_segment['path']
146+
_min = code_segment['min']
147+
_max = code_segment['max']
148+
code_fmt = code_segment['msg']
149+
150+
def check(reaction, user):
151+
return reaction.emoji == self.code_highlight_emoji and user != self.bot.user \
152+
and message.id == reaction.message.id
153+
154+
try:
155+
await self.bot.wait_for("reaction_add", check=check, timeout=self.highlight_timeout)
156+
await message.channel.send(
157+
content="Showing lines `{}` - `{}` in: `{}`...\n{}".format(_min, _max, path, code_fmt),
158+
suppress_embeds=True
159+
)
160+
except asyncio.TimeoutError:
161+
return
162+
63163

64164
async def setup(bot: Bot) -> None:
65165
await bot.add_cog(GitHub(bot))

0 commit comments

Comments
 (0)