Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
pieckenst committed Aug 26, 2024
2 parents f29c58f + ab49602 commit 9aafe81
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 62 deletions.
2 changes: 1 addition & 1 deletion cogs/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,4 @@ async def get_help(self, interaction, CogToPassAlong):


async def setup(bot):
await bot.add_cog(Help(bot))
await bot.add_cog(Help(bot))
89 changes: 57 additions & 32 deletions cogs/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,7 @@ async def rtfm(self, ctx, *, args=None):

@app_commands.command(description="Looks up docs", name="rtfm")
async def rtfm_slash(
self,
interaction: discord.Interaction,
library: typing.Optional[str] = None,
query: typing.Optional[str] = None
self, interaction: discord.Interaction, library: typing.Optional[str] = None, query: typing.Optional[str] = None
) -> None:
"""Looks up docs for a library with optionally a query."""
libraries = dict(self.rtfm_dictionary)
Expand All @@ -361,27 +358,37 @@ async def rtfm_slash(
await interaction.response.send_message(f"Alright, let's see\n{library + query}")

@rtfm_slash.autocomplete("library")
async def rtfm_library_autocomplete(self, interaction: discord.Interaction, current: str) -> list[app_commands.Choice]:
async def rtfm_library_autocomplete(
self, interaction: discord.Interaction, current: str
) -> list[app_commands.Choice]:
libraries = dict(self.rtfm_dictionary)
all_choices = [app_commands.Choice(name=name, value=link) for name, link in libraries.items()]
startswith = [choice for choice in all_choices if choice.name.lower().startswith(current.lower())]
return (startswith or all_choices)[:25]

@rtfm_slash.autocomplete("query")
async def rtfm_query_autocomplete(self, interaction: discord.Interaction, current: str) -> list[app_commands.Choice]:
async def rtfm_query_autocomplete(
self, interaction: discord.Interaction, current: str
) -> list[app_commands.Choice]:
url = interaction.namespace.library or dict(self.rtfm_dictionary)["master"]
unfiltered_results = await utils.rtfm(self.bot, url)
all_choices = [app_commands.Choice(name=result.name, value=result.url.replace(url, "")) for result in unfiltered_results]
all_choices = [
app_commands.Choice(name=result.name, value=result.url.replace(url, "")) for result in unfiltered_results
]

if not current:
return all_choices[:25]

filtered_results = fuzzy.finder(current, unfiltered_results, key=lambda t: t.name)
return [app_commands.Choice(name=result.name, value=result.url.replace(url, "")) for result in filtered_results][:25]
return [
app_commands.Choice(name=result.name, value=result.url.replace(url, "")) for result in filtered_results
][:25]

@rtfm_slash.error
async def rtfm_error(self, interaction: discord.Interaction, error: Exception) -> None:
await interaction.response.send_message(f"An error occurred: {error}. Please report this to my developer.", ephemeral=True)
await interaction.response.send_message(
f"An error occurred: {error}. Please report this to my developer.", ephemeral=True
)
print(f"Error in {interaction.command}: {error}")

def charinfo_converter(self, char: str) -> str:
Expand Down Expand Up @@ -423,7 +430,12 @@ async def pep8(self, ctx):
code = codeblock_converter(argument=modal.value)

use_special_formatting = modal.value2 is True
await message.edit(content="Using special formatting (120 characters)" if use_special_formatting else "Using default formatting", view=None)
await message.edit(
content=(
"Using special formatting (120 characters)" if use_special_formatting else "Using default formatting"
),
view=None,
)

try:
formatted_code = await asyncio.to_thread(utils.formatter, code.content, use_special_formatting)
Expand All @@ -443,7 +455,7 @@ async def pfp_grab(self, ctx):
avatar = ctx.author.display_avatar
file_extension = ".gif" if avatar.is_animated() else ".png"
file = await avatar.to_file(filename=f"pfp{file_extension}")

try:
await ctx.send("Here's your avatar:", file=file)
except discord.HTTPException:
Expand All @@ -456,32 +468,35 @@ async def pypi(self, ctx, *, package_name: str = None):

async with self.bot.session.get(f"https://pypi.org/pypi/{package_name}/json") as response:
if not response.ok:
return await ctx.send(f"Could not find package **{package_name}** on PyPI.", allowed_mentions=discord.AllowedMentions.none())
return await ctx.send(
f"Could not find package **{package_name}** on PyPI.",
allowed_mentions=discord.AllowedMentions.none(),
)

pypi_data = (await response.json())["info"]

embed = discord.Embed(
title=f"{pypi_data.get('name', 'N/A')} {pypi_data.get('version', 'N/A')}",
url=pypi_data.get('release_url', 'https://pypi.org'),
description=pypi_data.get('summary', 'No summary provided'),
color=discord.Color.random()
url=pypi_data.get("release_url", "https://pypi.org"),
description=pypi_data.get("summary", "No summary provided"),
color=discord.Color.random(),
)

embed.set_thumbnail(url="https://i.imgur.com/oP0e7jK.png")

embed.add_field(
name="Author Info",
value=f"**Name:** {pypi_data.get('author', 'N/A')}\n**Email:** {pypi_data.get('author_email', 'N/A')}",
inline=False
inline=False,
)
embed.add_field(
name="Package Info",
value=f"**Download URL:** {pypi_data.get('download_url', 'N/A')}\n"
f"**Documentation:** {pypi_data.get('docs_url', 'N/A')}\n"
f"**Home Page:** {pypi_data.get('home_page', 'N/A')}\n"
f"**Keywords:** {pypi_data.get('keywords', 'N/A')}\n"
f"**License:** {pypi_data.get('license', 'N/A')}",
inline=False
f"**Documentation:** {pypi_data.get('docs_url', 'N/A')}\n"
f"**Home Page:** {pypi_data.get('home_page', 'N/A')}\n"
f"**Keywords:** {pypi_data.get('keywords', 'N/A')}\n"
f"**License:** {pypi_data.get('license', 'N/A')}",
inline=False,
)

await ctx.send(embed=embed)
Expand All @@ -495,8 +510,14 @@ async def invite_bot(self, ctx, *, user: discord.User = commands.Author):
slash_invite = discord.utils.oauth_url(client_id=user.id)

view = discord.ui.View()
view.add_item(discord.ui.Button(label=f"{user.name}'s Normal Invite", url=invite, style=discord.ButtonStyle.link))
view.add_item(discord.ui.Button(label=f"{user.name}'s Invite With Slash Commands", url=slash_invite, style=discord.ButtonStyle.link))
view.add_item(
discord.ui.Button(label=f"{user.name}'s Normal Invite", url=invite, style=discord.ButtonStyle.link)
)
view.add_item(
discord.ui.Button(
label=f"{user.name}'s Invite With Slash Commands", url=slash_invite, style=discord.ButtonStyle.link
)
)

await ctx.send("Invite with slash commands and the bot scope or only with a bot scope:", view=view)

Expand All @@ -521,7 +542,7 @@ async def created_at(self, ctx, *, user: utils.SuperConverter = commands.Author)
f"Mention: {user.mention} was created:\n"
f"{creation_info}\n"
f"Raw Version: {creation_info}",
allowed_mentions=discord.AllowedMentions.none()
allowed_mentions=discord.AllowedMentions.none(),
)

