Skip to content

3.2.4#989

Merged
EstrellaXD merged 7 commits into
mainfrom
3.2-dev
Feb 24, 2026
Merged

3.2.4#989
EstrellaXD merged 7 commits into
mainfrom
3.2-dev

Conversation

@EstrellaXD
Copy link
Copy Markdown
Owner

@EstrellaXD EstrellaXD commented Feb 23, 2026

Summary

Test plan

  • Backend tests: 679 passed
  • WebUI tests: passed
  • CI: all checks green
  • Verified qBittorrent HTTPS connection with self-signed cert

Generated with /ship

EstrellaXD and others added 2 commits February 23, 2026 14:21
Allow users to drag bangumi cards from the "Unknown" section into weekday
columns in the calendar view. Manual assignments are locked so calendar
refresh from Bangumi.tv doesn't overwrite them. A reset button lets users
unlock and send cards back to Unknown.

Backend:
- Add weekday_locked field to Bangumi model (migration v9)
- Add PATCH /api/v1/bangumi/{id}/weekday endpoint
- Skip locked items in refresh_calendar()

Frontend:
- Add vuedraggable for smooth drag-and-drop
- Pin indicator and unpin button on manually-assigned cards
- Drop zone highlighting during drag
- i18n strings for drag/pin/unpin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
auto-bangumi Ready Ready Preview, Comment Feb 24, 2026 6:53pm

Copy link
Copy Markdown

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 pull request implements two major features for release 3.2.4: configurable security controls and calendar drag-and-drop functionality for manual bangumi scheduling.

Changes:

  • Adds a comprehensive Security configuration model supporting IP whitelists (login and MCP) and bearer token authentication for both login and MCP endpoints
  • Implements calendar drag-and-drop to manually assign bangumi to weekdays with a locking mechanism to prevent calendar refresh from overwriting manual assignments
  • Refactors authentication flow to support three authentication methods: DEV bypass, bearer tokens, and JWT cookies

Reviewed changes

