Skip to content

Conversation

@HikariNee
Copy link
Contributor

@HikariNee HikariNee commented Jun 3, 2025

Description

This PR fixes the evaluation of Javscript and typescript (and Pascal), removes the local error handler and does some visual changes.

Guidelines

  • My code follows the style guidelines of this project (formatted with Ruff)

  • I have performed a self-review of my own code

  • I have commented my code, particularly in hard-to-understand areas

  • I have made corresponding changes to the documentation if needed

  • My changes generate no new warnings

  • I have tested this change

  • Any dependent changes have been merged and published in downstream modules

  • I have added all appropriate labels to this PR

  • [Y] I have followed all of these guidelines.

How Has This Been Tested? (if applicable)

By invoking it in the Tux dev server.

Screenshots (if applicable)

NA

Additional Information

NA

Summary by Sourcery

Restructure and improve the run cog by formalizing code dispatch services, centralizing constants, and replacing monolithic parsing logic with helpers. Introduce custom exceptions for clear error reporting, fix JavaScript/TypeScript execution, and enhance embeds with a close button while removing the old global error handler.

New Features:

  • Add custom code execution exceptions for structured error handling in the run command
  • Enable code extraction from replies and embed a close button on execution result embeds

Bug Fixes:

  • Fix JavaScript and TypeScript evaluation by updating compiler mappings and service dispatch logic
  • Remove the global/local error handler for the run command and replace it with exception-based handling

Enhancements:

  • Refactor the code execution cog into an abstract CodeDispatch base class with separate GodboltService and WandboxService implementations
  • Centralize compiler mappings, supported languages list, and utility functions (_remove_ansi, _remove_backticks) as module-level constants
  • Improve Wandbox API wrapper with proper JSON headers and filter excessively verbose Nim errors

Documentation:

  • Add comprehensive docstrings for services, helper methods, and commands
  • Update error handler configuration to map new code execution exceptions to user-friendly messages

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jun 3, 2025

Reviewer's Guide

This PR refactors the code execution pipeline by restructuring the run command and dispatch services into typed, doc-driven components, replaces the global error handler with structured exceptions, corrects JavaScript/TypeScript evaluation and output filtering (including Nim error suppression), and adds appropriate headers and reaction handling.

Sequence Diagram for Successful '$run' Command Execution

sequenceDiagram
    actor User
    participant DiscordClient as Discord Client
    participant RunCog as Run Cog
    participant SelectedService as Execution Service (Godbolt/Wandbox)
    participant ExternalAPI as External API (Godbolt/Wandbox)

    User->>DiscordClient: !run [lang] ```code```
    DiscordClient->>RunCog: run(ctx, code)
    RunCog->>RunCog: _extract_code_from_message(ctx, code)
    opt code found
        RunCog->>RunCog: _parse_code_block(extracted_code)
        RunCog->>RunCog: _determine_service(language)
    end
    alt Service determined and code valid
        RunCog->>DiscordClient: add_reaction(LOADING_REACTION)
        RunCog->>SelectedService: run(language, source_code)
        activate SelectedService
        SelectedService->>SelectedService: _execute(compiler, source_code, options)
        SelectedService->>ExternalAPI: POST /api/... (code, compiler, options)
        activate ExternalAPI
        ExternalAPI-->>SelectedService: HTTP Response (output)
        deactivate ExternalAPI
        SelectedService-->>RunCog: output_string
        deactivate SelectedService
        RunCog->>RunCog: _create_result_embed(output_string, language, service)
        RunCog->>RunCog: _create_close_button_view()
        RunCog->>DiscordClient: send(embed, view)
        RunCog->>DiscordClient: clear_reaction(LOADING_REACTION)
    else Service not determined or code invalid
        %% This path leads to specific error handling (see Error Handling diagram)
    end
Loading

File-Level Changes

Change Details Files
Refactor code execution services
  • Converted CodeDispatch, GodboltService, and WandboxService to use typed abstract methods with detailed docstrings
  • Moved compiler mappings into GODBOLT_COMPILERS/WANDBOX_COMPILERS constants and added a 'ts' alias for TypeScript
  • Enhanced output trimming: removed header lines for Godbolt and filtered out Nim debug messages in Wandbox
tux/cogs/utility/run.py
Overhaul Run cog's 'run' command logic
  • Extracted code parsing, service determination, embed construction, and close-button view into private helper methods
  • Replaced the global error handler with specific exceptions (MissingCodeError, InvalidCodeFormatError, UnsupportedLanguageError, CompilationError)
  • Integrated a loading reaction (LOADING_REACTION constant) and ensured proper reaction cleanup
tux/cogs/utility/run.py
Introduce structured code execution exceptions
  • Defined MissingCodeError, InvalidCodeFormatError, UnsupportedLanguageError, and CompilationError in the exceptions module
  • Mapped these new exceptions to user-friendly messages in the central error handler
tux/utils/exceptions.py
tux/handlers/error.py
Include Content-Type header in Wandbox API requests
  • Added JSON 'Content-Type' header to the HTTP POST in the Wandbox wrapper
