Skip to content

Conversation

@JacobCoffee
Copy link
Owner

@JacobCoffee JacobCoffee commented Jan 22, 2026

Summary

  • Resolves Enhancement: Guild config helper #88 - Add get_by_guild_id() helper methods to config services
  • Reduces duplication in controller endpoints
  • Enables usage outside of routes (e.g., from bot service)

Changes

Service Method Added
GitHubConfigService get_by_guild_id(guild_id: int) -> GitHubConfig
SOTagsConfigService get_by_guild_id(guild_id: int) -> SOTagsConfig
AllowedUsersConfigService get_by_guild_id(guild_id: int) -> AllowedUsersConfig
ForumConfigService get_by_guild_id(guild_id: int) -> ForumConfig

Each method:

  • Takes a Discord guild ID as parameter
  • Returns the corresponding config model
  • Raises NotFoundError if no config exists

Test plan

  • 8 new tests for get_by_guild_id methods (success + not found cases)
  • All 1133 tests pass
  • Existing controller tests still pass

🤖 Generated with Claude Code

Summary by Sourcery

Add guild ID-based lookup helpers to guild configuration services and update controllers and tests to use and validate them.

New Features:

  • Provide get_by_guild_id helper methods on GitHub, StackOverflow tags, allowed users, and forum config services for retrieving configs by Discord guild ID.

Enhancements:

  • Refactor guild configuration controllers to use the new service helper methods instead of direct repository-style lookups.

Tests:

  • Add unit tests covering success and not-found scenarios for the new get_by_guild_id helpers on all guild configuration services.

Resolves GH #88 - Add helper methods to reduce duplication and allow
usage outside of routes.

- Add get_by_guild_id() to GitHubConfigService, SOTagsConfigService,
  AllowedUsersConfigService, and ForumConfigService
- Update controller endpoints to use the new helpers
- Add 8 tests for the new methods (success and not found cases)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 22, 2026 14:14
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 22, 2026

Reviewer's Guide

Adds typed get_by_guild_id helper methods to guild-related config services, refactors controllers to use them instead of raw get(..., id_attribute='guild_id'), and introduces unit tests validating success and not-found behavior for each service.

Sequence diagram for guild GitHub config retrieval via get_by_guild_id

sequenceDiagram
    actor Client
    participant GuildsController
    participant GitHubConfigService
    participant SQLAlchemyAsyncRepositoryService
    participant GitHubConfigRepository

    Client->>GuildsController: GET /guilds/{guild_id}/github/config
    GuildsController->>GitHubConfigService: get_by_guild_id(guild_id)
    GitHubConfigService->>SQLAlchemyAsyncRepositoryService: get(guild_id, id_attribute=guild_id)
    SQLAlchemyAsyncRepositoryService->>GitHubConfigRepository: fetch_by_guild_id(guild_id)

    alt config exists
        GitHubConfigRepository-->>SQLAlchemyAsyncRepositoryService: GitHubConfig
        SQLAlchemyAsyncRepositoryService-->>GitHubConfigService: GitHubConfig
        GitHubConfigService-->>GuildsController: GitHubConfig
        GuildsController-->>Client: 200 GitHubConfigSchema
    else config not found
        GitHubConfigRepository-->>SQLAlchemyAsyncRepositoryService: None
        SQLAlchemyAsyncRepositoryService-->>GitHubConfigService: NotFoundError
        GitHubConfigService-->>GuildsController: NotFoundError
        GuildsController-->>Client: 404 error response
    end
Loading

Class diagram for new get_by_guild_id helpers in guild config services

classDiagram
    class SQLAlchemyAsyncRepositoryService {
        +async get(id: int, id_attribute: str) ConfigModel
    }

    class GitHubConfigService {
        +repository_type
        +match_fields
        +async get_by_guild_id(guild_id: int) GitHubConfig
        +async to_model(data: ModelDictT_GitHubConfig, operation: str) GitHubConfig
    }

    class SOTagsConfigService {
        +repository_type
        +match_fields
        +async get_by_guild_id(guild_id: int) SOTagsConfig
        +async to_model(data: ModelDictT_SOTagsConfig, operation: str) SOTagsConfig
    }

    class AllowedUsersConfigService {
        +repository_type
        +match_fields
        +async get_by_guild_id(guild_id: int) AllowedUsersConfig
        +async to_model(data: ModelDictT_AllowedUsersConfig, operation: str) AllowedUsersConfig
    }

    class ForumConfigService {
        +repository_type
        +match_fields
        +async get_by_guild_id(guild_id: int) ForumConfig
        +async to_model(data: ModelDictT_ForumConfig, operation: str) ForumConfig
    }

    class GitHubConfig
    class SOTagsConfig
    class AllowedUsersConfig
    class ForumConfig

    class ModelDictT_GitHubConfig
    class ModelDictT_SOTagsConfig
    class ModelDictT_AllowedUsersConfig
    class ModelDictT_ForumConfig

    SQLAlchemyAsyncRepositoryService <|-- GitHubConfigService
    SQLAlchemyAsyncRepositoryService <|-- SOTagsConfigService
    SQLAlchemyAsyncRepositoryService <|-- AllowedUsersConfigService
    SQLAlchemyAsyncRepositoryService <|-- ForumConfigService

    GitHubConfigService --> GitHubConfig
    SOTagsConfigService --> SOTagsConfig
    AllowedUsersConfigService --> AllowedUsersConfig
    ForumConfigService --> ForumConfig