@commands.command(brief="Makes a fake user ID based on the current time.")
Expand All @@ -537,7 +558,7 @@ async def snowflake_info(self, ctx, *, snowflake: typing.Optional[utils.ObjectPl
embed = discord.Embed(title="❄️ Snowflake Info:", color=discord.Color.blue())
embed.add_field(
name="Created At:",
value=f"{discord.utils.format_dt(snowflake.created_at, style='D')}\n{discord.utils.format_dt(snowflake.created_at, style='T')}"
value=f"{discord.utils.format_dt(snowflake.created_at, style='D')}\n{discord.utils.format_dt(snowflake.created_at, style='T')}",
)
embed.add_field(name="Worker ID:", value=str(snowflake.worker_id))
embed.add_field(name="Process ID:", value=str(snowflake.process_id))
Expand All @@ -558,9 +579,9 @@ async def fake_token(self, ctx):
embed = discord.Embed(
title="Newly Generated Fake Token",
description=f"ID: `{discord_object.id}`\n"
f"Created at:\n"
f"{discord.utils.format_dt(discord_object.created_at, style='D')}\n"
f"{discord.utils.format_dt(discord_object.created_at, style='T')}"
f"Created at:\n"
f"{discord.utils.format_dt(discord_object.created_at, style='D')}\n"
f"{discord.utils.format_dt(discord_object.created_at, style='T')}",
)
embed.add_field(name="Generated Token:", value=f"`{first_bit}.{second_bit}.{last_bit}`")
embed.set_thumbnail(url=ctx.author.display_avatar.url)
Expand All @@ -587,17 +608,21 @@ async def addbot(self, ctx, *, user: discord.User = commands.Author):
member = await self.bot.try_member(guild, ctx.author.id)
if member is None:
view = discord.ui.View()
view.add_item(discord.ui.Button(label="Test Guild Invite", url="https://discord.gg/hKn8qgCDzK", style=discord.ButtonStyle.link))
view.add_item(
discord.ui.Button(
label="Test Guild Invite", url="https://discord.gg/hKn8qgCDzK", style=discord.ButtonStyle.link
)
)
return await message.edit(
content="Make sure to join the guild linked soon... then rerun the command. If you are in the guild, contact the owner (listed in the owner command).",
view=view
view=view,
)

embed = discord.Embed(
title="Bot Request",
colour=discord.Colour.blurple(),
description=f"Reason:\n{modal.value}\n\n[Invite URL]({discord.utils.oauth_url(client_id=user.id, scopes=('bot',))})",
timestamp=ctx.message.created_at
timestamp=ctx.message.created_at,
)

embed.add_field(name="Author", value=f"{ctx.author} (ID: {ctx.author.id})", inline=False)
Expand Down Expand Up @@ -685,4 +710,4 @@ async def console(self, ctx, *, code: codeblock_converter = None):

async def setup(bot):
await bot.add_cog(Info(bot))
await bot.add_cog(DevTools(bot))
await bot.add_cog(DevTools(bot))
57 changes: 28 additions & 29 deletions utils/extra.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async def google_tts(bot: JDBot, text: str, language: str = "en") -> discord.Fil
params={"text": text, "language": language},
) as response:
mp3_data = await response.read()

mp3_fp = io.BytesIO(mp3_data)
return discord.File(mp3_fp, f"{language}_tts.mp3")

Expand Down Expand Up @@ -88,8 +88,7 @@ async def post(bot: JDBot, code: str) -> str:

async def get_paste(bot: JDBot, paste_id: str) -> Optional[str]:
async with bot.session.get(
f"https://api.senarc.net/bin/{paste_id}",
headers={"accept": "application/json", "headless": "true"}
f"https://api.senarc.net/bin/{paste_id}", headers={"accept": "application/json", "headless": "true"}
) as response:
json_data: dict = await response.json()
return json_data.get("content")
Expand All @@ -101,17 +100,9 @@ def groupby(iterable: list[Any], count: int) -> list[list[Any]]:

def npm_create_embed(data: dict) -> discord.Embed:
e = discord.Embed(title=f"Package information for **{data.get('name')}**")
e.add_field(
name="**Latest Version:**",
value=f"\n{data.get('latest_version', 'None Provided')}",
inline=False
)
e.add_field(
name="**Description:**",
value=f"\n{data.get('description', 'None Provided')}",
inline=False
)

e.add_field(name="**Latest Version:**", value=f"\n{data.get('latest_version', 'None Provided')}", inline=False)
e.add_field(name="**Description:**", value=f"\n{data.get('description', 'None Provided')}", inline=False)

formatted_author = ""
authors = data.get("authors", [])
if isinstance(authors, list):
Expand All @@ -122,14 +113,14 @@ def npm_create_embed(data: dict) -> discord.Embed:

e.add_field(name="**Author:**", value=f"\n{formatted_author}", inline=False)
e.add_field(name="**License:**", value=f"\n{data.get('license', 'None Provided')}", inline=False)

dependencies = [[lib, min_version] for lib, min_version in data.get("dependencies", {}).items()]
e.add_field(
name="Dependencies:",
value=f"\n{tabulate.tabulate(dependencies, ['Library', 'Minimum version'])}",
inline=False,
)

if next_version := data.get("next_version"):
e.add_field(name="**Upcoming Version:**", value=f"\n{next_version}")

Expand All @@ -139,7 +130,7 @@ def npm_create_embed(data: dict) -> discord.Embed:
def get_required_npm(data: dict) -> dict:
latest = data["dist-tags"]["latest"]
version_data = data["versions"][latest]

return {
"latest_version": latest,
"next_version": data["dist-tags"].get("next"),
Expand Down Expand Up @@ -363,8 +354,9 @@ class InvalidateType(enum.IntEnum):
DM = 2
CHANNEL = 3


class InvalidationConfig:
def __init__(self, entity_id: int, entity_type: InvalidateType, bot: 'JDBot'):
def __init__(self, entity_id: int, entity_type: InvalidateType, bot: "JDBot"):
self.entity_id = entity_id
self.entity_type = entity_type
self.bot = bot
Expand All @@ -383,34 +375,41 @@ def entity(self) -> Optional[Union[User, Guild, DMChannel, TextChannel]]:
return self.bot.get_channel(self.entity_id)
return None


class InvalidationManager:
def __init__(self, bot: 'JDBot'):
def __init__(self, bot: "JDBot"):
self.bot = bot

async def add_entity(self, entity_id: int, entity_type: InvalidateType, in_chosen: bool = True) -> InvalidationConfig:
async def add_entity(
self, entity_id: int, entity_type: InvalidateType, in_chosen: bool = True
) -> InvalidationConfig:
table = "invalidation_config" if in_chosen else "invalidation_out"
await self.bot.db.execute(
f"INSERT INTO {table} (entity_id, entity_type) VALUES ($1, $2)",
entity_id, entity_type.value
f"INSERT INTO {table} (entity_id, entity_type) VALUES ($1, $2)", entity_id, entity_type.value
)
return InvalidationConfig(entity_id, entity_type, self.bot)

async def verify_entity(self, entity_id: int, entity_type: InvalidateType, in_chosen: bool = True) -> Optional[dict]:
async def verify_entity(
self, entity_id: int, entity_type: InvalidateType, in_chosen: bool = True
) -> Optional[dict]:
table = "invalidation_config" if in_chosen else "invalidation_out"
return await self.bot.db.fetchrow(
f"SELECT * FROM {table} WHERE entity_id = $1 AND entity_type = $2",
entity_id, entity_type.value
f"SELECT * FROM {table} WHERE entity_id = $1 AND entity_type = $2", entity_id, entity_type.value
)

async def remove_entity(self, entity_id: int, entity_type: InvalidateType, in_chosen: bool = True) -> None:
table = "invalidation_config" if in_chosen else "invalidation_out"
await self.bot.db.execute(
f"DELETE FROM {table} WHERE entity_id = $1 AND entity_type = $2",
entity_id, entity_type.value
f"DELETE FROM {table} WHERE entity_id = $1 AND entity_type = $2", entity_id, entity_type.value
)

def check_invalidation(
self, cache: list[InvalidationConfig], entity_id: int, entity_type: InvalidateType
) -> Optional[InvalidationConfig]:
return next(
(config for config in cache if config.entity_id == entity_id and config.entity_type == entity_type), None
)

def check_invalidation(self, cache: list[InvalidationConfig], entity_id: int, entity_type: InvalidateType) -> Optional[InvalidationConfig]:
return next((config for config in cache if config.entity_id == entity_id and config.entity_type == entity_type), None)

# Usage example:
# invalidation_manager = InvalidationManager(bot)
Expand Down

0 comments on commit 9aafe81

Please sign in to comment.