Copilot reviewed 36 out of 40 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
backend/src/module/models/config.py Adds Security model with login/MCP whitelists and tokens; refactors env var expansion
backend/src/module/mcp/security.py Renames LocalNetworkMiddleware to McpAccessMiddleware; adds configurable CIDR whitelist and bearer token auth
backend/src/module/security/api.py Adds check_login_ip dependency and bearer token bypass in get_current_user
backend/src/module/api/auth.py Refactors JWT issuance into _issue_token helper; adds login IP check dependency
backend/src/module/api/config.py Fixes sanitization to only mask string values, preventing integer masking
backend/src/module/api/bangumi.py Adds PATCH /bangumi/{id}/weekday endpoint for manual weekday assignment
backend/src/module/database/bangumi.py Adds set_weekday method to handle weekday locking
backend/src/module/database/combine.py Adds migration v9 for weekday_locked column
backend/src/module/models/bangumi.py Adds weekday_locked field to Bangumi and BangumiUpdate models
backend/src/module/manager/torrent.py Skips locked bangumi in calendar refresh
backend/src/module/conf/const.py Adds security defaults with private network MCP whitelist
backend/src/module/conf/config.py Adds security section migration in _migrate_old_config
backend/src/test/* Adds 101 new tests covering security, auth, config, and downloader modules
webui/types/config.ts Adds Security interface; removes deprecated RssParser fields
webui/types/bangumi.ts Adds weekday_locked to BangumiRule type
webui/src/pages/index/calendar.vue Implements drag-and-drop with vuedraggable; adds pin/unpin UI
webui/src/components/setting/config-security.vue New component for security settings configuration
webui/src/store/bangumi.ts Adds setWeekday action
webui/src/api/bangumi.ts Adds setWeekday API client method
webui/src/i18n/*.json Adds translations for drag-and-drop and security features
webui/package.json Adds vuedraggable dependency
backend/pyproject.toml Bumps version to 3.2.4
CHANGELOG.md Documents all changes
Files not reviewed (1)
  • webui/pnpm-lock.yaml: Language not supported

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

Comment on lines +348 to +383
@router.patch(
path="/{bangumi_id}/weekday",
response_model=APIResponse,
dependencies=[Depends(get_current_user)],
)
async def set_weekday(bangumi_id: int, request: SetWeekdayRequest):
"""Manually set the broadcast weekday for a bangumi."""
if request.weekday is not None and not (0 <= request.weekday <= 6):
return JSONResponse(
status_code=400,
content={
"status": False,
"msg_en": "Weekday must be 0-6 (Mon-Sun) or null.",
"msg_zh": "星期必须是 0-6(周一至周日)或空。",
},
)
with Database() as db:
success = db.bangumi.set_weekday(bangumi_id, request.weekday)
if success:
action = f"weekday {request.weekday}" if request.weekday is not None else "unknown"
return JSONResponse(
status_code=200,
content={
"status": True,
"msg_en": f"Set bangumi to {action}.",
"msg_zh": f"已设置放送日为 {action}。",
},
)
return JSONResponse(
status_code=404,
content={
"status": False,
"msg_en": f"Bangumi {bangumi_id} not found.",
"msg_zh": f"未找到番剧 {bangumi_id}。",
},
)
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The new set_weekday API endpoint (PATCH /bangumi/{id}/weekday) lacks automated test coverage. While 101 new tests were added to this PR, none specifically test this new endpoint's behavior including validation of weekday range (0-6), null handling, success/failure responses, and database state updates. Adding test coverage would help ensure this critical user-facing feature works correctly.

Copilot uses AI. Check for mistakes.
if isinstance(v, dict):
result[k] = _sanitize_dict(v)
elif any(s in k.lower() for s in _SENSITIVE_KEYS):
elif isinstance(v, str) and any(s in k.lower() for s in _SENSITIVE_KEYS):
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The sanitization function now only masks string values, which is correct. However, there's a potential issue: the function checks if the value v is a string, but if a sensitive key has a non-string value (like a list of tokens), those values won't be masked. For the Security model, login_tokens and mcp_tokens are lists of strings, not strings themselves, so they will not be sanitized and will be exposed in the API response.

Copilot uses AI. Check for mistakes.
Comment on lines +135 to +141
async function onDropToDay(dayIndex: number, evt: any) {
if (evt.added) {
const group: BangumiGroup = evt.added.element;
for (const rule of group.rules) {
await setWeekday(rule.id, dayIndex);
}
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The onDropToDay function uses sequential await calls in a for loop, which can be slow when a group contains multiple rules. Consider using Promise.all() to set the weekday for all rules concurrently, improving performance.

Copilot uses AI. Check for mistakes.
Comment on lines +268 to +275
<button
v-if="group.primary.weekday_locked"
class="calendar-unpin-btn"
:title="$t('calendar.unpin')"
@click="onUnpin(group, $event)"
>
&times;
</button>
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The unpin button lacks keyboard accessibility. It only has a click handler but no keyboard event handlers (like @keydown.enter or @keydown.space). Users relying on keyboard navigation won't be able to trigger the unpin action. Add keyboard event handlers to make this button accessible.

Copilot uses AI. Check for mistakes.
Comment on lines +268 to +275
<button
v-if="group.primary.weekday_locked"
class="calendar-unpin-btn"
:title="$t('calendar.unpin')"
@click="onUnpin(group, $event)"
>
&times;
</button>
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The unpin button lacks an accessible label (aria-label). While it has a title attribute for tooltips, screen readers need an explicit aria-label to announce the button's purpose to users. Add aria-label with a descriptive label like "Unpin bangumi from this day".

Copilot uses AI. Check for mistakes.
Comment on lines +144 to +149
async function onUnpin(group: BangumiGroup, event: Event) {
event.stopPropagation();
for (const rule of group.rules) {
await setWeekday(rule.id, null);
}
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The onUnpin function also uses sequential await calls in a for loop. Similar to onDropToDay, consider using Promise.all() to reset the weekday for all rules concurrently.

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +92
async function setWeekday(bangumiId: number, weekday: number | null) {
await apiBangumi.setWeekday(bangumiId, weekday);
const item = bangumi.value.find((b) => b.id === bangumiId);
if (item) {
item.air_weekday = weekday;
item.weekday_locked = weekday !== null;
}
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The setWeekday function doesn't handle errors from the API call. If apiBangumi.setWeekday fails (e.g., due to network error or invalid bangumi_id), the local state will not be updated but there's no error notification to the user. The drag-and-drop UI will appear to have succeeded even though the backend update failed. Consider wrapping the API call in a try-catch block and showing an error notification on failure.

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +40
def clear_network_cache():
"""Clear the parsed network cache (call after config reload)."""
_parse_network.cache_clear()
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The clear_network_cache function is defined but never called. After config reload (e.g., in config.py's update_config), the LRU cache should be cleared to ensure stale CIDR parsing results don't persist. Without this, changes to mcp_whitelist won't take effect until the server restarts.

Copilot uses AI. Check for mistakes.
Titles like "29 岁单身冒险家的日常" cause the regex to match the leading
number as episode, leaving title_raw as None. This cascades into storing
null aliases and crashing match_torrent with TypeError.

- Fall back to title_jp when title_en and title_zh are both None
- Return None from raw_parser when no title can be extracted
- Reject None/empty aliases in add_title_alias
- Filter null values from parsed title_aliases JSON
- Skip None title_raw in get_all_title_patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 tests covering the full bug chain:
- raw_parser misparses leading number as episode
- TitleParser.raw_parser returns None for unparseable titles
- add_title_alias rejects None and empty string
- _get_aliases_list filters null values from JSON
- get_all_title_patterns skips None title_raw
- match_torrent and match_list handle corrupted data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…#910, #773)

Add _fallback_parse() tried when TITLE_RE.match() returns None, using two
regex patterns to extract episode numbers from formats the main regex misses:
- digits before [ bracket (issues #876, #910)
- compound [02(57)] format (issue #773)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@EstrellaXD EstrellaXD changed the title feat: release 3.2.4 - security config, calendar drag-and-drop release 3.2.4 Feb 24, 2026
EstrellaXD and others added 2 commits February 24, 2026 19:44
Prevent memory leaks by ensuring the search EventSource connection is
closed when the modal unmounts and setTimeout handles are cleared in
copy-to-clipboard flows across modal components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…on (#923)

- Decouple HTTPS scheme selection from TLS certificate verification:
  `verify=False` always, since self-signed certs are the norm for
  home-server/NAS/Docker qBittorrent setups
- Bump connect timeout from 3.1s to 5.0s for slow TLS handshakes
- Add actionable error messages when HTTPS connection fails
- Fix `continue` → `break` bug in torrents_rename_file verification loop
- Consolidate json imports to top-level
- Add 31 unit tests for QbDownloader constructor, auth, and error handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@EstrellaXD EstrellaXD changed the title release 3.2.4 3.2.4 Feb 24, 2026
@EstrellaXD EstrellaXD merged commit e1b90c9 into main Feb 24, 2026
16 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