Loading

File-Level Changes

Change Details Files
Introduce get_by_guild_id helper on all guild config services to encapsulate guild-id-based lookup and reuse.
  • Add async get_by_guild_id(guild_id: int) method to GitHubConfigService that delegates to self.get with id_attribute='guild_id'.
  • Add async get_by_guild_id(guild_id: int) method to SOTagsConfigService that delegates to self.get with id_attribute='guild_id'.
  • Add async get_by_guild_id(guild_id: int) method to AllowedUsersConfigService that delegates to self.get with id_attribute='guild_id'.
  • Add async get_by_guild_id(guild_id: int) method to ForumConfigService that delegates to self.get with id_attribute='guild_id'.
  • Document method behavior, including NotFoundError when config for the guild does not exist.
services/api/src/byte_api/domain/guilds/services.py
Refactor guild config controller endpoints to use the new service helpers instead of inlining repository ID-attribute logic.
  • Update get_guild_github_config controller handler to call github_service.get_by_guild_id instead of get(..., id_attribute='guild_id').
  • Update get_guild_sotags_config controller handler to call sotags_service.get_by_guild_id instead of get(..., id_attribute='guild_id').
  • Update get_guild_allowed_users_config controller handler to call allowed_users_service.get_by_guild_id instead of get(..., id_attribute='guild_id').
  • Update get_guild_forum_config controller handler to call forum_service.get_by_guild_id instead of get(..., id_attribute='guild_id').
  • Remove obsolete TODO comment referencing the desire for such a helper.
services/api/src/byte_api/domain/guilds/controllers.py
Add unit tests covering get_by_guild_id success and not-found paths for each config service.
  • Export new test names in all to keep them discoverable and consistent with the module’s explicit exports.
  • For each of GitHubConfigService, SOTagsConfigService, AllowedUsersConfigService, and ForumConfigService, add a success test that sets up a Guild (and User where needed), creates a config, calls get_by_guild_id, and asserts returned fields match the created config.
  • For each of the four services, add a not-found test that uses a non-existent guild ID and asserts NotFoundError is raised.
tests/unit/api/test_guilds_services.py

Assessment against linked issues

Issue Objective Addressed Explanation
#88 Add a reusable helper method on guild config services to retrieve configurations by guild_id instead of duplicating service.get(..., id_attribute="guild_id") calls.
#88 Refactor existing guild config retrieval in controllers to use the new helper method, reducing duplication in route handlers.

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

@railway-app
Copy link

railway-app bot commented Jan 22, 2026

🚅 Deployed to the byte-pr-140 environment in byte

Service Status Web Updated (UTC)
byte ✅ Success (View Logs) Web Jan 22, 2026 at 2:15 pm

@railway-app railway-app bot temporarily deployed to byte / byte-pr-140 January 22, 2026 14:14 Destroyed
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 - I've left some high level feedback:

  • The four get_by_guild_id helpers are identical across services; consider extracting a common helper/mixin (e.g., a base GuildScopedConfigService with a generic get_by_guild_id) to avoid repetition and keep future changes in one place.
  • The new get_by_guild_id tests are very similar across services; you might reduce duplication and make them easier to maintain by parameterizing over service/repository/model details instead of repeating almost identical test bodies.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The four `get_by_guild_id` helpers are identical across services; consider extracting a common helper/mixin (e.g., a base `GuildScopedConfigService` with a generic `get_by_guild_id`) to avoid repetition and keep future changes in one place.
- The new `get_by_guild_id` tests are very similar across services; you might reduce duplication and make them easier to maintain by parameterizing over service/repository/model details instead of repeating almost identical test bodies.

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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds get_by_guild_id() helper methods to four configuration service classes to reduce code duplication and enable usage outside of route handlers, resolving issue #88.

Changes:

  • Added get_by_guild_id() helper methods to GitHubConfigService, SOTagsConfigService, AllowedUsersConfigService, and ForumConfigService
  • Refactored four controller endpoints to use the new helper methods instead of direct get() calls with id_attribute parameter
  • Added comprehensive test coverage with 8 new tests (success and not found cases for each service)

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
services/api/src/byte_api/domain/guilds/services.py Added get_by_guild_id() helper methods to all four config service classes with consistent implementation and documentation
services/api/src/byte_api/domain/guilds/controllers.py Updated four endpoint methods to use the new helper methods and removed the TODO comment
tests/unit/api/test_guilds_services.py Added 8 new unit tests covering success and error cases for all four new helper methods, updated __all__ exports

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link

Documentation preview will be available shortly at https://jacobcoffee.github.io/byte-docs-preview/140

@JacobCoffee
Copy link
Owner Author

After further review, this PR adds unnecessary abstraction.

The get_by_guild_id() methods are just thin wrappers around AdvancedAlchemy's existing service.get(guild_id, id_attribute="guild_id") which already works outside of routes.

The original TODO (#88) was asking for helper methods usable outside routes - but that capability already exists. Adding 4 identical wrapper methods violates DRY and creates maintenance burden.

Closing as unnecessary.

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.

Enhancement: Guild config helper

2 participants