-
-
Notifications
You must be signed in to change notification settings - Fork 43
Better version of cowsay #1028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Better version of cowsay #1028
Conversation
Reviewer's GuideIntroduces a new Cowsay cog that defines a hybrid_command with usage generation, enforces per-user cooldowns, sanitizes and length-limits input, and generates ASCII art output using the cowsay library. Sequence diagram for the cowsay command execution with cooldown and input validationsequenceDiagram
actor User
participant DiscordBot as Bot
participant CowsayCog
participant cowsay
User->>Bot: Invoke /cowsay command with text
Bot->>CowsayCog: cowsay_command(ctx, text)
CowsayCog->>CowsayCog: Check user cooldown
alt On cooldown
CowsayCog->>Bot: Respond with cooldown message (ephemeral)
else Not on cooldown
CowsayCog->>CowsayCog: Sanitize and check text length
alt Text too long
CowsayCog->>Bot: Send error message
else Text valid
CowsayCog->>cowsay: get_output_string("cow", sanitized_text)
cowsay-->>CowsayCog: ASCII cow text
CowsayCog->>Bot: Send cow ASCII art
end
end
Class diagram for the new Cowsay cog and commandclassDiagram
class Cowsay {
+__init__(bot: Tux)
+cowsay_command(ctx: commands.Context[Tux], text: str)
}
class Tux
class commands.Cog
Cowsay --|> commands.Cog
Cowsay o-- Tux
class cowsay {
+get_output_string(animal: str, text: str)
}
Cowsay ..> cowsay : uses
class user_cooldowns {
+user_id: float (timestamp)
}
Cowsay ..> user_cooldowns : uses
class generate_usage {
+generate_usage(command)
}
Cowsay ..> generate_usage : uses
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `tux/cogs/fun/cowsay.py:44` </location>
<code_context>
+
+ # Enforce character limit and sanitize input
+ max_length = 200
+ sanitized_text = ''.join(c for c in text if c.isprintable()).strip()
+ if len(sanitized_text) > max_length:
+ await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.")
</code_context>
<issue_to_address>
Sanitization may not prevent all unwanted input (e.g., backticks or code block escapes).
Consider escaping or removing backticks and other Markdown-sensitive characters to avoid Discord code block formatting issues.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
# Enforce character limit and sanitize input
max_length = 200
sanitized_text = ''.join(c for c in text if c.isprintable()).strip()
if len(sanitized_text) > max_length:
await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.")
return
cow_text = cowsay.get_output_string("cow", sanitized_text)
await ctx.send(content=f"```{cow_text}```")
=======
# Enforce character limit and sanitize input
max_length = 200
sanitized_text = ''.join(c for c in text if c.isprintable()).strip()
# Remove Markdown-sensitive characters (backticks and triple backticks)
sanitized_text = sanitized_text.replace("`", "")
sanitized_text = sanitized_text.replace("```", "")
if len(sanitized_text) > max_length:
await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.")
return
cow_text = cowsay.get_output_string("cow", sanitized_text)
await ctx.send(content=f"```{cow_text}```")
>>>>>>> REPLACE
</suggested_fix>
### Comment 2
<location> `tux/cogs/fun/cowsay.py:49` </location>
<code_context>
+ await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.")
+ return
+
+ cow_text = cowsay.get_output_string("cow", sanitized_text)
+ await ctx.send(content=f"```{cow_text}```")
+
</code_context>
<issue_to_address>
Potential for cowsay output to exceed Discord's message length limit.
Check cow_text length before sending, and truncate or split if it exceeds Discord's 2000 character limit.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
cow_text = cowsay.get_output_string("cow", sanitized_text)
await ctx.send(content=f"```{cow_text}```")
=======
cow_text = cowsay.get_output_string("cow", sanitized_text)
# Discord message limit is 2000 characters
max_discord_length = 2000
cow_text_wrapped = f"```{cow_text}```"
if len(cow_text_wrapped) <= max_discord_length:
await ctx.send(content=cow_text_wrapped)
else:
# Split cow_text into chunks that fit within the Discord limit, accounting for code block markers
code_block_start = "```"
code_block_end = "```"
max_chunk_length = max_discord_length - len(code_block_start) - len(code_block_end)
for i in range(0, len(cow_text), max_chunk_length):
chunk = cow_text[i:i+max_chunk_length]
await ctx.send(content=f"{code_block_start}{chunk}{code_block_end}")
>>>>>>> REPLACE
</suggested_fix>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
tux/cogs/fun/cowsay.py
Outdated
# Enforce character limit and sanitize input | ||
max_length = 200 | ||
sanitized_text = ''.join(c for c in text if c.isprintable()).strip() | ||
if len(sanitized_text) > max_length: | ||
await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.") | ||
return | ||
|
||
cow_text = cowsay.get_output_string("cow", sanitized_text) | ||
await ctx.send(content=f"```{cow_text}```") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): Sanitization may not prevent all unwanted input (e.g., backticks or code block escapes).
Consider escaping or removing backticks and other Markdown-sensitive characters to avoid Discord code block formatting issues.
# Enforce character limit and sanitize input | |
max_length = 200 | |
sanitized_text = ''.join(c for c in text if c.isprintable()).strip() | |
if len(sanitized_text) > max_length: | |
await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.") | |
return | |
cow_text = cowsay.get_output_string("cow", sanitized_text) | |
await ctx.send(content=f"```{cow_text}```") | |
# Enforce character limit and sanitize input | |
max_length = 200 | |
sanitized_text = ''.join(c for c in text if c.isprintable()).strip() | |
# Remove Markdown-sensitive characters (backticks and triple backticks) | |
sanitized_text = sanitized_text.replace("`", "") | |
sanitized_text = sanitized_text.replace("```", "") | |
if len(sanitized_text) > max_length: | |
await ctx.send(content=f"❌ Input too long! Please limit your message to {max_length} characters.") | |
return | |
cow_text = cowsay.get_output_string("cow", sanitized_text) | |
await ctx.send(content=f"```{cow_text}```") |
cow_text = cowsay.get_output_string("cow", sanitized_text) | ||
await ctx.send(content=f"```{cow_text}```") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Potential for cowsay output to exceed Discord's message length limit.
Check cow_text length before sending, and truncate or split if it exceeds Discord's 2000 character limit.
cow_text = cowsay.get_output_string("cow", sanitized_text) | |
await ctx.send(content=f"```{cow_text}```") | |
cow_text = cowsay.get_output_string("cow", sanitized_text) | |
# Discord message limit is 2000 characters | |
max_discord_length = 2000 | |
cow_text_wrapped = f"```{cow_text}```" | |
if len(cow_text_wrapped) <= max_discord_length: | |
await ctx.send(content=cow_text_wrapped) | |
else: | |
# Split cow_text into chunks that fit within the Discord limit, accounting for code block markers | |
code_block_start = "```" | |
code_block_end = "```" | |
max_chunk_length = max_discord_length - len(code_block_start) - len(code_block_end) | |
for i in range(0, len(cow_text), max_chunk_length): | |
chunk = cow_text[i:i+max_chunk_length] | |
await ctx.send(content=f"{code_block_start}{chunk}{code_block_end}") |
it'll probably be a while till we get around look to this, just to let you know |
changes: added cowsay.py
Summary by Sourcery
Introduce a new cowsay cog that allows users to generate ASCII cow messages with input validation and a per-user cooldown
New Features:
cowsay
command to render ASCII cow speech in Discordcowsay
command