From ef591224cdf093115a070d11c4b8f0d9260421d6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:09:07 -0400 Subject: [PATCH 01/71] feat(speedtest): added the cog --- speedtest/__init__.py | 5 ++++ speedtest/info.json | 12 ++++++++++ speedtest/speedtest.py | 53 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 speedtest/__init__.py create mode 100644 speedtest/info.json create mode 100644 speedtest/speedtest.py diff --git a/speedtest/__init__.py b/speedtest/__init__.py new file mode 100644 index 0000000..f91daf6 --- /dev/null +++ b/speedtest/__init__.py @@ -0,0 +1,5 @@ +from .speedtest import Speedtest + + +async def setup(bot): + await bot.add_cog(Speedtest(bot)) diff --git a/speedtest/info.json b/speedtest/info.json new file mode 100644 index 0000000..f331eac --- /dev/null +++ b/speedtest/info.json @@ -0,0 +1,12 @@ +{ + "author" : ["SeaswimmerTheFsh (seasw.)"], + "install_msg" : "Thank you for installing SeaUtils!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "name" : "SeaUtils", + "short" : "A collection of useful utilities.", + "description" : "A collection of useful utilities.", + "end_user_data_statement" : "This cog does not store end user data.", + "hidden": true, + "disabled": false, + "min_bot_version": "3.5.0", + "min_python_version": [3, 8, 0] +} diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py new file mode 100644 index 0000000..bdfacda --- /dev/null +++ b/speedtest/speedtest.py @@ -0,0 +1,53 @@ +# _____ _ +# / ____| (_) +# | (___ ___ __ _ _____ ___ _ __ ___ _ __ ___ ___ _ __ +# \___ \ / _ \/ _` / __\ \ /\ / / | '_ ` _ \| '_ ` _ \ / _ \ '__| +# ____) | __/ (_| \__ \\ V V /| | | | | | | | | | | | __/ | +# |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_| + +import json +import subprocess + +import discord +from redbot.core import commands +from redbot.core.bot import Red +from redbot.core.utils import chat_formatting as cf + + +class Speedtest(commands.Cog): + """A collection of random utilities.""" + + __author__ = ["SeaswimmerTheFsh"] + __version__ = "1.0.0" + + def __init__(self, bot: Red): + self.bot = bot + + def format_help_for_context(self, ctx: commands.Context) -> str: + pre_processed = super().format_help_for_context(ctx) or "" + n = "\n" if "\n\n" not in pre_processed else "" + text = [ + f"{pre_processed}{n}", + f"Cog Version: **{self.__version__}**", + f"Author: {cf.humanize_list(self.__author__)}" + ] + return "\n".join(text) + + @commands.command() + @commands.is_owner() + async def speedtest(self, ctx: commands.Context): + """Run a speedtest.""" + msg = await ctx.maybe_send_embed("Running speedtest...") + result = subprocess.run(["speedtest", "-f json", "--accept-license"], stdout=subprocess.PIPE) + r = json.loads(result.stdout.decode("utf-8")) + if await ctx.embed_requested(): + embed = discord.Embed(title="Speedtest Results", link=r["result"]["url"], color=await ctx.embed_color()) + embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") + embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['igm'])} ms \nUpload: {round(r['upload']['latency']['igm'])} ms") + embed.set_image(url=r["result"]["image"] + ".png") + await msg.edit(embed=embed) + else: + await msg.edit(content=f"**Speedtest Results**\n" + f"**Bandwidth**: {r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up\n" + f"**Ping**: Base: {round(r['ping']['latency'])} ms, Download: {round(r['download']['latency']['igm'])} ms, Upload: {round(r['upload']['latency']['igm'])} ms\n" + f"**Results**: {r['result']['url']}") From c3ab7593c77dd9e0887bf75b0f6ceb4ed8034813 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:19:48 -0400 Subject: [PATCH 02/71] fix(speedtest): bunch of fixes --- speedtest/speedtest.py | 43 ++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index bdfacda..96ad02d 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -5,6 +5,7 @@ # ____) | __/ (_| \__ \\ V V /| | | | | | | | | | | | __/ | # |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_| +import asyncio import json import subprocess @@ -33,21 +34,35 @@ class Speedtest(commands.Cog): ] return "\n".join(text) + async def run_speedtest(self) -> str | asyncio.Any: + process = await asyncio.create_subprocess_exec( + "speedtest", "-f json", "--accept-license", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + stdout, stderr = await process.communicate() + if process.returncode != 0: + return stderr.decode("utf-8") + return json.loads(stdout.decode("utf-8")) + @commands.command() @commands.is_owner() - async def speedtest(self, ctx: commands.Context): + async def speedtest(self, ctx: commands.Context) -> None: """Run a speedtest.""" msg = await ctx.maybe_send_embed("Running speedtest...") - result = subprocess.run(["speedtest", "-f json", "--accept-license"], stdout=subprocess.PIPE) - r = json.loads(result.stdout.decode("utf-8")) - if await ctx.embed_requested(): - embed = discord.Embed(title="Speedtest Results", link=r["result"]["url"], color=await ctx.embed_color()) - embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") - embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['igm'])} ms \nUpload: {round(r['upload']['latency']['igm'])} ms") - embed.set_image(url=r["result"]["image"] + ".png") - await msg.edit(embed=embed) - else: - await msg.edit(content=f"**Speedtest Results**\n" - f"**Bandwidth**: {r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up\n" - f"**Ping**: Base: {round(r['ping']['latency'])} ms, Download: {round(r['download']['latency']['igm'])} ms, Upload: {round(r['upload']['latency']['igm'])} ms\n" - f"**Results**: {r['result']['url']}") + async with ctx.typing(): + r = await self.run_speedtest() + if isinstance(r, str): + await msg.edit(content=f"An error occurred: {r}") + return + if await ctx.embed_requested(): + embed = discord.Embed(title="Speedtest Results", link=r["result"]["url"], color=await ctx.embed_color()) + embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") + embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['igm'])} ms \nUpload: {round(r['upload']['latency']['igm'])} ms") + embed.set_image(url=r["result"]["image"] + ".png") + await msg.edit(embed=embed) + else: + await msg.edit(content=f"**Speedtest Results**\n" + f"**Bandwidth**: {r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up\n" + f"**Ping**: Base: {round(r['ping']['latency'])} ms, Download: {round(r['download']['latency']['igm'])} ms, Upload: {round(r['upload']['latency']['igm'])} ms\n" + f"**Results**: {r['result']['url']}") From 14dfafea2a95b8c2fbdb6b3563b5f98c796d1452 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:20:33 -0400 Subject: [PATCH 03/71] fix(speedtest): fixed an AttributeError --- speedtest/speedtest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 96ad02d..4d16bc2 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -8,6 +8,7 @@ import asyncio import json import subprocess +from typing import Any import discord from redbot.core import commands @@ -34,7 +35,7 @@ class Speedtest(commands.Cog): ] return "\n".join(text) - async def run_speedtest(self) -> str | asyncio.Any: + async def run_speedtest(self) -> str | Any: process = await asyncio.create_subprocess_exec( "speedtest", "-f json", "--accept-license", stdout=subprocess.PIPE, From 4795df7dcc451e2e8dbdfbe146f4adac7b24ab2d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:21:33 -0400 Subject: [PATCH 04/71] fix(speedtest): added a error message for if speedtest is not installed --- speedtest/speedtest.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 4d16bc2..ea1daa4 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -36,11 +36,14 @@ class Speedtest(commands.Cog): return "\n".join(text) async def run_speedtest(self) -> str | Any: - process = await asyncio.create_subprocess_exec( - "speedtest", "-f json", "--accept-license", - stdout=subprocess.PIPE, - stderr=subprocess.PIPE - ) + try: + process = await asyncio.create_subprocess_exec( + "speedtest", "-f json", "--accept-license", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + except FileNotFoundError: + return "Speedtest CLI is not installed." stdout, stderr = await process.communicate() if process.returncode != 0: return stderr.decode("utf-8") From 8f55c6083a075691f7a91280a65962be4d71445e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:24:04 -0400 Subject: [PATCH 05/71] fix(speedtest): improve an error message --- speedtest/speedtest.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index ea1daa4..1d10019 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -56,16 +56,19 @@ class Speedtest(commands.Cog): msg = await ctx.maybe_send_embed("Running speedtest...") async with ctx.typing(): r = await self.run_speedtest() - if isinstance(r, str): - await msg.edit(content=f"An error occurred: {r}") - return if await ctx.embed_requested(): + if isinstance(r, str): + await msg.edit(embed=discord.Embed(description=f"An error occurred! {r}", color=await discord.Colour.red())) + return embed = discord.Embed(title="Speedtest Results", link=r["result"]["url"], color=await ctx.embed_color()) embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['igm'])} ms \nUpload: {round(r['upload']['latency']['igm'])} ms") embed.set_image(url=r["result"]["image"] + ".png") await msg.edit(embed=embed) else: + if isinstance(r, str): + await msg.edit(content=f"An error occurred! {r}") + return await msg.edit(content=f"**Speedtest Results**\n" f"**Bandwidth**: {r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up\n" f"**Ping**: Base: {round(r['ping']['latency'])} ms, Download: {round(r['download']['latency']['igm'])} ms, Upload: {round(r['upload']['latency']['igm'])} ms\n" From 7806aa29c596d1b6e72da1c2548233320cba6310 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:24:40 -0400 Subject: [PATCH 06/71] fix(speedtest): removed an await --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 1d10019..3e427f3 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -58,7 +58,7 @@ class Speedtest(commands.Cog): r = await self.run_speedtest() if await ctx.embed_requested(): if isinstance(r, str): - await msg.edit(embed=discord.Embed(description=f"An error occurred! {r}", color=await discord.Colour.red())) + await msg.edit(embed=discord.Embed(description=f"An error occurred! {r}", color=discord.Colour.red())) return embed = discord.Embed(title="Speedtest Results", link=r["result"]["url"], color=await ctx.embed_color()) embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") From b210fa8bb023db8737eaef57a95d8c0555ed45da Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:37:35 -0400 Subject: [PATCH 07/71] fix(speedtest): hopefully fixed an error --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 3e427f3..901b9bd 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -38,7 +38,7 @@ class Speedtest(commands.Cog): async def run_speedtest(self) -> str | Any: try: process = await asyncio.create_subprocess_exec( - "speedtest", "-f json", "--accept-license", + program=["speedtest", "-f", "json", "--accept-license"], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) From 30003cd7c8506e3a207cf584d3836618a03557f4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:38:02 -0400 Subject: [PATCH 08/71] fix(speedtest) whoops! --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 901b9bd..08615bd 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -38,7 +38,7 @@ class Speedtest(commands.Cog): async def run_speedtest(self) -> str | Any: try: process = await asyncio.create_subprocess_exec( - program=["speedtest", "-f", "json", "--accept-license"], + "speedtest", "-f", "json", "--accept-license", stdout=subprocess.PIPE, stderr=subprocess.PIPE ) From c2333f40efe6bc5675fa217a4a278523b5a2214b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:38:52 -0400 Subject: [PATCH 09/71] fix(speedtest): fixed an incorrectly named kwarg --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 08615bd..aa8acec 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -60,7 +60,7 @@ class Speedtest(commands.Cog): if isinstance(r, str): await msg.edit(embed=discord.Embed(description=f"An error occurred! {r}", color=discord.Colour.red())) return - embed = discord.Embed(title="Speedtest Results", link=r["result"]["url"], color=await ctx.embed_color()) + embed = discord.Embed(title="Speedtest Results", url=r["result"]["url"], color=await ctx.embed_color()) embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['igm'])} ms \nUpload: {round(r['upload']['latency']['igm'])} ms") embed.set_image(url=r["result"]["image"] + ".png") From eb41c1a72b4e973df343db5b812540d530c56573 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:40:02 -0400 Subject: [PATCH 10/71] fix(speedtest): fixed two keyerrors --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index aa8acec..165071a 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -62,7 +62,7 @@ class Speedtest(commands.Cog): return embed = discord.Embed(title="Speedtest Results", url=r["result"]["url"], color=await ctx.embed_color()) embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") - embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['igm'])} ms \nUpload: {round(r['upload']['latency']['igm'])} ms") + embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['iqm'])} ms \nUpload: {round(r['upload']['latency']['iqm'])} ms") embed.set_image(url=r["result"]["image"] + ".png") await msg.edit(embed=embed) else: From e88cba6cf4562ecd93efd4f729e9e25d118dbf08 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:40:46 -0400 Subject: [PATCH 11/71] fix(speedtest): fixed another keyerror --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 165071a..a4429de 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -63,7 +63,7 @@ class Speedtest(commands.Cog): embed = discord.Embed(title="Speedtest Results", url=r["result"]["url"], color=await ctx.embed_color()) embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['iqm'])} ms \nUpload: {round(r['upload']['latency']['iqm'])} ms") - embed.set_image(url=r["result"]["image"] + ".png") + embed.set_image(url=r["result"]["url"] + ".png") await msg.edit(embed=embed) else: if isinstance(r, str): From 45d0b3282653acc5185e4618f3809e72cbf7f219 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:55:05 -0400 Subject: [PATCH 12/71] feat(speedtest): convert to pydantic --- speedtest/info.json | 8 +++-- speedtest/models.py | 72 ++++++++++++++++++++++++++++++++++++++++++ speedtest/speedtest.py | 33 ++++++++++--------- 3 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 speedtest/models.py diff --git a/speedtest/info.json b/speedtest/info.json index f331eac..c36a53a 100644 --- a/speedtest/info.json +++ b/speedtest/info.json @@ -1,12 +1,14 @@ { "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing SeaUtils!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", - "name" : "SeaUtils", + "install_msg" : "Thank you for installing Speedtest!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "name" : "Speedtest", "short" : "A collection of useful utilities.", "description" : "A collection of useful utilities.", "end_user_data_statement" : "This cog does not store end user data.", "hidden": true, "disabled": false, "min_bot_version": "3.5.0", - "min_python_version": [3, 8, 0] + "min_python_version": [3, 10, 0], + "tags" : ["utility", "information"], + "requirements": ["pydantic"] } diff --git a/speedtest/models.py b/speedtest/models.py new file mode 100644 index 0000000..0a60699 --- /dev/null +++ b/speedtest/models.py @@ -0,0 +1,72 @@ +from datetime import datetime + +from pydantic import BaseModel + + +class Speedtest(BaseModel): + type: str + timestamp: datetime + ping: "Ping" + download: "Bandwidth" + upload: "Bandwidth" + isp: str + interface: "Interface" + server: "Server" + result: "Result" + + @classmethod + def from_json(cls, data: dict) -> "Speedtest": + return cls( + type=data["type"], + timestamp=datetime.fromisoformat(data["timestamp"]), + ping=Ping(**data["ping"]), + download=Bandwidth(**data["download"]), + upload=Bandwidth(**data["upload"]), + isp=data["isp"], + interface=Interface(**data["interface"]), + server=Server(**data["server"]), + result=Result(**data["result"]) + ) + +class Bandwidth(BaseModel): + bandwidth: float + bytes: int + elapsed: int + latency: "Latency" + +class Interface(BaseModel): + internalIp: str + name: str + macAddr: str + isVpn: bool + externalIp: str + +class Ping(BaseModel): + jitter: float + latency: float + low: float + high: float + +class Latency(BaseModel): + iqm: float + low: float + high: float + jitter: float + +class Server(BaseModel): + id: str + name: str + location: str + country: str + host: str + port: int + ip: str + +class Result: + id: str + url: str + persisted: bool + + @property + def image(self): + return self.url + ".png" diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index a4429de..9e522a6 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -8,13 +8,14 @@ import asyncio import json import subprocess -from typing import Any import discord from redbot.core import commands from redbot.core.bot import Red from redbot.core.utils import chat_formatting as cf +from .models import Speedtest as sp + class Speedtest(commands.Cog): """A collection of random utilities.""" @@ -35,7 +36,7 @@ class Speedtest(commands.Cog): ] return "\n".join(text) - async def run_speedtest(self) -> str | Any: + async def run_speedtest(self) -> str | sp: try: process = await asyncio.create_subprocess_exec( "speedtest", "-f", "json", "--accept-license", @@ -47,7 +48,7 @@ class Speedtest(commands.Cog): stdout, stderr = await process.communicate() if process.returncode != 0: return stderr.decode("utf-8") - return json.loads(stdout.decode("utf-8")) + return sp.from_json(json.loads(stdout.decode("utf-8"))) @commands.command() @commands.is_owner() @@ -55,21 +56,23 @@ class Speedtest(commands.Cog): """Run a speedtest.""" msg = await ctx.maybe_send_embed("Running speedtest...") async with ctx.typing(): - r = await self.run_speedtest() + speedtest = await self.run_speedtest() if await ctx.embed_requested(): - if isinstance(r, str): - await msg.edit(embed=discord.Embed(description=f"An error occurred! {r}", color=discord.Colour.red())) + if not isinstance(speedtest, sp): + await msg.edit(embed=discord.Embed(description=f"An error occurred! {speedtest}", color=discord.Colour.red())) return - embed = discord.Embed(title="Speedtest Results", url=r["result"]["url"], color=await ctx.embed_color()) - embed.add_field(name="Bandwidth", value=f"{r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up") - embed.add_field(name="Ping", value=f"Base: {round(r['ping']['latency'])} ms \nDownload: {round(r['download']['latency']['iqm'])} ms \nUpload: {round(r['upload']['latency']['iqm'])} ms") - embed.set_image(url=r["result"]["url"] + ".png") + embed = discord.Embed(title="Speedtest Results", url=speedtest.result.url, color=await ctx.embed_color()) + embed.add_field(name="Bandwidth", value=f"{speedtest.download.bandwidth / 1_000_000:.2f} Mbps down, {speedtest.download.bandwidth / 1_000_000:.2f} Mbps up") + embed.add_field(name="Ping", value=f"Base: {round(speedtest.ping.latency)} ms \nDownload: {round(speedtest.download.latency.iqm)} ms \nUpload: {round(speedtest.upload.latency.iqm)} ms") + embed.set_image(url=speedtest.result.image) await msg.edit(embed=embed) else: - if isinstance(r, str): - await msg.edit(content=f"An error occurred! {r}") + if not isinstance(speedtest, sp): + await msg.edit(content=f"An error occurred! {speedtest}") return await msg.edit(content=f"**Speedtest Results**\n" - f"**Bandwidth**: {r['download']['bandwidth'] / 1_000_000:.2f} Mbps down, {r['upload']['bandwidth'] / 1_000_000:.2f} Mbps up\n" - f"**Ping**: Base: {round(r['ping']['latency'])} ms, Download: {round(r['download']['latency']['igm'])} ms, Upload: {round(r['upload']['latency']['igm'])} ms\n" - f"**Results**: {r['result']['url']}") + f"**Bandwidth**: {speedtest.download.bandwidth / 1_000_000:.2f} Mbps down, {speedtest.download.bandwidth / 1_000_000:.2f} Mbps up\n" + f"**Ping**: Base: {round(speedtest.ping.latency)} ms\n" + f"Download: {round(speedtest.download.latency.iqm)} ms\n" + f"Upload: {round(speedtest.upload.latency.iqm)} ms\n" + f"**Image**: {speedtest.result.image}") From 418eeb983cdf96d62e3a12777ff080bb4ddd5df9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:56:40 -0400 Subject: [PATCH 13/71] fix(speedtest): fixed a pydantic validation error --- speedtest/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/models.py b/speedtest/models.py index 0a60699..cce2ebb 100644 --- a/speedtest/models.py +++ b/speedtest/models.py @@ -54,7 +54,7 @@ class Latency(BaseModel): jitter: float class Server(BaseModel): - id: str + id: int name: str location: str country: str From d557928feec047a167e6850f29769f806fc51cc1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 17:58:22 -0400 Subject: [PATCH 14/71] fix(speedtest): another pydantic fix --- speedtest/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/speedtest/models.py b/speedtest/models.py index cce2ebb..89b520e 100644 --- a/speedtest/models.py +++ b/speedtest/models.py @@ -62,11 +62,11 @@ class Server(BaseModel): port: int ip: str -class Result: +class Result(BaseModel): id: str url: str persisted: bool @property - def image(self): + def image(self) -> str: return self.url + ".png" From cba25d1f9439aff9996bb03e390722841eeb212d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 18:08:18 -0400 Subject: [PATCH 15/71] misc(speedtest): doing some testing --- speedtest/models.py | 16 ++++++++++------ speedtest/speedtest.py | 6 +++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/speedtest/models.py b/speedtest/models.py index 89b520e..cd1ca07 100644 --- a/speedtest/models.py +++ b/speedtest/models.py @@ -34,6 +34,16 @@ class Bandwidth(BaseModel): elapsed: int latency: "Latency" + @property + def mbps(self) -> float: + return self.bandwidth / 1_000_000 + +class Latency(BaseModel): + iqm: float + low: float + high: float + jitter: float + class Interface(BaseModel): internalIp: str name: str @@ -47,12 +57,6 @@ class Ping(BaseModel): low: float high: float -class Latency(BaseModel): - iqm: float - low: float - high: float - jitter: float - class Server(BaseModel): id: int name: str diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 9e522a6..0fe98f8 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -62,16 +62,16 @@ class Speedtest(commands.Cog): await msg.edit(embed=discord.Embed(description=f"An error occurred! {speedtest}", color=discord.Colour.red())) return embed = discord.Embed(title="Speedtest Results", url=speedtest.result.url, color=await ctx.embed_color()) - embed.add_field(name="Bandwidth", value=f"{speedtest.download.bandwidth / 1_000_000:.2f} Mbps down, {speedtest.download.bandwidth / 1_000_000:.2f} Mbps up") + embed.add_field(name="Bandwidth", value=f"{speedtest.download.mbps:,.2f} Mbps down, {speedtest.upload.mbps:,.2f} Mbps up") embed.add_field(name="Ping", value=f"Base: {round(speedtest.ping.latency)} ms \nDownload: {round(speedtest.download.latency.iqm)} ms \nUpload: {round(speedtest.upload.latency.iqm)} ms") embed.set_image(url=speedtest.result.image) await msg.edit(embed=embed) else: if not isinstance(speedtest, sp): - await msg.edit(content=f"An error occurred! {speedtest}") + await msg.edit(content=f"An error occurred! \n`{speedtest}`") return await msg.edit(content=f"**Speedtest Results**\n" - f"**Bandwidth**: {speedtest.download.bandwidth / 1_000_000:.2f} Mbps down, {speedtest.download.bandwidth / 1_000_000:.2f} Mbps up\n" + f"**Bandwidth**: {speedtest.download.mbps:,.2f} Mbps down, {speedtest.download.mbps:,.2f} Mbps up\n" f"**Ping**: Base: {round(speedtest.ping.latency)} ms\n" f"Download: {round(speedtest.download.latency.iqm)} ms\n" f"Upload: {round(speedtest.upload.latency.iqm)} ms\n" From 94b692a7057c9c5b66ed7f8e6e5b26a61b32d934 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 18:12:45 -0400 Subject: [PATCH 16/71] fix(speedtest): adding a debugging statement --- speedtest/speedtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 0fe98f8..0176c04 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -71,7 +71,7 @@ class Speedtest(commands.Cog): await msg.edit(content=f"An error occurred! \n`{speedtest}`") return await msg.edit(content=f"**Speedtest Results**\n" - f"**Bandwidth**: {speedtest.download.mbps:,.2f} Mbps down, {speedtest.download.mbps:,.2f} Mbps up\n" + f"**Bandwidth**: {speedtest.download.mbps:,.2f} Mbps down ({speedtest.download.bandwidth}), {speedtest.download.mbps:,.2f} Mbps up\n" f"**Ping**: Base: {round(speedtest.ping.latency)} ms\n" f"Download: {round(speedtest.download.latency.iqm)} ms\n" f"Upload: {round(speedtest.upload.latency.iqm)} ms\n" From 9103d64fbcc379d30d4a2b9a5ebfe368ca97a149 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 25 May 2024 18:17:00 -0400 Subject: [PATCH 17/71] fix(speedtest): just show the speedtest.net image --- speedtest/speedtest.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/speedtest/speedtest.py b/speedtest/speedtest.py index 0176c04..e727b0f 100644 --- a/speedtest/speedtest.py +++ b/speedtest/speedtest.py @@ -62,17 +62,10 @@ class Speedtest(commands.Cog): await msg.edit(embed=discord.Embed(description=f"An error occurred! {speedtest}", color=discord.Colour.red())) return embed = discord.Embed(title="Speedtest Results", url=speedtest.result.url, color=await ctx.embed_color()) - embed.add_field(name="Bandwidth", value=f"{speedtest.download.mbps:,.2f} Mbps down, {speedtest.upload.mbps:,.2f} Mbps up") - embed.add_field(name="Ping", value=f"Base: {round(speedtest.ping.latency)} ms \nDownload: {round(speedtest.download.latency.iqm)} ms \nUpload: {round(speedtest.upload.latency.iqm)} ms") embed.set_image(url=speedtest.result.image) await msg.edit(embed=embed) else: if not isinstance(speedtest, sp): await msg.edit(content=f"An error occurred! \n`{speedtest}`") return - await msg.edit(content=f"**Speedtest Results**\n" - f"**Bandwidth**: {speedtest.download.mbps:,.2f} Mbps down ({speedtest.download.bandwidth}), {speedtest.download.mbps:,.2f} Mbps up\n" - f"**Ping**: Base: {round(speedtest.ping.latency)} ms\n" - f"Download: {round(speedtest.download.latency.iqm)} ms\n" - f"Upload: {round(speedtest.upload.latency.iqm)} ms\n" - f"**Image**: {speedtest.result.image}") + await msg.edit(content=f"**[Result]({speedtest.result.url})**") From e9c062afa951bef99b46c371f77652a92252e7d4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 16:22:22 -0400 Subject: [PATCH 18/71] feat(seautils): added dig command --- seautils/seautils.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/seautils/seautils.py b/seautils/seautils.py index c575f6b..d2c42b3 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -5,6 +5,7 @@ # ____) | __/ (_| \__ \\ V V /| | | | | | | | | | | | __/ | # |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_| +import asyncio import inspect import operator from functools import partial, partialmethod @@ -82,3 +83,22 @@ class SeaUtils(commands.Cog): await ctx.send(embed=embed, reference=ctx.message.to_reference(fail_if_not_exists=False)) else: await ctx.send(content="Object not found!", reference=ctx.message.to_reference(fail_if_not_exists=False)) + + @commands.command(name='dig', aliases=['dnslookup', 'nslookup']) + @commands.is_owner() + async def dig(self, ctx: commands.Context, name: str, type: str | None = 'A', server: str | None = None, port: int = 53) -> None: + """Retrieve DNS information for a domain.""" + command_opts: list[str | int] = ['dig'] + if server: + command_opts.extend(['@', server]) + command_opts.extend([name, type]) + if port != 53: + command_opts.extend(['-p', port]) + command_opts.extend(['+yaml']) + + process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + stdout, stderr = await process.communicate() + if stderr: + await ctx.send(content=cf.box(text=stderr.decode())) + else: + await ctx.send(content=cf.box(text=stdout.decode(), lang='yaml')) From 8867cc627f8c107f99fbcbace6a0ebcbd2e7b2ba Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 16:33:15 -0400 Subject: [PATCH 19/71] feat(seautils): add an embed to the dig command --- seautils/seautils.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index d2c42b3..15362a7 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -8,9 +8,11 @@ import asyncio import inspect import operator +from datetime import datetime from functools import partial, partialmethod from typing import Any +import yaml from discord import Embed, app_commands from discord.utils import CachedSlotProperty, cached_property from redbot.core import commands @@ -99,6 +101,31 @@ class SeaUtils(commands.Cog): process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) stdout, stderr = await process.communicate() if stderr: - await ctx.send(content=cf.box(text=stderr.decode())) + await ctx.maybe_send_embed(content= "An error was encountered!\n" + cf.box(text=stderr.decode())) else: - await ctx.send(content=cf.box(text=stdout.decode(), lang='yaml')) + data = yaml.safe_load(stdout.decode()) + message_data = data[0]['message'] + response_data = message_data['response_message_data'] + timestamp = datetime.fromisoformat(message_data['response_time'].replace('Z', '+00:00')) + if ctx.embed_requested(): + embed = Embed( + title="DNS Query Result", + description=f"Query for {response_data['QUESTION_SECTION'][0]}", + color=await ctx.embed_color(), + timestamp=timestamp + ) + embed.add_field(name="Response Address", value=message_data['response_address'], inline=True) + embed.add_field(name="Response Port", value=message_data['response_port'], inline=True) + embed.add_field(name="Query Address", value=message_data['query_address'], inline=True) + embed.add_field(name="Query Port", value=message_data['query_port'], inline=True) + embed.add_field(name="Status", value=response_data['status'], inline=True) + embed.add_field(name="Flags", value=response_data['flags'], inline=True) + + question_section = "\n".join(response_data['QUESTION_SECTION']) + embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) + + answer_section = "\n".join(response_data['ANSWER_SECTION']) + embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) + await ctx.send(embed=embed) + else: + await ctx.send(content=cf.box(text=stdout, lang='yaml')) From 93f358cfad1e00fe2084a2a585c344fc46bda464 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 17:46:14 -0400 Subject: [PATCH 20/71] fix(seautils): fixed timestamp --- seautils/seautils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 15362a7..6eaafa7 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -8,7 +8,6 @@ import asyncio import inspect import operator -from datetime import datetime from functools import partial, partialmethod from typing import Any @@ -106,13 +105,12 @@ class SeaUtils(commands.Cog): data = yaml.safe_load(stdout.decode()) message_data = data[0]['message'] response_data = message_data['response_message_data'] - timestamp = datetime.fromisoformat(message_data['response_time'].replace('Z', '+00:00')) if ctx.embed_requested(): embed = Embed( title="DNS Query Result", description=f"Query for {response_data['QUESTION_SECTION'][0]}", color=await ctx.embed_color(), - timestamp=timestamp + timestamp=message_data['response_time'] ) embed.add_field(name="Response Address", value=message_data['response_address'], inline=True) embed.add_field(name="Response Port", value=message_data['response_port'], inline=True) From aa7e347a95a7993e5fee8f4797ae8d78eabc8412 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 17:48:00 -0400 Subject: [PATCH 21/71] fix(seautils): fix a keyerror --- seautils/seautils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 6eaafa7..198a748 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -108,7 +108,6 @@ class SeaUtils(commands.Cog): if ctx.embed_requested(): embed = Embed( title="DNS Query Result", - description=f"Query for {response_data['QUESTION_SECTION'][0]}", color=await ctx.embed_color(), timestamp=message_data['response_time'] ) @@ -122,8 +121,9 @@ class SeaUtils(commands.Cog): question_section = "\n".join(response_data['QUESTION_SECTION']) embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) - answer_section = "\n".join(response_data['ANSWER_SECTION']) - embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) + if 'ANSWER_SECTION' in response_data: + answer_section = "\n".join(response_data['ANSWER_SECTION']) + embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) await ctx.send(embed=embed) else: await ctx.send(content=cf.box(text=stdout, lang='yaml')) From 028cae9e99e2d60ccaa26d87bd1ad19f1f7fdf4b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 17:53:58 -0400 Subject: [PATCH 22/71] feat(seautils): improve error code handling --- seautils/seautils.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 198a748..c884d08 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -12,7 +12,7 @@ from functools import partial, partialmethod from typing import Any import yaml -from discord import Embed, app_commands +from discord import Color, Embed, app_commands from discord.utils import CachedSlotProperty, cached_property from redbot.core import commands from redbot.core.bot import Red @@ -103,8 +103,8 @@ class SeaUtils(commands.Cog): await ctx.maybe_send_embed(content= "An error was encountered!\n" + cf.box(text=stderr.decode())) else: data = yaml.safe_load(stdout.decode()) - message_data = data[0]['message'] - response_data = message_data['response_message_data'] + message_data: dict = data[0]['message'] + response_data: dict = message_data['response_message_data'] if ctx.embed_requested(): embed = Embed( title="DNS Query Result", @@ -118,12 +118,23 @@ class SeaUtils(commands.Cog): embed.add_field(name="Status", value=response_data['status'], inline=True) embed.add_field(name="Flags", value=response_data['flags'], inline=True) + match response_data.get('status'): + case 'FORMERR', 'SERVFAIL', 'NXDOMAIN', 'NOTIMP', 'REFUSED': + embed.colour = Color.red() + embed.description = "Dig query did not return `NOERROR` status." + case _: + embed.colour = await ctx.embed_color() + question_section = "\n".join(response_data['QUESTION_SECTION']) embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) if 'ANSWER_SECTION' in response_data: answer_section = "\n".join(response_data['ANSWER_SECTION']) embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) + + if 'AUTHORITY_SECTION' in response_data: + authority_section = "\n".join(response_data['AUTHORITY_SECTION']) + embed.add_field(name="Authority Section", value=f"```{authority_section}```", inline=False) await ctx.send(embed=embed) else: await ctx.send(content=cf.box(text=stdout, lang='yaml')) From 8b68cb7530ab59d494f62952efb38589b762dca7 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 17:54:46 -0400 Subject: [PATCH 23/71] fix(seautils): don't use match and case --- seautils/seautils.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index c884d08..cf29811 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -118,12 +118,9 @@ class SeaUtils(commands.Cog): embed.add_field(name="Status", value=response_data['status'], inline=True) embed.add_field(name="Flags", value=response_data['flags'], inline=True) - match response_data.get('status'): - case 'FORMERR', 'SERVFAIL', 'NXDOMAIN', 'NOTIMP', 'REFUSED': - embed.colour = Color.red() - embed.description = "Dig query did not return `NOERROR` status." - case _: - embed.colour = await ctx.embed_color() + if response_data.get('status') != 'NOERROR': + embed.colour = Color.red() + embed.description = "Dig query did not return `NOERROR` status." question_section = "\n".join(response_data['QUESTION_SECTION']) embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) From 7a2ee0a655c005a89cbde8b14903469e4e9585dc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 17:57:10 -0400 Subject: [PATCH 24/71] misc(seautils): added an error symbol to the failed dns query result message --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index cf29811..ad22a84 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -120,7 +120,7 @@ class SeaUtils(commands.Cog): if response_data.get('status') != 'NOERROR': embed.colour = Color.red() - embed.description = "Dig query did not return `NOERROR` status." + embed.description = cf.error("Dig query did not return `NOERROR` status.") question_section = "\n".join(response_data['QUESTION_SECTION']) embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) From d44424224584b5cfba84869dd3481b1aaafca8ec Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:01:35 -0400 Subject: [PATCH 25/71] fix(seautils): catch the error that is raised if dig is not installed on the system --- seautils/seautils.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index ad22a84..e68f3f3 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -8,6 +8,7 @@ import asyncio import inspect import operator +from asyncio.subprocess import Process from functools import partial, partialmethod from typing import Any @@ -97,8 +98,13 @@ class SeaUtils(commands.Cog): command_opts.extend(['-p', port]) command_opts.extend(['+yaml']) - process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) - stdout, stderr = await process.communicate() + try: + process: Process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + stdout, stderr = await process.communicate() + except (FileNotFoundError): + await ctx.maybe_send_embed(content="The `dig` command is not installed on this system.") + return + if stderr: await ctx.maybe_send_embed(content= "An error was encountered!\n" + cf.box(text=stderr.decode())) else: From 091f4fe36d2171b7ac29f7ce565977f78e177f5c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:02:17 -0400 Subject: [PATCH 26/71] fix(seautils): fixed maybe_send_message --- seautils/seautils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index e68f3f3..3a15c05 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -102,11 +102,11 @@ class SeaUtils(commands.Cog): process: Process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) stdout, stderr = await process.communicate() except (FileNotFoundError): - await ctx.maybe_send_embed(content="The `dig` command is not installed on this system.") + await ctx.maybe_send_embed(message="The `dig` command is not installed on this system.") return if stderr: - await ctx.maybe_send_embed(content= "An error was encountered!\n" + cf.box(text=stderr.decode())) + await ctx.maybe_send_embed(message="An error was encountered!\n" + cf.box(text=stderr.decode())) else: data = yaml.safe_load(stdout.decode()) message_data: dict = data[0]['message'] From 25fdf7b402e35712b64fb86a7cc21d84a7149342 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:31:38 -0400 Subject: [PATCH 27/71] feat(seautils): default to nslookup if dig is not present --- seautils/seautils.py | 94 ++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 3a15c05..8ef8e1f 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -101,43 +101,59 @@ class SeaUtils(commands.Cog): try: process: Process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) stdout, stderr = await process.communicate() - except (FileNotFoundError): - await ctx.maybe_send_embed(message="The `dig` command is not installed on this system.") - return - - if stderr: - await ctx.maybe_send_embed(message="An error was encountered!\n" + cf.box(text=stderr.decode())) - else: - data = yaml.safe_load(stdout.decode()) - message_data: dict = data[0]['message'] - response_data: dict = message_data['response_message_data'] - if ctx.embed_requested(): - embed = Embed( - title="DNS Query Result", - color=await ctx.embed_color(), - timestamp=message_data['response_time'] - ) - embed.add_field(name="Response Address", value=message_data['response_address'], inline=True) - embed.add_field(name="Response Port", value=message_data['response_port'], inline=True) - embed.add_field(name="Query Address", value=message_data['query_address'], inline=True) - embed.add_field(name="Query Port", value=message_data['query_port'], inline=True) - embed.add_field(name="Status", value=response_data['status'], inline=True) - embed.add_field(name="Flags", value=response_data['flags'], inline=True) - - if response_data.get('status') != 'NOERROR': - embed.colour = Color.red() - embed.description = cf.error("Dig query did not return `NOERROR` status.") - - question_section = "\n".join(response_data['QUESTION_SECTION']) - embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) - - if 'ANSWER_SECTION' in response_data: - answer_section = "\n".join(response_data['ANSWER_SECTION']) - embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) - - if 'AUTHORITY_SECTION' in response_data: - authority_section = "\n".join(response_data['AUTHORITY_SECTION']) - embed.add_field(name="Authority Section", value=f"```{authority_section}```", inline=False) - await ctx.send(embed=embed) + if stderr: + await ctx.maybe_send_embed(message="An error was encountered!\n" + cf.box(text=stderr.decode())) else: - await ctx.send(content=cf.box(text=stdout, lang='yaml')) + data = yaml.safe_load(stdout.decode()) + message_data: dict = data[0]['message'] + response_data: dict = message_data['response_message_data'] + if ctx.embed_requested(): + embed = Embed( + title="DNS Query Result", + color=await ctx.embed_color(), + timestamp=message_data['response_time'] + ) + embed.add_field(name="Response Address", value=message_data['response_address'], inline=True) + embed.add_field(name="Response Port", value=message_data['response_port'], inline=True) + embed.add_field(name="Query Address", value=message_data['query_address'], inline=True) + embed.add_field(name="Query Port", value=message_data['query_port'], inline=True) + embed.add_field(name="Status", value=response_data['status'], inline=True) + embed.add_field(name="Flags", value=response_data['flags'], inline=True) + + if response_data.get('status') != 'NOERROR': + embed.colour = Color.red() + embed.description = cf.error("Dig query did not return `NOERROR` status.") + + question_section = "\n".join(response_data['QUESTION_SECTION']) + embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) + + if 'ANSWER_SECTION' in response_data: + answer_section = "\n".join(response_data['ANSWER_SECTION']) + embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) + + if 'AUTHORITY_SECTION' in response_data: + authority_section = "\n".join(response_data['AUTHORITY_SECTION']) + embed.add_field(name="Authority Section", value=f"```{authority_section}```", inline=False) + await ctx.send(embed=embed) + else: + await ctx.send(content=cf.box(text=stdout, lang='yaml')) + except (FileNotFoundError): + try: + ns_process = await asyncio.create_subprocess_exec('nslookup', name, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + ns_stdout, ns_stderr = await ns_process.communicate() + if ns_stderr: + await ctx.maybe_send_embed(message="An error was encountered!\n" + cf.box(text=ns_stderr.decode())) + else: + warning = cf.warning("`dig` is not installed! Defaulting to `nslookup`.\nThis command provides more information when `dig` is installed on the system.\n") + if await ctx.embed_requested(): + embed = Embed( + title="DNS Query Result", + color=await ctx.embed_color(), + timestamp=ctx.message.created_at + ) + embed.description = warning + cf.box(text=ns_stdout.decode()) + await ctx.send(embed=embed) + else: + await ctx.send(content= warning + cf.box(text=ns_stdout.decode())) + except (FileNotFoundError): + await ctx.maybe_send_embed(message=cf.error("Neither `dig` nor `nslookup` are installed on the system. Unable to resolve DNS query.")) From 7d51814a288b21a059a9ac8c98136887c161eb5f Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:35:17 -0400 Subject: [PATCH 28/71] misc(seautils): purposefully breaking dig so i can test nslookup fallback --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 8ef8e1f..005a0b1 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -90,7 +90,7 @@ class SeaUtils(commands.Cog): @commands.is_owner() async def dig(self, ctx: commands.Context, name: str, type: str | None = 'A', server: str | None = None, port: int = 53) -> None: """Retrieve DNS information for a domain.""" - command_opts: list[str | int] = ['dig'] + command_opts: list[str | int] = ['digsss'] if server: command_opts.extend(['@', server]) command_opts.extend([name, type]) From 5ffc42480abdb4dfaf7efc9e3e12a3ec33a419dd Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:40:43 -0400 Subject: [PATCH 29/71] fix(seautils): revert breaking dig --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 005a0b1..8ef8e1f 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -90,7 +90,7 @@ class SeaUtils(commands.Cog): @commands.is_owner() async def dig(self, ctx: commands.Context, name: str, type: str | None = 'A', server: str | None = None, port: int = 53) -> None: """Retrieve DNS information for a domain.""" - command_opts: list[str | int] = ['digsss'] + command_opts: list[str | int] = ['dig'] if server: command_opts.extend(['@', server]) command_opts.extend([name, type]) From 29bb64b35c194f08f548057e39df023e5ef199c8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:42:42 -0400 Subject: [PATCH 30/71] fix(seautils): query ANY instead of A records --- seautils/seautils.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 8ef8e1f..c7e732f 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -88,15 +88,12 @@ class SeaUtils(commands.Cog): @commands.command(name='dig', aliases=['dnslookup', 'nslookup']) @commands.is_owner() - async def dig(self, ctx: commands.Context, name: str, type: str | None = 'A', server: str | None = None, port: int = 53) -> None: + async def dig(self, ctx: commands.Context, name: str, type: str | None = 'ANY', server: str | None = None, port: int = 53) -> None: """Retrieve DNS information for a domain.""" command_opts: list[str | int] = ['dig'] if server: command_opts.extend(['@', server]) - command_opts.extend([name, type]) - if port != 53: - command_opts.extend(['-p', port]) - command_opts.extend(['+yaml']) + command_opts.extend([name, type, '-p', port, '+yaml']) try: process: Process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) From 54491cb9c9d19c492718c7c95dccb42d69de8d49 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:44:01 -0400 Subject: [PATCH 31/71] fix(seautils): convert port number to a string --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index c7e732f..85df38e 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -93,7 +93,7 @@ class SeaUtils(commands.Cog): command_opts: list[str | int] = ['dig'] if server: command_opts.extend(['@', server]) - command_opts.extend([name, type, '-p', port, '+yaml']) + command_opts.extend([name, type, '-p', str(port), '+yaml']) try: process: Process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) From b27a3ee7788fb89ea571a73aecf2380189303d81 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:46:32 -0400 Subject: [PATCH 32/71] fix(seautils): fall back to the embed description if answer_section is too long --- seautils/seautils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 85df38e..ce9c64e 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -126,7 +126,10 @@ class SeaUtils(commands.Cog): if 'ANSWER_SECTION' in response_data: answer_section = "\n".join(response_data['ANSWER_SECTION']) - embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) + if len(answer_section) > 1024: + embed.description = answer_section + else: + embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) if 'AUTHORITY_SECTION' in response_data: authority_section = "\n".join(response_data['AUTHORITY_SECTION']) From fb468ee63e19e8f1dc7b8050a46eb05705ff2e0b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 18:55:09 -0400 Subject: [PATCH 33/71] fix(seautils): retrieve A, AAAA, and CNAME records by default (& docstring changes) --- seautils/seautils.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index ce9c64e..1feb77a 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -88,12 +88,19 @@ class SeaUtils(commands.Cog): @commands.command(name='dig', aliases=['dnslookup', 'nslookup']) @commands.is_owner() - async def dig(self, ctx: commands.Context, name: str, type: str | None = 'ANY', server: str | None = None, port: int = 53) -> None: - """Retrieve DNS information for a domain.""" + async def dig(self, ctx: commands.Context, name: str, type: str | None = None, server: str | None = None, port: int = 53) -> None: + """Retrieve DNS information for a domain. + + Uses `dig` to perform a DNS query. Will fall back to `nslookup` if `dig` is not installed on the system. + `nslookup` does not provide as much information as `dig`, so only the `name` parameter will be used if `nslookup` is used. + Will return the A, AAAA, and CNAME records for a domain by default. You can specify a different record type with the `type` parameter.""" command_opts: list[str | int] = ['dig'] + query_types = [type] if type else ['A', 'AAAA', 'CNAME'] if server: command_opts.extend(['@', server]) - command_opts.extend([name, type, '-p', str(port), '+yaml']) + for query_type in query_types: + command_opts.extend([name, query_type]) + command_opts.extend(['-p', str(port), '+yaml']) try: process: Process = await asyncio.create_subprocess_exec(*command_opts, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) From 8608e6a34e3aa7517ef713ab9a53b690019a9d56 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 19:06:11 -0400 Subject: [PATCH 34/71] fix(seautils): fixed only the first A response being used --- seautils/seautils.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 1feb77a..2d44336 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -128,19 +128,33 @@ class SeaUtils(commands.Cog): embed.colour = Color.red() embed.description = cf.error("Dig query did not return `NOERROR` status.") - question_section = "\n".join(response_data['QUESTION_SECTION']) - embed.add_field(name="Question Section", value=f"```{question_section}```", inline=False) + questions = [] + answers = [] + authorities = [] + for m in data: + response = m['message']['response_message_data'] + if 'QUESTION_SECTION' in response: + for question in response['QUESTION_SECTION']: + questions.append(question) + if 'ANSWER_SECTION' in response: + for answer in response['ANSWER_SECTION']: + answers.append(answer) + if 'AUTHORITY_SECTION' in response: + for authority in response['AUTHORITY_SECTION']: + authorities.append(authority) - if 'ANSWER_SECTION' in response_data: - answer_section = "\n".join(response_data['ANSWER_SECTION']) - if len(answer_section) > 1024: - embed.description = answer_section - else: - embed.add_field(name="Answer Section", value=f"```{answer_section}```", inline=False) + question_section = "\n".join(questions) + embed.add_field(name="Question Section", value=f"{cf.box(question_section)}", inline=False) - if 'AUTHORITY_SECTION' in response_data: - authority_section = "\n".join(response_data['AUTHORITY_SECTION']) - embed.add_field(name="Authority Section", value=f"```{authority_section}```", inline=False) + answer_section = "\n".join(answers) + if len(answer_section) > 1024: + embed.description = cf.warning("Answer section is too long to fit within embed field, falling back to description.") + cf.box(answer_section) + else: + embed.add_field(name="Answer Section", value=f"{cf.box(answer_section)}", inline=False) + + if authorities: + authority_section = "\n".join(authorities) + embed.add_field(name="Authority Section", value=f"{cf.box(authority_section)}", inline=False) await ctx.send(embed=embed) else: await ctx.send(content=cf.box(text=stdout, lang='yaml')) From cb6ddabb4dfe506d959386d27762131cfbf23456 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 19:10:15 -0400 Subject: [PATCH 35/71] fix(seautils): prevent duplicates in dig --- seautils/seautils.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 2d44336..dedb4e3 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -135,13 +135,18 @@ class SeaUtils(commands.Cog): response = m['message']['response_message_data'] if 'QUESTION_SECTION' in response: for question in response['QUESTION_SECTION']: - questions.append(question) + if question not in questions: + questions.append(question) + if 'ANSWER_SECTION' in response: for answer in response['ANSWER_SECTION']: - answers.append(answer) + if answer not in answers: + answers.append(answer) + if 'AUTHORITY_SECTION' in response: for authority in response['AUTHORITY_SECTION']: - authorities.append(authority) + if authority not in authorities: + authorities.append(authority) question_section = "\n".join(questions) embed.add_field(name="Question Section", value=f"{cf.box(question_section)}", inline=False) From 7f46d6accc65d4597d0324c7cb86f358d3a38f7b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 19:25:01 -0400 Subject: [PATCH 36/71] fix(seautils): fixed empty answer section --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index dedb4e3..69b80d0 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -157,7 +157,7 @@ class SeaUtils(commands.Cog): else: embed.add_field(name="Answer Section", value=f"{cf.box(answer_section)}", inline=False) - if authorities: + if not len(authorities) == 0: authority_section = "\n".join(authorities) embed.add_field(name="Authority Section", value=f"{cf.box(authority_section)}", inline=False) await ctx.send(embed=embed) From 50094b85fc7b322e35ac418fb277065cca1fe8f9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 19:26:07 -0400 Subject: [PATCH 37/71] fix(seautils): fixed the wrong thing lmao --- seautils/seautils.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 69b80d0..8b87a70 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -148,16 +148,18 @@ class SeaUtils(commands.Cog): if authority not in authorities: authorities.append(authority) - question_section = "\n".join(questions) - embed.add_field(name="Question Section", value=f"{cf.box(question_section)}", inline=False) + if questions: + question_section = "\n".join(questions) + embed.add_field(name="Question Section", value=f"{cf.box(question_section)}", inline=False) - answer_section = "\n".join(answers) - if len(answer_section) > 1024: - embed.description = cf.warning("Answer section is too long to fit within embed field, falling back to description.") + cf.box(answer_section) - else: - embed.add_field(name="Answer Section", value=f"{cf.box(answer_section)}", inline=False) + if answers: + answer_section = "\n".join(answers) + if len(answer_section) > 1024: + embed.description = cf.warning("Answer section is too long to fit within embed field, falling back to description.") + cf.box(answer_section) + else: + embed.add_field(name="Answer Section", value=f"{cf.box(answer_section)}", inline=False) - if not len(authorities) == 0: + if authorities: authority_section = "\n".join(authorities) embed.add_field(name="Authority Section", value=f"{cf.box(authority_section)}", inline=False) await ctx.send(embed=embed) From 2886d5e80d5b8bf7aec20220461a13436eeac3a6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 19:29:26 -0400 Subject: [PATCH 38/71] feat(seautils): use prolog syntax highlighting for dig results --- seautils/seautils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 8b87a70..da87b3a 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -150,18 +150,18 @@ class SeaUtils(commands.Cog): if questions: question_section = "\n".join(questions) - embed.add_field(name="Question Section", value=f"{cf.box(question_section)}", inline=False) + embed.add_field(name="Question Section", value=f"{cf.box(text=question_section, lang='prolog')}", inline=False) if answers: answer_section = "\n".join(answers) if len(answer_section) > 1024: embed.description = cf.warning("Answer section is too long to fit within embed field, falling back to description.") + cf.box(answer_section) else: - embed.add_field(name="Answer Section", value=f"{cf.box(answer_section)}", inline=False) + embed.add_field(name="Answer Section", value=f"{cf.box(text=answer_section, lang='prolog')}", inline=False) if authorities: authority_section = "\n".join(authorities) - embed.add_field(name="Authority Section", value=f"{cf.box(authority_section)}", inline=False) + embed.add_field(name="Authority Section", value=f"{cf.box(text=authority_section, lang='prolog')}", inline=False) await ctx.send(embed=embed) else: await ctx.send(content=cf.box(text=stdout, lang='yaml')) From a641cae640b31ada70a8248a28d2d9c00e229337 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 20:20:21 -0400 Subject: [PATCH 39/71] feat(seautils): add `[p]rfc` command --- poetry.lock | 34 +++++++++++++++++++++++++++++++++- pyproject.toml | 1 + seautils/info.json | 3 ++- seautils/seautils.py | 31 +++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 50be601..d30b1f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -228,6 +228,27 @@ files = [ [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + [[package]] name = "brotli" version = "1.1.0" @@ -2111,6 +2132,17 @@ files = [ {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, ] +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + [[package]] name = "tinycss2" version = "1.2.1" @@ -2451,4 +2483,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "0ac382e0399d9c23c5f89a0ffeb3aae056dc8b28e864b22f815c0e3eb34175bd" +content-hash = "55119c37c690ab197058ad091cb31bdf7c1c51ae62947e0026f4cddb423093d3" diff --git a/pyproject.toml b/pyproject.toml index 245364d..a2afb43 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ websockets = "^12.0" pillow = "^10.3.0" numpy = "^1.26.4" colorthief = "^0.2.1" +beautifulsoup4 = "^4.12.3" [tool.poetry.group.dev] optional = true diff --git a/seautils/info.json b/seautils/info.json index f331eac..8e93f9d 100644 --- a/seautils/info.json +++ b/seautils/info.json @@ -8,5 +8,6 @@ "hidden": true, "disabled": false, "min_bot_version": "3.5.0", - "min_python_version": [3, 8, 0] + "min_python_version": [3, 8, 0], + "requirements": ["beautifulsoup4"] } diff --git a/seautils/seautils.py b/seautils/seautils.py index da87b3a..389ea71 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -12,7 +12,9 @@ from asyncio.subprocess import Process from functools import partial, partialmethod from typing import Any +import aiohttp import yaml +from bs4 import BeautifulSoup from discord import Color, Embed, app_commands from discord.utils import CachedSlotProperty, cached_property from redbot.core import commands @@ -185,3 +187,32 @@ class SeaUtils(commands.Cog): await ctx.send(content= warning + cf.box(text=ns_stdout.decode())) except (FileNotFoundError): await ctx.maybe_send_embed(message=cf.error("Neither `dig` nor `nslookup` are installed on the system. Unable to resolve DNS query.")) + + async def get_results(self, ctx: commands.Context, soup: BeautifulSoup) -> list: + pre_tags = soup.find_all('pre') + content = [] + for pre_tag in pre_tags: + if await ctx.embed_requested(): + embed = Embed( + title="RFC Document", + description=pre_tag.text, + color=await ctx.embed_color() + ) + content.append(embed) + else: + content.append(pre_tag.text) + return content + + @commands.command() + async def rfc(self, ctx: commands.Context, number: int) -> None: + """Retrieve the text of an RFC document.""" + url = f"https://www.rfc-editor.org/rfc/rfc{number}.html" + async with aiohttp.ClientSession() as session: + async with session.get(url=url) as response: + if response.status == 200: + html = await response.text() + soup = BeautifulSoup(html, 'html.parser') + content = await self.get_results(ctx, soup) + await SimpleMenu(pages=content, disable_after_timeout=True, timeout=300).start(ctx) + else: + await ctx.maybe_send_embed(content=cf.error(f"An error occurred while fetching RFC {number}. Status code: {response.status}.")) From 28246121a6ae55aa1000fc5354d8fd80b143b0aa Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 20:29:39 -0400 Subject: [PATCH 40/71] feat(seautils): use markdownify to convert rfc html documents to markdown --- poetry.lock | 17 ++++++++++++++++- pyproject.toml | 1 + seautils/info.json | 2 +- seautils/seautils.py | 32 ++++++++++++++++---------------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/poetry.lock b/poetry.lock index d30b1f7..017d640 100644 --- a/poetry.lock +++ b/poetry.lock @@ -911,6 +911,21 @@ profiling = ["gprof2dot"] rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] +[[package]] +name = "markdownify" +version = "0.12.1" +description = "Convert HTML to markdown." +optional = false +python-versions = "*" +files = [ + {file = "markdownify-0.12.1-py3-none-any.whl", hash = "sha256:a3805abd8166dbb7b27783c5599d91f54f10d79894b2621404d85b333c7ce561"}, + {file = "markdownify-0.12.1.tar.gz", hash = "sha256:1fb08c618b30e0ee7a31a39b998f44a18fb28ab254f55f4af06b6d35a2179e27"}, +] + +[package.dependencies] +beautifulsoup4 = ">=4.9,<5" +six = ">=1.15,<2" + [[package]] name = "markupsafe" version = "2.1.5" @@ -2483,4 +2498,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "55119c37c690ab197058ad091cb31bdf7c1c51ae62947e0026f4cddb423093d3" +content-hash = "229d7fd39618cf708f3cd5409dde2e6e25b822e4f936e14b3ade9800bf00daab" diff --git a/pyproject.toml b/pyproject.toml index a2afb43..872ccdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ pillow = "^10.3.0" numpy = "^1.26.4" colorthief = "^0.2.1" beautifulsoup4 = "^4.12.3" +markdownify = "^0.12.1" [tool.poetry.group.dev] optional = true diff --git a/seautils/info.json b/seautils/info.json index 8e93f9d..7356137 100644 --- a/seautils/info.json +++ b/seautils/info.json @@ -9,5 +9,5 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 8, 0], - "requirements": ["beautifulsoup4"] + "requirements": ["beautifulsoup4", "markdownify"] } diff --git a/seautils/seautils.py b/seautils/seautils.py index 389ea71..a32d02c 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -17,6 +17,7 @@ import yaml from bs4 import BeautifulSoup from discord import Color, Embed, app_commands from discord.utils import CachedSlotProperty, cached_property +from markdownify import MarkdownConverter from redbot.core import commands from redbot.core.bot import Red from redbot.core.dev_commands import cleanup_code @@ -24,6 +25,9 @@ from redbot.core.utils import chat_formatting as cf from redbot.core.utils.views import SimpleMenu +def md(soup: BeautifulSoup, **options) -> Any | str: + return MarkdownConverter(**options).convert_soup(soup) + class SeaUtils(commands.Cog): """A collection of random utilities.""" @@ -188,21 +192,6 @@ class SeaUtils(commands.Cog): except (FileNotFoundError): await ctx.maybe_send_embed(message=cf.error("Neither `dig` nor `nslookup` are installed on the system. Unable to resolve DNS query.")) - async def get_results(self, ctx: commands.Context, soup: BeautifulSoup) -> list: - pre_tags = soup.find_all('pre') - content = [] - for pre_tag in pre_tags: - if await ctx.embed_requested(): - embed = Embed( - title="RFC Document", - description=pre_tag.text, - color=await ctx.embed_color() - ) - content.append(embed) - else: - content.append(pre_tag.text) - return content - @commands.command() async def rfc(self, ctx: commands.Context, number: int) -> None: """Retrieve the text of an RFC document.""" @@ -212,7 +201,18 @@ class SeaUtils(commands.Cog): if response.status == 200: html = await response.text() soup = BeautifulSoup(html, 'html.parser') - content = await self.get_results(ctx, soup) + pre_tags = soup.find_all('pre') + content = [] + for pre_tag in pre_tags: + if await ctx.embed_requested(): + embed = Embed( + title="RFC Document", + description=md(pre_tag), + color=await ctx.embed_color() + ) + content.append(embed) + else: + content.append(md(pre_tag)) await SimpleMenu(pages=content, disable_after_timeout=True, timeout=300).start(ctx) else: await ctx.maybe_send_embed(content=cf.error(f"An error occurred while fetching RFC {number}. Status code: {response.status}.")) From 99cd13ccf114179f4a188018223cd57435330a76 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 20:35:25 -0400 Subject: [PATCH 41/71] feat(seautils): add correct formatting for masked links --- seautils/seautils.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index a32d02c..9200927 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -8,6 +8,7 @@ import asyncio import inspect import operator +import re from asyncio.subprocess import Process from functools import partial, partialmethod from typing import Any @@ -28,6 +29,9 @@ from redbot.core.utils.views import SimpleMenu def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) +def convert_rfc_references(text: str): + return re.sub(r"\(RFC\s(\d+)\)", r"(https://www.rfc-editor.org/rfc/rfc\1.html)", text) + class SeaUtils(commands.Cog): """A collection of random utilities.""" @@ -204,15 +208,16 @@ class SeaUtils(commands.Cog): pre_tags = soup.find_all('pre') content = [] for pre_tag in pre_tags: + text = convert_rfc_references(md(pre_tag)) if await ctx.embed_requested(): embed = Embed( title="RFC Document", - description=md(pre_tag), + description=text, color=await ctx.embed_color() ) content.append(embed) else: - content.append(md(pre_tag)) + content.append(text) await SimpleMenu(pages=content, disable_after_timeout=True, timeout=300).start(ctx) else: await ctx.maybe_send_embed(content=cf.error(f"An error occurred while fetching RFC {number}. Status code: {response.status}.")) From c4ef2a7d4b32024fe56abcdb5d78d1fe9cce0cbe Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 20:38:39 -0400 Subject: [PATCH 42/71] fix(seautils): fixed some broken regex --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 9200927..ac71d1c 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -30,7 +30,7 @@ def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) def convert_rfc_references(text: str): - return re.sub(r"\(RFC\s(\d+)\)", r"(https://www.rfc-editor.org/rfc/rfc\1.html)", text) + return re.sub(r"\(\.rfc\s(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) class SeaUtils(commands.Cog): """A collection of random utilities.""" From 29b6a2141a6f0bf6e143025ee10cc3e16346c561 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 20:39:19 -0400 Subject: [PATCH 43/71] fix(seautils): actually actually fixed incorrect regex --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index ac71d1c..51a896f 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -30,7 +30,7 @@ def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) def convert_rfc_references(text: str): - return re.sub(r"\(\.rfc\s(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) + return re.sub(r"\(\.\/rfc\s(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) class SeaUtils(commands.Cog): """A collection of random utilities.""" From 0ed96babdbf0be6b69b9ef9aea03d579e209ba7e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 20:40:48 -0400 Subject: [PATCH 44/71] fix(seautils): ACTUALLY fixed broken regex --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 51a896f..f6943d1 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -30,7 +30,7 @@ def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) def convert_rfc_references(text: str): - return re.sub(r"\(\.\/rfc\s(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) + return re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) class SeaUtils(commands.Cog): """A collection of random utilities.""" From 42e209b54755768443605c71987069cd6278681d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:10:28 -0400 Subject: [PATCH 45/71] misc(seautils): include the number of the rfc document in the embed --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index f6943d1..146384f 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -211,7 +211,7 @@ class SeaUtils(commands.Cog): text = convert_rfc_references(md(pre_tag)) if await ctx.embed_requested(): embed = Embed( - title="RFC Document", + title=f"RFC Document {number}", description=text, color=await ctx.embed_color() ) From 8d3f5c1d5facc078854894ae2fdd4bcd20c5d00a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:16:10 -0400 Subject: [PATCH 46/71] fix(seautils): fix table of contents in rfc documents --- seautils/seautils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 146384f..649a875 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -29,8 +29,10 @@ from redbot.core.utils.views import SimpleMenu def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) -def convert_rfc_references(text: str): - return re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) +def convert_rfc_references(text: str, number: int) -> str: + one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) + two = re.sub(r"\((#(?:section|page)-\d+)\)", f"https://www.rfc-editor.org/rfc/rfc{number}.html\1", one) + return two class SeaUtils(commands.Cog): """A collection of random utilities.""" From 0ea80075f6cc2b55a76fc80fa688271c85611bd6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:16:45 -0400 Subject: [PATCH 47/71] fix(seautils): fixed a missing argument --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 649a875..5ef5dda 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -210,7 +210,7 @@ class SeaUtils(commands.Cog): pre_tags = soup.find_all('pre') content = [] for pre_tag in pre_tags: - text = convert_rfc_references(md(pre_tag)) + text = convert_rfc_references(md(pre_tag), number) if await ctx.embed_requested(): embed = Embed( title=f"RFC Document {number}", From ae8d0d5db4f7c3dac6513742991b3d942b6ebf61 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:17:29 -0400 Subject: [PATCH 48/71] fix(seautils): added missing () --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 5ef5dda..638a01e 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -31,7 +31,7 @@ def md(soup: BeautifulSoup, **options) -> Any | str: def convert_rfc_references(text: str, number: int) -> str: one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) - two = re.sub(r"\((#(?:section|page)-\d+)\)", f"https://www.rfc-editor.org/rfc/rfc{number}.html\1", one) + two = re.sub(r"\((#(?:section|page)-\d+)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) return two class SeaUtils(commands.Cog): From ac5d4df36b357a32edf75db721ba9b7839170d43 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:18:49 -0400 Subject: [PATCH 49/71] fix(seautils): fixed broken regex --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 638a01e..4db4bfc 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -31,7 +31,7 @@ def md(soup: BeautifulSoup, **options) -> Any | str: def convert_rfc_references(text: str, number: int) -> str: one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) - two = re.sub(r"\((#(?:section|page)-\d+)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) + two = re.sub(r"\((#(?:section|page)-\d+(?:.\d+)?)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) return two class SeaUtils(commands.Cog): From 861a03719bd8dd01db153f55fa5bf47c3a423b92 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:22:30 -0400 Subject: [PATCH 50/71] fix(seautils): added a bad solution to a stupid problem --- seautils/seautils.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 4db4bfc..fd6f25b 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -211,15 +211,35 @@ class SeaUtils(commands.Cog): content = [] for pre_tag in pre_tags: text = convert_rfc_references(md(pre_tag), number) - if await ctx.embed_requested(): - embed = Embed( - title=f"RFC Document {number}", - description=text, - color=await ctx.embed_color() - ) - content.append(embed) + if len(text) > 4096: + text1 = text[:4096] + text2 = text[4096:] + if await ctx.embed_requested(): + embed = Embed( + title=f"RFC Document {number}", + description=text1, + color=await ctx.embed_color() + ) + content.append(embed) + embed2 = Embed( + title=f"RFC Document {number}", + description=text2, + color=await ctx.embed_color() + ) + content.append(embed2) + else: + content.append(text1) + content.append(text2) else: - content.append(text) + if await ctx.embed_requested(): + embed = Embed( + title=f"RFC Document {number}", + description=text, + color=await ctx.embed_color() + ) + content.append(embed) + else: + content.append(text) await SimpleMenu(pages=content, disable_after_timeout=True, timeout=300).start(ctx) else: await ctx.maybe_send_embed(content=cf.error(f"An error occurred while fetching RFC {number}. Status code: {response.status}.")) From 2d895d16c9eaba1c56313a591f77859f7eb8d707 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:54:48 -0400 Subject: [PATCH 51/71] fix(seautils): fixed body error --- seautils/seautils.py | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index fd6f25b..6b2618a 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -208,28 +208,21 @@ class SeaUtils(commands.Cog): html = await response.text() soup = BeautifulSoup(html, 'html.parser') pre_tags = soup.find_all('pre') - content = [] + content: list[Embed | str] = [] for pre_tag in pre_tags: text = convert_rfc_references(md(pre_tag), number) if len(text) > 4096: - text1 = text[:4096] - text2 = text[4096:] - if await ctx.embed_requested(): - embed = Embed( - title=f"RFC Document {number}", - description=text1, - color=await ctx.embed_color() - ) - content.append(embed) - embed2 = Embed( - title=f"RFC Document {number}", - description=text2, - color=await ctx.embed_color() - ) - content.append(embed2) - else: - content.append(text1) - content.append(text2) + pagified_text = cf.pagify(text, delims=["\n\n"], page_length=4096) + for page in pagified_text: + if await ctx.embed_requested(): + embed = Embed( + title=f"RFC Document {number}", + description=page, + color=await ctx.embed_color() + ) + content.append(embed) + else: + content.append(page) else: if await ctx.embed_requested(): embed = Embed( @@ -240,6 +233,9 @@ class SeaUtils(commands.Cog): content.append(embed) else: content.append(text) + if await ctx.embed_requested(): + for embed in content: + embed.set_footer(text=f"Page {content.index(embed) + 1}/{len(content)}") await SimpleMenu(pages=content, disable_after_timeout=True, timeout=300).start(ctx) else: await ctx.maybe_send_embed(content=cf.error(f"An error occurred while fetching RFC {number}. Status code: {response.status}.")) From b9f0dbf98a5272d81e39c8c62788ccc47cda36dc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:56:43 -0400 Subject: [PATCH 52/71] fix(seautils): removed big gap at the bottom of rfc embeds --- seautils/seautils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 6b2618a..b37bdd6 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -32,7 +32,8 @@ def md(soup: BeautifulSoup, **options) -> Any | str: def convert_rfc_references(text: str, number: int) -> str: one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) two = re.sub(r"\((#(?:section|page)-\d+(?:.\d+)?)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) - return two + three: str = re.sub(r"\n{3,}", "\n\n", two) + return three class SeaUtils(commands.Cog): """A collection of random utilities.""" From 58245c621cfdc71cdab576de3177fb23b8019894 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 21:58:20 -0400 Subject: [PATCH 53/71] misc(seautils): changed a function name --- seautils/seautils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index b37bdd6..06e704e 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -29,7 +29,7 @@ from redbot.core.utils.views import SimpleMenu def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) -def convert_rfc_references(text: str, number: int) -> str: +def format_rfx_text(text: str, number: int) -> str: one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) two = re.sub(r"\((#(?:section|page)-\d+(?:.\d+)?)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) three: str = re.sub(r"\n{3,}", "\n\n", two) @@ -211,7 +211,7 @@ class SeaUtils(commands.Cog): pre_tags = soup.find_all('pre') content: list[Embed | str] = [] for pre_tag in pre_tags: - text = convert_rfc_references(md(pre_tag), number) + text = format_rfx_text(md(pre_tag), number) if len(text) > 4096: pagified_text = cf.pagify(text, delims=["\n\n"], page_length=4096) for page in pagified_text: From 069ea800db9c71dd684290cadc52b81fe3e1c859 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:02:42 -0400 Subject: [PATCH 54/71] feat(seautils): added a detailed docstring to the rfc command --- seautils/seautils.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 06e704e..3281583 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -201,7 +201,18 @@ class SeaUtils(commands.Cog): @commands.command() async def rfc(self, ctx: commands.Context, number: int) -> None: - """Retrieve the text of an RFC document.""" + """Retrieve the text of an RFC document. + + This command uses the [RFC Editor website](https://www.rfc-editor.org/) to fetch the text of an RFC document. + `number` refers to the number of the RFC document you wish to retrieve. + Modified excerpt from the RFC Editor website: + >>> The RFC Series (ISSN 2070-1721) contains technical and organizational documents about the Internet, + including the specifications and policy documents produced by five streams: + - [Internet Engineering Task Force](https://www.ietf.org/) + - [Internet Research Task Force](https://www.irtf.org/) + - [Internet Architecture Board](https://www.iab.org/) + - [Independent Submissions](https://www.rfc-editor.org/independent) + - [Editorial](https://www.rfc-editor.org/info/rfc9280)""" url = f"https://www.rfc-editor.org/rfc/rfc{number}.html" async with aiohttp.ClientSession() as session: async with session.get(url=url) as response: From 7207cd374721fbb99a89831521a5666c8798097e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:09:56 -0400 Subject: [PATCH 55/71] misc(seautils): improved the rfc docstring --- seautils/seautils.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 3281583..2084062 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -205,14 +205,10 @@ class SeaUtils(commands.Cog): This command uses the [RFC Editor website](https://www.rfc-editor.org/) to fetch the text of an RFC document. `number` refers to the number of the RFC document you wish to retrieve. - Modified excerpt from the RFC Editor website: - >>> The RFC Series (ISSN 2070-1721) contains technical and organizational documents about the Internet, - including the specifications and policy documents produced by five streams: - - [Internet Engineering Task Force](https://www.ietf.org/) - - [Internet Research Task Force](https://www.irtf.org/) - - [Internet Architecture Board](https://www.iab.org/) - - [Independent Submissions](https://www.rfc-editor.org/independent) - - [Editorial](https://www.rfc-editor.org/info/rfc9280)""" + Modified excerpt from [Wikipedia](https://en.wikipedia.org/wiki/Request_for_Comments): + >>> A Request for Comments (RFC) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). + An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. + It is submitted either for [peer review](https://en.wikipedia.org/wiki/Peer_review) or to convey new concepts, information, or, occasionally, engineering humor.""" # noqa: E501 url = f"https://www.rfc-editor.org/rfc/rfc{number}.html" async with aiohttp.ClientSession() as session: async with session.get(url=url) as response: From 4f25e3d0f3bfae987d4a5424dc745be1bd8964ed Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:11:11 -0400 Subject: [PATCH 56/71] fix(seautils): removed some text from the rfc docstring --- seautils/seautils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 2084062..30f7d12 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -204,7 +204,6 @@ class SeaUtils(commands.Cog): """Retrieve the text of an RFC document. This command uses the [RFC Editor website](https://www.rfc-editor.org/) to fetch the text of an RFC document. - `number` refers to the number of the RFC document you wish to retrieve. Modified excerpt from [Wikipedia](https://en.wikipedia.org/wiki/Request_for_Comments): >>> A Request for Comments (RFC) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. From dfabac55f510a72ff7dd64c49485a1467a551b5a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:13:18 -0400 Subject: [PATCH 57/71] misc(seautils): hopefully fixed `[p]rfc`'s help from overflowing into a second page --- seautils/seautils.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 30f7d12..73bcfae 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -204,10 +204,7 @@ class SeaUtils(commands.Cog): """Retrieve the text of an RFC document. This command uses the [RFC Editor website](https://www.rfc-editor.org/) to fetch the text of an RFC document. - Modified excerpt from [Wikipedia](https://en.wikipedia.org/wiki/Request_for_Comments): - >>> A Request for Comments (RFC) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). - An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. - It is submitted either for [peer review](https://en.wikipedia.org/wiki/Peer_review) or to convey new concepts, information, or, occasionally, engineering humor.""" # noqa: E501 + > A [Request for Comments (RFC)](https://en.wikipedia.org/wiki/Request_for_Comments) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. It is submitted either for [peer review](https://en.wikipedia.org/wiki/Peer_review) or to convey new concepts, information, or, occasionally, engineering humor.""" # noqa: E501 url = f"https://www.rfc-editor.org/rfc/rfc{number}.html" async with aiohttp.ClientSession() as session: async with session.get(url=url) as response: From 8f492cd93776ce07f10e1b7a60c6c3624d620353 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:14:35 -0400 Subject: [PATCH 58/71] fix(seautils): hopefully actually fixed the docstring --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 73bcfae..09f451b 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -204,7 +204,7 @@ class SeaUtils(commands.Cog): """Retrieve the text of an RFC document. This command uses the [RFC Editor website](https://www.rfc-editor.org/) to fetch the text of an RFC document. - > A [Request for Comments (RFC)](https://en.wikipedia.org/wiki/Request_for_Comments) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. It is submitted either for [peer review](https://en.wikipedia.org/wiki/Peer_review) or to convey new concepts, information, or, occasionally, engineering humor.""" # noqa: E501 + A [Request for Comments (RFC)](https://en.wikipedia.org/wiki/Request_for_Comments) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. It is submitted either for [peer review](https://en.wikipedia.org/wiki/Peer_review) or to convey new concepts, information, or, occasionally, engineering humor.""" # noqa: E501 url = f"https://www.rfc-editor.org/rfc/rfc{number}.html" async with aiohttp.ClientSession() as session: async with session.get(url=url) as response: From 5b23f2f0fbd0cd10faa349e195cdad3391de7e6b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:17:20 -0400 Subject: [PATCH 59/71] feat(seautils): add the url of the rfc document being retrieved to the embed --- seautils/seautils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seautils/seautils.py b/seautils/seautils.py index 09f451b..cd8a3dd 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -221,6 +221,7 @@ class SeaUtils(commands.Cog): if await ctx.embed_requested(): embed = Embed( title=f"RFC Document {number}", + url=url, description=page, color=await ctx.embed_color() ) From f51329524ce08e79ead3e9d8889918c523a5a983 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:19:09 -0400 Subject: [PATCH 60/71] fix(seautils): oops lmao --- seautils/seautils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seautils/seautils.py b/seautils/seautils.py index cd8a3dd..b3c9480 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -232,6 +232,7 @@ class SeaUtils(commands.Cog): if await ctx.embed_requested(): embed = Embed( title=f"RFC Document {number}", + url=url, description=text, color=await ctx.embed_color() ) From 037a26deb0c7c63a0bcce710c1eb5f87f39cc553 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:20:51 -0400 Subject: [PATCH 61/71] misc(seautils): switch to datatracker.ietf.org links for publicly facing urls --- seautils/seautils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index b3c9480..c4ff3d8 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -206,6 +206,7 @@ class SeaUtils(commands.Cog): This command uses the [RFC Editor website](https://www.rfc-editor.org/) to fetch the text of an RFC document. A [Request for Comments (RFC)](https://en.wikipedia.org/wiki/Request_for_Comments) is a publication in a series from the principal technical development and standards-setting bodies for the [Internet](https://en.wikipedia.org/wiki/Internet), most prominently the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force). An RFC is authored by individuals or groups of engineers and [computer scientists](https://en.wikipedia.org/wiki/Computer_scientist) in the form of a [memorandum](https://en.wikipedia.org/wiki/Memorandum) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet-connected systems. It is submitted either for [peer review](https://en.wikipedia.org/wiki/Peer_review) or to convey new concepts, information, or, occasionally, engineering humor.""" # noqa: E501 url = f"https://www.rfc-editor.org/rfc/rfc{number}.html" + datatracker_url = f"https://datatracker.ietf.org/doc/rfc{number}" async with aiohttp.ClientSession() as session: async with session.get(url=url) as response: if response.status == 200: @@ -221,7 +222,7 @@ class SeaUtils(commands.Cog): if await ctx.embed_requested(): embed = Embed( title=f"RFC Document {number}", - url=url, + url=datatracker_url, description=page, color=await ctx.embed_color() ) @@ -232,7 +233,7 @@ class SeaUtils(commands.Cog): if await ctx.embed_requested(): embed = Embed( title=f"RFC Document {number}", - url=url, + url=datatracker_url, description=text, color=await ctx.embed_color() ) From 545106d496f9f07a74209bc8755a0c88eeceed3e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 28 May 2024 22:25:47 -0400 Subject: [PATCH 62/71] fix(seautils): fixed a typo in a function name --- seautils/seautils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index c4ff3d8..76cc789 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -29,7 +29,7 @@ from redbot.core.utils.views import SimpleMenu def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) -def format_rfx_text(text: str, number: int) -> str: +def format_rfc_text(text: str, number: int) -> str: one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) two = re.sub(r"\((#(?:section|page)-\d+(?:.\d+)?)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) three: str = re.sub(r"\n{3,}", "\n\n", two) @@ -215,7 +215,7 @@ class SeaUtils(commands.Cog): pre_tags = soup.find_all('pre') content: list[Embed | str] = [] for pre_tag in pre_tags: - text = format_rfx_text(md(pre_tag), number) + text = format_rfc_text(md(pre_tag), number) if len(text) > 4096: pagified_text = cf.pagify(text, delims=["\n\n"], page_length=4096) for page in pagified_text: From 46f189a297e9abed28831fa95537e033e27abdc1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Thu, 30 May 2024 11:02:22 -0400 Subject: [PATCH 63/71] fix(seautils): pylint fix --- .forgejo/workflows/config/.pylintrc | 3 ++- seautils/seautils.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/config/.pylintrc b/.forgejo/workflows/config/.pylintrc index 2dd59c9..94010af 100644 --- a/.forgejo/workflows/config/.pylintrc +++ b/.forgejo/workflows/config/.pylintrc @@ -18,4 +18,5 @@ import-self, relative-beyond-top-level, too-many-instance-attributes, - duplicate-code + duplicate-code, + too-many-nested-blocks diff --git a/seautils/seautils.py b/seautils/seautils.py index 76cc789..56bc5d8 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -101,14 +101,14 @@ class SeaUtils(commands.Cog): @commands.command(name='dig', aliases=['dnslookup', 'nslookup']) @commands.is_owner() - async def dig(self, ctx: commands.Context, name: str, type: str | None = None, server: str | None = None, port: int = 53) -> None: + async def dig(self, ctx: commands.Context, name: str, record_type: str | None = None, server: str | None = None, port: int = 53) -> None: """Retrieve DNS information for a domain. Uses `dig` to perform a DNS query. Will fall back to `nslookup` if `dig` is not installed on the system. `nslookup` does not provide as much information as `dig`, so only the `name` parameter will be used if `nslookup` is used. Will return the A, AAAA, and CNAME records for a domain by default. You can specify a different record type with the `type` parameter.""" command_opts: list[str | int] = ['dig'] - query_types = [type] if type else ['A', 'AAAA', 'CNAME'] + query_types: list[str] = [record_type] if record_type else ['A', 'AAAA', 'CNAME'] if server: command_opts.extend(['@', server]) for query_type in query_types: From c06db07f0821a2f391c5b6208fa7ef9f3dd266e2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 1 Jun 2024 15:02:08 -0400 Subject: [PATCH 64/71] misc(seautils): bunch of miscellaneous changes --- seautils/seautils.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 56bc5d8..7a4040c 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -30,8 +30,8 @@ def md(soup: BeautifulSoup, **options) -> Any | str: return MarkdownConverter(**options).convert_soup(soup) def format_rfc_text(text: str, number: int) -> str: - one = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) - two = re.sub(r"\((#(?:section|page)-\d+(?:.\d+)?)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) + one: str = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) + two: str = re.sub(r"\((#(?:section|page)-\d+(?:.\d+)?)\)", f"(https://www.rfc-editor.org/rfc/rfc{number}.html\1)", one) three: str = re.sub(r"\n{3,}", "\n\n", two) return three @@ -41,23 +41,23 @@ class SeaUtils(commands.Cog): __author__ = ["SeaswimmerTheFsh"] __version__ = "1.0.0" - def __init__(self, bot: Red): + def __init__(self, bot: Red) -> None: self.bot = bot def format_help_for_context(self, ctx: commands.Context) -> str: - pre_processed = super().format_help_for_context(ctx) or "" + pre_processed = super().format_help_for_context(ctx=ctx) or "" n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", f"Cog Version: **{self.__version__}**", - f"Author: {cf.humanize_list(self.__author__)}" + f"Author: {cf.humanize_list(items=self.__author__)}" ] return "\n".join(text) def format_src(self, obj: Any) -> str: """A large portion of this code is repurposed from Zephyrkul's RTFS cog. https://github.com/Zephyrkul/FluffyCogs/blob/master/rtfs/rtfs.py""" - obj = inspect.unwrap(obj) + obj = inspect.unwrap(func=obj) src: Any = getattr(obj, "__func__", obj) if isinstance(obj, (commands.Command, app_commands.Command)): src = obj.callback @@ -67,11 +67,11 @@ class SeaUtils(commands.Cog): src = obj.fget elif isinstance(obj, (cached_property, CachedSlotProperty)): src = obj.function - return inspect.getsource(src) + return inspect.getsource(object=src) @commands.command(aliases=["source", "src", "code", "showsource"]) @commands.is_owner() - async def showcode(self, ctx: commands.Context, *, object: str): # pylint: disable=redefined-builtin + async def showcode(self, ctx: commands.Context, *, object: str) -> None: # pylint: disable=redefined-builtin """Show the code for a particular object.""" try: if object.startswith("/") and (obj := ctx.bot.tree.get_command(object[1:])): @@ -195,7 +195,7 @@ class SeaUtils(commands.Cog): embed.description = warning + cf.box(text=ns_stdout.decode()) await ctx.send(embed=embed) else: - await ctx.send(content= warning + cf.box(text=ns_stdout.decode())) + await ctx.send(content = warning + cf.box(text=ns_stdout.decode())) except (FileNotFoundError): await ctx.maybe_send_embed(message=cf.error("Neither `dig` nor `nslookup` are installed on the system. Unable to resolve DNS query.")) From 66b933569be682381744fc67d82723a505e6519b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 1 Jun 2024 15:03:23 -0400 Subject: [PATCH 65/71] misc(seautils): soup --- seautils/seautils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seautils/seautils.py b/seautils/seautils.py index 7a4040c..304fd70 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -27,7 +27,7 @@ from redbot.core.utils.views import SimpleMenu def md(soup: BeautifulSoup, **options) -> Any | str: - return MarkdownConverter(**options).convert_soup(soup) + return MarkdownConverter(**options).convert_soup(soup=soup) def format_rfc_text(text: str, number: int) -> str: one: str = re.sub(r"\(\.\/rfc(\d+)", r"(https://www.rfc-editor.org/rfc/rfc\1.html", text) From 2ac1dacd19af043ab643b325f83707328dc0273d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 01:10:00 -0400 Subject: [PATCH 66/71] fix(backup): added another error type caught by backup import, in the case where you didn't reply to a message or upload a file --- backup/backup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/backup.py b/backup/backup.py index 7fe9b4d..6202e3a 100644 --- a/backup/backup.py +++ b/backup/backup.py @@ -100,7 +100,7 @@ class Backup(commands.Cog): except (json.JSONDecodeError, IndexError): try: export = json.loads(await ctx.message.reference.resolved.attachments[0].read()) - except (json.JSONDecodeError, IndexError): + except (json.JSONDecodeError, IndexError, AttributeError): await ctx.send(error("Please provide a valid JSON export file.")) return From 73547699620538f6f28106c2759b6a82cc0d8310 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 12:16:01 -0400 Subject: [PATCH 67/71] fix(emojiinfo): pylint fix --- emojiinfo/model.py | 1 + 1 file changed, 1 insertion(+) diff --git a/emojiinfo/model.py b/emojiinfo/model.py index af457d1..cc8a468 100644 --- a/emojiinfo/model.py +++ b/emojiinfo/model.py @@ -81,6 +81,7 @@ class PartialEmoji(discord.PartialEmoji): with open(path, "r", encoding="UTF-8") as file: emojis: dict = json.load(file) emoji_aliases = [] + emoji_group = None for dict_name, group in emojis.items(): for k, v in group.items(): if v == value: From 28f814db564444c672857e1b82e52e3c44ff79fd Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 12:16:09 -0400 Subject: [PATCH 68/71] fix(seautils): pylint fix --- seautils/seautils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/seautils/seautils.py b/seautils/seautils.py index 304fd70..3bbf5cf 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -80,6 +80,8 @@ class SeaUtils(commands.Cog): text = self.format_src(type(obj)) elif obj := ctx.bot.get_command(object): text = self.format_src(obj) + else: + raise AttributeError temp_content = cf.pagify( text=cleanup_code(text), escape_mass_mentions=True, From e3e96e5b842ba8bd3ee8a6da5786369b6d4f508a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 11 Jun 2024 16:39:04 -0400 Subject: [PATCH 69/71] fix(workflow): changed meli token --- .forgejo/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index f88c687..98b12fc 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -58,7 +58,7 @@ jobs: npx -p "@getmeli/cli" meli upload ./site \ --url "https://pages.coastalcommits.com" \ --site "${{ vars.MELI_SITE_ID }}" \ - --token "${{ secrets.MELI_SITE_SECRET }}" \ + --token "${{ secrets.MELI_SECRET }}" \ --release "$CI_ACTION_REF_NAME_SLUG/${{ env.GITHUB_SHA }}" \ --branch "$CI_ACTION_REF_NAME_SLUG" From 24239425c5a183348add69dc53fc08c5f6f9a821 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 11 Jun 2024 16:48:03 -0400 Subject: [PATCH 70/71] fix(workflows): missing -e argument --- .forgejo/workflows/workflow.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 98b12fc..baca6fb 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -53,7 +53,7 @@ jobs: unset GITHUB_TOKEN unset GITLAB_TOKEN - echo "${YELLOW}Deploying to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}...\n" + echo -e "${YELLOW}Deploying to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}...\n" npx -p "@getmeli/cli" meli upload ./site \ --url "https://pages.coastalcommits.com" \ @@ -62,7 +62,7 @@ jobs: --release "$CI_ACTION_REF_NAME_SLUG/${{ env.GITHUB_SHA }}" \ --branch "$CI_ACTION_REF_NAME_SLUG" - echo "\n${YELLOW}Deployed to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}!" - echo "${GREEN}https://$CI_ACTION_REF_NAME_SLUG.seacogs.coastalcommits.com/" + echo -e "\n${YELLOW}Deployed to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}!" + echo -e "${GREEN}https://$CI_ACTION_REF_NAME_SLUG.seacogs.coastalcommits.com/" env: GITEA_TOKEN: ${{ secrets.COASTALCOMMITSTOKEN }} From d173dd68a5c760ed77dcca6e33b79e855fff8d04 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 11 Jun 2024 16:50:15 -0400 Subject: [PATCH 71/71] fix(workflow): nvm --- .forgejo/workflows/workflow.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index baca6fb..98b12fc 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -53,7 +53,7 @@ jobs: unset GITHUB_TOKEN unset GITLAB_TOKEN - echo -e "${YELLOW}Deploying to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}...\n" + echo "${YELLOW}Deploying to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}...\n" npx -p "@getmeli/cli" meli upload ./site \ --url "https://pages.coastalcommits.com" \ @@ -62,7 +62,7 @@ jobs: --release "$CI_ACTION_REF_NAME_SLUG/${{ env.GITHUB_SHA }}" \ --branch "$CI_ACTION_REF_NAME_SLUG" - echo -e "\n${YELLOW}Deployed to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}!" - echo -e "${GREEN}https://$CI_ACTION_REF_NAME_SLUG.seacogs.coastalcommits.com/" + echo "\n${YELLOW}Deployed to ${BLUE}Meli ${YELLOW}on branch ${GREEN}$CI_ACTION_REF_NAME_SLUG${YELLOW}!" + echo "${GREEN}https://$CI_ACTION_REF_NAME_SLUG.seacogs.coastalcommits.com/" env: GITEA_TOKEN: ${{ secrets.COASTALCOMMITSTOKEN }}