tux/wrappers/wandbox.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@HikariNee HikariNee closed this Jun 3, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @HikariNee - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 97 to 98
if (
temp["compiler_error"] != "" and self.compiler_map.get("nim") != lang
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Incorrect Nim language check in compiler error condition

self.compiler_map.get("nim") returns a version string, not the language key. Compare lang directly to "nim" instead (e.g., lang != "nim").

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lang is always the compiler name, the check will fail.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’re absolutely right—since lang already holds the compiler key ("nim"), comparing against self.compiler_map.get("nim") (which is a version string) will never be false and Nim errors will still slip through. Let’s just compare lang directly to "nim". For example:

-        if (
-            temp["compiler_error"] != "" and self.compiler_map.get("nim") != lang
-        ):
+        # treat Nim’s debug messages as non-errors
+        if temp["compiler_error"] != "" and lang != "nim":
             return temp["compiler_error"]

Or even more succinctly:

if temp["compiler_error"] and lang != "nim":
    return temp["compiler_error"]

That should properly skip Nim’s debug output from being treated as a “compiler_error” while still catching real errors for all other languages. Don’t forget to add (or update) a test case for "nim" so we can be sure we’re filtering its debug noise but still surfacing actual compilation failures.

@HikariNee HikariNee reopened this Jun 3, 2025
@kzndotsh
Copy link
Contributor

kzndotsh commented Jun 5, 2025

@sourcery-ai review

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @HikariNee - I've reviewed your changes - here's some feedback:

  • Normalize the extracted language (e.g. .lower()) before looking up in GODBOLT_COMPILERS/WANDBOX_COMPILERS to avoid case-sensitivity mismatches.
  • The generic type parameter on discord.ui.Button[discord.ui.View] in _create_close_button_view is not needed and could be removed to avoid potential type errors.
  • You could merge the two compiler maps into a single lookup or shared registry and drive _determine_service from that to eliminate duplication and keep supported languages in sync.
Here's what I looked at during the review
  • 🟡 General issues: 4 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


@staticmethod
def __remove_backticks(st: str) -> str:
def _determine_service(self, language: str) -> str | None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Normalize language string before mapping to services

Normalize the language string (e.g., language = language.lower().strip()) before matching it to WANDBOX_COMPILERS and GODBOLT_COMPILERS to handle variations in user input.

help_text = (
"The following languages are currently supported by the `run` command:\n"
f"```{languages_text}\n```\n\n"
"Please use triple backticks and provide syntax highlighting like below:\n"
'```\n`\u200b``python\nprint("Hello, World!")\n`\u200b``\n```\n'
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Fix code block quoting in supported languages help

Use \n{languages_text}\n to ensure the list is displayed as code content, not as a language specifier.

Suggested change
help_text = (
"The following languages are currently supported by the `run` command:\n"
f"```{languages_text}\n```\n\n"
"Please use triple backticks and provide syntax highlighting like below:\n"
'```\n`\u200b``python\nprint("Hello, World!")\n`\u200b``\n```\n'
)
help_text = (
"The following languages are currently supported by the `run` command:\n"
f"```\n{languages_text}\n```\n\n"
"Please use triple backticks and provide syntax highlighting like below:\n"
'```\n`\u200b``python\nprint("Hello, World!")\n`\u200b``\n```\n'
)

Comment on lines +280 to +278
if program_output := result.get("program_output"):
output_parts.append(str(program_output))

return " ".join(output_parts).strip() if output_parts else None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Preserve newlines when joining Wandbox output parts

Using spaces to join output_parts removes line breaks from multiline outputs. Use '\n'.join(output_parts) to preserve the original formatting.

Suggested change
if program_output := result.get("program_output"):
output_parts.append(str(program_output))
return " ".join(output_parts).strip() if output_parts else None
if program_output := result.get("program_output"):
output_parts.append(str(program_output))
return "\n".join(output_parts).strip() if output_parts else None

return cleaned_code.split("\n").pop(0), "\n".join(cleaned_code.splitlines()[1:])

async def send_embedded_reply(self, ctx: commands.Context[Tux], output: str, lang: str, is_wandbox: bool) -> None:
# sourcery skip: assign-if-exp, reintroduce-else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Unused skip comment (unused-skip-comment)

HikariNee and others added 7 commits June 5, 2025 23:32
… issues with Javascript, Typescript and Pascal.
Introduce new exceptions for code execution errors, including
MissingCodeError, InvalidCodeFormatError, UnsupportedLanguageError,
and CompilationError. These exceptions provide specific feedback
to users and are integrated into the error handling configuration
to log and optionally send certain errors to Sentry for monitoring.

Enhancing error handling for code execution improves user experience
by providing clear feedback on what went wrong and allows for better
monitoring of issues related to code execution, aiding in debugging
and improving system reliability.
… and documentation

Add comprehensive docstrings to functions and classes for better
understanding and maintainability. Introduce custom exceptions for
specific error scenarios like missing code, invalid format, unsupported
language, and compilation errors. Refactor code to improve readability
and maintainability by using helper functions and constants. Enhance
user feedback with detailed error messages and usage instructions.

These changes improve the robustness and user experience of the code
execution cog by providing clear error messages and documentation,
making it easier for users to understand how to use the feature and for
developers to maintain and extend the code.
@cursor
Copy link

cursor bot commented Jun 6, 2025

🚨 BugBot failed to run

Remote branch not found for this Pull Request. It may have been merged or deleted (requestId: serverGenReqId_2f12ad1b-2b96-4d24-9cef-515670c373cc).

@kzndotsh kzndotsh merged commit bb4f1f3 into allthingslinux:main Jun 6, 2025
7 checks passed
@sentry
Copy link

sentry bot commented Jun 9, 2025

Suspect Issues

This pull request was deployed and Sentry observed the following issues:

  • ‼️ ReadTimeout: The read operation timed out CogLoader Setup View Issue
  • ‼️ HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body CogLoader Setup View Issue

Did you find this useful? React with a 👍 or 👎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants