Skip to content

Release 20251211 - /project 全部结果并排序#17

Merged
MistEO merged 2 commits intomainfrom
dev
Dec 11, 2025
Merged

Release 20251211 - /project 全部结果并排序#17
MistEO merged 2 commits intomainfrom
dev

Conversation

@MistEO
Copy link
Copy Markdown
Contributor

@MistEO MistEO commented Dec 11, 2025

Summary by Sourcery

在管理员通知端点中处理无效的 JSON 负载,并调整项目查询结果的排序以优先显示特定的 type_id

Bug Fixes:

  • /notify_admin 端点接收到无效的 JSON 请求体时,返回 400 错误。

Enhancements:

  • /project 查询中返回所有缓存的项目,并通过排序使具有请求 type_id 的条目优先显示。
Original summary in English

Summary by Sourcery

Handle invalid JSON payloads in the admin notification endpoint and adjust project query results ordering to prioritize a specific type_id.

Bug Fixes:

  • Return a 400 error when the /notify_admin endpoint receives an invalid JSON body.

Enhancements:

  • Return all cached projects from the /project query while sorting them to show entries with the requested type_id first.

Copilot AI review requested due to automatic review settings December 11, 2025 10:47
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Dec 11, 2025

审阅者指南(在小型 PR 上默认折叠)

审阅者指南

为管理员通知端点新增了健壮的 JSON 解析/错误处理,并修改了项目列表逻辑:返回所有项目,但在排序时优先显示 type_id 与请求匹配的项目。

notify_admin 的 JSON 解析和错误处理时序图

sequenceDiagram
    actor Client
    participant APIRouter as APIRouter_notify_admin
    participant Endpoint as notify_admin
    participant Request as Request
    participant Logger as logger
    participant Settings as settings
    participant HTTPException as HTTPException

    Client->>APIRouter: POST /notify_admin
    APIRouter->>Endpoint: notify_admin(request)
    Endpoint->>Request: json()
    alt valid_json
        Request-->>Endpoint: body
        Endpoint->>Logger: info(str(body))
        Endpoint->>Settings: read notify_admin_url
        alt notify_admin_url_not_configured
            Endpoint-->>Client: HTTP 200 { ec: 200, msg: disabled }
        else notify_admin_url_configured
            Endpoint->>ExternalService: POST notify_admin_url with body
            ExternalService-->>Endpoint: response
            Endpoint-->>Client: HTTP 200 { ec: 200 }
        end
    else invalid_json
        Request-->>Endpoint: raise Exception
        Endpoint->>Logger: error(notify_admin invalid json)
        Endpoint->>HTTPException: construct 400 Invalid JSON
        HTTPException-->>Client: HTTP 400 { detail: Invalid JSON }
    end
Loading

query_project 返回所有项目并按 type_id 匹配情况排序的流程图

flowchart TD
    A_start["Client calls GET /project with type_id"] --> B_loadCache["Load project_cache[0]"]
    B_loadCache --> C_iterate["Iterate over all projects p in project_cache[0]"]
    C_iterate --> D_buildItem["For each p build dict { name, github, desc, tags, download }"]
    D_buildItem --> E_collect["Collect list data of all project dicts"]
    E_collect --> F_sort["Sort data with key: p.type_id != type_id (matches first)"]
    F_sort --> G_response["Return { ec: 200, data } with all projects ordered"]
Loading

文件级变更

变更 详情 文件
为格式错误的 notify_admin 请求添加防御性 JSON 解析和明确的 400 错误响应。
  • request.json() 包裹在 try/except 中以捕获 JSON 解析错误。
  • 在响应之前记录格式错误的 JSON 日志,并包含上下文信息。
  • 在解析失败时抛出带有清晰 'Invalid JSON' 详情的 HTTPException(400)
src/notify_admin/__init__.py
从缓存中返回所有项目,同时在排序时优先展示 type_id 与请求匹配的项目。
  • 用排序替代按 type_id 过滤,将 type_id 匹配的条目移动到列表前面。
  • 保留现有的项目到字典的映射结构,只改变遍历顺序。
src/project/__init__.py

技巧与命令

与 Sourcery 交互

  • 触发新审查: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 根据审查评论生成 GitHub Issue: 通过回复某条审查评论,请求 Sourcery 从该评论创建一个 issue。你也可以直接回复该评论 @sourcery-ai issue 来创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title 来随时(重新)生成标题。
  • 生成拉取请求摘要: 在拉取请求正文任意位置写上 @sourcery-ai summary,即可在你想要的位置随时生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary 来随时(重新)生成摘要。
  • 生成审阅者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 一次性解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。适用于你已经处理完所有评论且不希望再看到它们时。
  • 忽略所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。特别适用于你希望从一次全新的审查开始——别忘了再评论 @sourcery-ai review 来触发新的审查!

自定义你的体验

访问你的 控制面板 以:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审阅者指南等。
  • 更改审查语言。
  • 添加、移除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds robust JSON parsing/error handling to the admin notification endpoint and changes project listing to include all projects while ordering those matching the requested type_id first.

Sequence diagram for notify_admin JSON parsing and error handling

sequenceDiagram
    actor Client
    participant APIRouter as APIRouter_notify_admin
    participant Endpoint as notify_admin
    participant Request as Request
    participant Logger as logger
    participant Settings as settings
    participant HTTPException as HTTPException

    Client->>APIRouter: POST /notify_admin
    APIRouter->>Endpoint: notify_admin(request)
    Endpoint->>Request: json()
    alt valid_json
        Request-->>Endpoint: body
        Endpoint->>Logger: info(str(body))
        Endpoint->>Settings: read notify_admin_url
        alt notify_admin_url_not_configured
            Endpoint-->>Client: HTTP 200 { ec: 200, msg: disabled }
        else notify_admin_url_configured
            Endpoint->>ExternalService: POST notify_admin_url with body
            ExternalService-->>Endpoint: response
            Endpoint-->>Client: HTTP 200 { ec: 200 }
        end
    else invalid_json
        Request-->>Endpoint: raise Exception
        Endpoint->>Logger: error(notify_admin invalid json)
        Endpoint->>HTTPException: construct 400 Invalid JSON
        HTTPException-->>Client: HTTP 400 { detail: Invalid JSON }
    end
Loading

Flow diagram for query_project returning all projects ordered by type_id match

flowchart TD
    A_start["Client calls GET /project with type_id"] --> B_loadCache["Load project_cache[0]"]
    B_loadCache --> C_iterate["Iterate over all projects p in project_cache[0]"]
    C_iterate --> D_buildItem["For each p build dict { name, github, desc, tags, download }"]
    D_buildItem --> E_collect["Collect list data of all project dicts"]
    E_collect --> F_sort["Sort data with key: p.type_id != type_id (matches first)"]
    F_sort --> G_response["Return { ec: 200, data } with all projects ordered"]
Loading

File-Level Changes

Change Details Files
Add defensive JSON parsing and explicit 400 error response for malformed notify_admin requests.
  • Wrap request.json() in a try/except to catch JSON parsing errors.
  • Log malformed JSON errors with context before responding.
  • Raise HTTPException(400) with a clear 'Invalid JSON' detail when parsing fails.
src/notify_admin/__init__.py
Return all projects from the cache while prioritizing those with the requested type_id in the ordering.
  • Replace filtering by type_id with sorting that moves matching type_id entries to the front.
  • Preserve the existing project-to-dict mapping structure, only changing the iteration order.
src/project/__init__.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

Copy link
Copy Markdown

@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 there - 我已经审查了你的更改,这里是一些反馈:

  • notify_admin 中,建议捕获更具体的 JSON 解析异常(例如 JSONDecodeErrorValueError),而不是捕获 Exception,以避免掩盖无关错误并让调试更容易。
  • query_project 中新的排序逻辑(sorted(project_cache[0], key=lambda p: p.type_id != type_id))只能保证匹配 type_id 的条目排在前面;如果你需要在分组内或跨分组保持稳定或更有意义的顺序,建议添加一个次级排序键(例如名称、id 或创建时间)。
给 AI 代理的提示
请根据本次代码审查中的评论进行修改:

## 总体评论
-`notify_admin` 中,建议捕获更具体的 JSON 解析异常(例如 `JSONDecodeError``ValueError`),而不是捕获 `Exception`,以避免掩盖无关错误并让调试更容易。
- `query_project` 中新的排序逻辑(`sorted(project_cache[0], key=lambda p: p.type_id != type_id)`)只能保证匹配 `type_id` 的条目排在前面;如果你需要在分组内或跨分组保持稳定或更有意义的顺序,建议添加一个次级排序键(例如名称、id 或创建时间)。

## 单独评论

### 评论 1
<location> `src/notify_admin/__init__.py:11-15` </location>
<code_context>
 @router.post("/notify_admin")
 async def notify_admin(request: Request):
-    body = await request.json()
+    try:
+        body = await request.json()
+    except Exception as e:
+        logger.error(f"notify_admin invalid json: {e}")
+        raise HTTPException(status_code=400, detail="Invalid JSON")
+
     logger.info(str(body))
</code_context>

<issue_to_address>
**suggestion (bug_risk):** 在解析 JSON 时收窄异常类型,而不是捕获所有 Exception。

在这里捕获 `Exception` 也会把无关的错误(例如连接问题、内部故障)一起吞掉,并统一标记为 "Invalid JSON",从而掩盖真正的问题。更好的做法是只捕获 `request.json()` 可能抛出的特定 JSON 解析异常(例如 `JSONDecodeError` / `ValueError`,或者框架自己的异常类型),让其他异常继续向上传播为 500,这样只有真正的解析错误才会返回 400。

建议实现方式:

```python
from json import JSONDecodeError

from fastapi import Request, APIRouter, HTTPException
from aiohttp import ClientSession
from loguru import logger

```

```python
@router.post("/notify_admin")
async def notify_admin(request: Request):
    try:
        body = await request.json()
    except JSONDecodeError as e:
        logger.error(f"notify_admin invalid json: {e}")
        raise HTTPException(status_code=400, detail="Invalid JSON")

```
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得我们的审查有帮助,请考虑分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English

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

  • In notify_admin, consider catching the specific JSON parse exception (e.g. JSONDecodeError or ValueError) instead of Exception to avoid masking unrelated errors and make debugging easier.
  • The new sorting in query_project (sorted(project_cache[0], key=lambda p: p.type_id != type_id)) only guarantees that matching type_id items come first; if a stable or more meaningful order within and across groups is important, consider adding a secondary sort key (e.g. name, id, or created time).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `notify_admin`, consider catching the specific JSON parse exception (e.g. `JSONDecodeError` or `ValueError`) instead of `Exception` to avoid masking unrelated errors and make debugging easier.
- The new sorting in `query_project` (`sorted(project_cache[0], key=lambda p: p.type_id != type_id)`) only guarantees that matching `type_id` items come first; if a stable or more meaningful order within and across groups is important, consider adding a secondary sort key (e.g. name, id, or created time).

## Individual Comments

### Comment 1
<location> `src/notify_admin/__init__.py:11-15` </location>
<code_context>
 @router.post("/notify_admin")
 async def notify_admin(request: Request):
-    body = await request.json()
+    try:
+        body = await request.json()
+    except Exception as e:
+        logger.error(f"notify_admin invalid json: {e}")
+        raise HTTPException(status_code=400, detail="Invalid JSON")
+
     logger.info(str(body))
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Narrow the exception type when parsing JSON instead of catching all Exceptions.

Catching `Exception` here will also swallow unrelated errors (e.g., connection issues, internal failures) and mislabel them as "Invalid JSON", which obscures real problems. Instead, catch only the specific JSON parsing exception(s) that `request.json()` can raise (e.g., `JSONDecodeError` / `ValueError` or the framework’s own type) and let other exceptions propagate as 500s so only true parse errors return a 400.

Suggested implementation:

```python
from json import JSONDecodeError

from fastapi import Request, APIRouter, HTTPException
from aiohttp import ClientSession
from loguru import logger

```

```python
@router.post("/notify_admin")
async def notify_admin(request: Request):
    try:
        body = await request.json()
    except JSONDecodeError as e:
        logger.error(f"notify_admin invalid json: {e}")
        raise HTTPException(status_code=400, detail="Invalid JSON")

```
</issue_to_address>

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 +11 to +15
try:
body = await request.json()
except Exception as e:
logger.error(f"notify_admin invalid json: {e}")
raise HTTPException(status_code=400, detail="Invalid JSON")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): 在解析 JSON 时收窄异常类型,而不是捕获所有 Exception。

在这里捕获 Exception 也会把无关的错误(例如连接问题、内部故障)一起吞掉,并统一标记为 "Invalid JSON",从而掩盖真正的问题。更好的做法是只捕获 request.json() 可能抛出的特定 JSON 解析异常(例如 JSONDecodeError / ValueError,或者框架自己的异常类型),让其他异常继续向上传播为 500,这样只有真正的解析错误才会返回 400。

建议实现方式:

from json import JSONDecodeError

from fastapi import Request, APIRouter, HTTPException
from aiohttp import ClientSession
from loguru import logger
@router.post("/notify_admin")
async def notify_admin(request: Request):
    try:
        body = await request.json()
    except JSONDecodeError as e:
        logger.error(f"notify_admin invalid json: {e}")
        raise HTTPException(status_code=400, detail="Invalid JSON")
Original comment in English

suggestion (bug_risk): Narrow the exception type when parsing JSON instead of catching all Exceptions.

Catching Exception here will also swallow unrelated errors (e.g., connection issues, internal failures) and mislabel them as "Invalid JSON", which obscures real problems. Instead, catch only the specific JSON parsing exception(s) that request.json() can raise (e.g., JSONDecodeError / ValueError or the framework’s own type) and let other exceptions propagate as 500s so only true parse errors return a 400.

Suggested implementation:

from json import JSONDecodeError

from fastapi import Request, APIRouter, HTTPException
from aiohttp import ClientSession
from loguru import logger
@router.post("/notify_admin")
async def notify_admin(request: Request):
    try:
        body = await request.json()
    except JSONDecodeError as e:
        logger.error(f"notify_admin invalid json: {e}")
        raise HTTPException(status_code=400, detail="Invalid JSON")

Copy link
Copy Markdown
Contributor

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 release updates the /project endpoint to return all projects with sorted results and adds JSON parsing error handling to the /notify_admin endpoint.

  • Changed /project endpoint from filtering by type_id to returning all projects sorted by type_id match
  • Added error handling for invalid JSON requests in /notify_admin endpoint

Reviewed changes

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

File Description
src/project/init.py Modified query logic to return all projects sorted by type_id match instead of filtering
src/notify_admin/init.py Added try-catch block and HTTPException for invalid JSON request handling

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

}
for p in project_cache[0]
if p.type_id == type_id
for p in sorted(project_cache[0], key=lambda p: p.type_id != type_id)
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

The sorting logic change has altered the behavior of the endpoint. Previously, the code filtered projects to only return those matching the specified type_id. Now it returns ALL projects but sorts them so matching projects appear first. This changes the API response to include projects of all types, which may be a breaking change for API consumers expecting only filtered results. Consider whether this behavior change is intentional and documented.

Suggested change
for p in sorted(project_cache[0], key=lambda p: p.type_id != type_id)
for p in project_cache[0] if p.type_id == type_id

Copilot uses AI. Check for mistakes.
body = await request.json()
try:
body = await request.json()
except Exception as e:
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

Using a broad Exception handler can mask specific errors and make debugging difficult. Consider catching more specific exceptions like JSONDecodeError from the json module, which is the actual exception raised when JSON parsing fails.

Copilot uses AI. Check for mistakes.
@MistEO MistEO merged commit 5fc4e58 into main Dec 11, 2025
8 checks passed
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