Skip to content

Fix anime-watch-hub#87

Open
zk1tty wants to merge 2 commits intotinyfish-io:mainfrom
zk1tty:main
Open

Fix anime-watch-hub#87
zk1tty wants to merge 2 commits intotinyfish-io:mainfrom
zk1tty:main

Conversation

@zk1tty
Copy link
Contributor

@zk1tty zk1tty commented Mar 19, 2026

I fixed the issues of #86

After

Screenshot 2026-03-19 at 9 37 01 AM Screenshot 2026-03-19 at 9 42 30 AM

Summary by CodeRabbit

Release Notes

  • New Features

    • Enabled script execution and form submission capabilities within embedded streaming content for improved interactivity.
  • Bug Fixes

    • Improved streaming event detection with stricter type validation.
    • Enhanced error handling and status messaging during anime searches.
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9b9811ae-bcc2-43fb-b530-484bd6a3cdd9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

These changes update streaming platform integration by reformatting SSE encoding logic, extending iframe sandbox permissions for script and form execution, and refactoring event-stream parsing logic including updated field references (streaming_url), event types (PROGRESS replacing STATUS), and status-based completion branching.

Changes

Cohort / File(s) Summary
SSE Streaming Endpoint
app/api/check-platform/route.ts
Reformatted SSE controller.enqueue call into single-line expression; no behavior or error-handling changes.
Embedded Content Sandbox
components/platform-card.tsx
Extended iframe sandbox policy to permit script execution and form submission alongside same-origin access.
Event-Stream Parsing Logic
hooks/use-anime-search.ts
Refactored streamed JSON event handling: STREAMING_URL now requires strict type check and reads from data.streaming_url; STATUS events replaced with PROGRESS events using data.purpose; COMPLETE events now branch on data.status === 'failed' with error/success paths; ERROR handling preserved.

Sequence Diagram

sequenceDiagram participant API as Check-Platform API participant Hook as useAnimeSearch Hook participant UI as Platform Component participant Browser as Browser/Iframe API->>Hook: SSE Stream (STREAMING_URL) Note over Hook: Check data.type === 'STREAMING_URL'<br/>Read data.streaming_url Hook->>Hook: Set streamingUrl state API->>Hook: SSE Stream (PROGRESS) Note over Hook: Check data.type === 'PROGRESS'<br/>Read data.purpose Hook->>Hook: Update statusMessage API->>Hook: SSE Stream (COMPLETE) alt data.status === 'failed' Hook->>Hook: Set status='error'<br/>Set statusMessage from error<br/>Clear streamingUrl else success Hook->>Hook: Set status='complete'<br/>Set result from data.result<br/>Clear streamingUrl & statusMessage end Hook->>UI: Provide streamingUrl & status UI->>Browser: Render iframe with<br/>sandbox="allow-same-origin<br/>allow-scripts allow-forms" Browser->>Browser: Execute scripts & forms 
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related Issues

  • Event handling bug + live streaming inside iframe #86: This PR directly addresses the event-parsing schema evolution (STREAMING_URL → data.streaming_url, STATUS → PROGRESS, COMPLETE status branching) and iframe sandbox capability expansion for embedded streaming content.

Poem

🐰 Hop-hop, the sandbox grows wide,
Scripts and forms now fit inside!
Event streams dance with purpose bright,
PROGRESS flows and errors set right—
A streaming burrow, snug and tight! 🎬

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The pull request title "Fix anime-watch-hub" is vague and generic, using only the word "Fix" without specifying what was fixed or which components were changed. Replace with a more specific title that describes the main changes, such as "Fix streaming URL handling and iframe sandbox policy" or "Fix /run-see event handling and live streaming support."
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@zk1tty zk1tty changed the title Fix /run-see event handling bug + live streaming inside iframe Fix anime-watch-hub Mar 19, 2026
@simantak-dabhade
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed. Inline comments: In `@anime-watch-hub/components/platform-card.tsx`: - Around line 69-73: The iframe is rendering agent.streamingUrl directly and uses a permissive sandbox ("allow-same-origin allow-scripts allow-forms"); validate and gate the URL before rendering by enforcing a strict HTTPS origin allowlist and a safe URL format (e.g., hostname check + https scheme) where the SSE assigns state (the useAnimeSearch hook / the code that sets agent.streamingUrl), and remove dangerous sandbox flags (drop allow-same-origin and allow-scripts/allow-forms unless explicitly needed); only render the <iframe> in PlatformCard when the streamingUrl has passed the allowlist/validation and use a minimal sandbox (no same-origin/scripts/forms) to follow least privilege. In `@anime-watch-hub/hooks/use-anime-search.ts`: - Around line 60-83: The SSE parser in use-anime-search.ts is using the wrong event shape; update the handling in the event dispatching (the code that currently checks for data.type === 'STREAMING_URL' / 'PROGRESS' / 'COMPLETE') to match the documented Mino schema: treat streamingUrl as a top-level field on events (if data.streamingUrl exists, call updateAgent(platform.id, { status: 'browsing', streamingUrl: data.streamingUrl, statusMessage: 'Browsing platform...' })), treat progress updates as type === 'STATUS' and use data.message for statusMessage (updateAgent(platform.id, { statusMessage: data.message })), and for COMPLETE events read data.resultJson (string) and JSON.parse it into result before calling updateAgent(platform.id, { status: 'complete', result: parsedResult, statusMessage: undefined }); also preserve the error branch for COMPLETE when data.status === 'failed' but read error message from data.error?.message as before. Ensure you reference these symbols: the SSE parsing block in use-anime-search.ts and the updateAgent(platform.id, ...) calls. 

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a24c2676-0d6d-477b-9955-8c741a29917d

📥 Commits

Reviewing files that changed from the base of the PR and between 119903c and e1b84c4.

📒 Files selected for processing (3)
  • anime-watch-hub/app/api/check-platform/route.ts
  • anime-watch-hub/components/platform-card.tsx
  • anime-watch-hub/hooks/use-anime-search.ts
Comment on lines 69 to 73
src={agent.streamingUrl}
className="h-full w-full"
title={`${agent.platformName} live view`}
sandbox="allow-same-origin"
sandbox="allow-same-origin allow-scripts allow-forms"
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash set -euo pipefail # Verify unvalidated streaming_url -> streamingUrl data flow rg -nP --type=ts --type=tsx '\bstreaming_url\b|\bstreamingUrl\b' -C2 # Verify iframe sandbox usage and current permissions rg -nP --type=tsx '<iframe|sandbox=' -C2

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 100


🏁 Script executed:

# List repository structure to understand the codebase git ls-files | head -30

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 1292


🏁 Script executed:

# Search for platform-card.tsx regardless of reported type fd "platform-card" -t f

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 117


🏁 Script executed:

# Also search for anime-watch-hub or similar directory patterns fd -t d "anime" 2>/dev/null || true

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 89


🏁 Script executed:

# Read the platform-card.tsx file to verify the actual code cat -n anime-watch-hub/components/platform-card.tsx

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 5057


🏁 Script executed:

# Check file sizes to decide on full vs partial read wc -l anime-watch-hub/hooks/use-anime-search.ts anime-watch-hub/lib/types.ts 2>/dev/null || true

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 164


🏁 Script executed:

# Read use-anime-search.ts around lines 56-66 to verify data flow sed -n '45,100p' anime-watch-hub/hooks/use-anime-search.ts

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 2016


🏁 Script executed:

# Read types.ts to check MinoAgentState definition and streamingUrl type cat -n anime-watch-hub/lib/types.ts

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 1761


🏁 Script executed:

# Check the start of use-anime-search.ts to see where the SSE endpoint comes from head -50 anime-watch-hub/hooks/use-anime-search.ts

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 1619


Harden iframe sandbox + validate streaming URL before render

Line 72 enables scripts and forms while line 69 renders agent.streamingUrl directly. The streamingUrl originates from external SSE payloads via /api/check-platform (anime-watch-hub/hooks/use-anime-search.ts, line 64) with no origin validation or format checking before assignment to state. This creates a high-risk trust boundary: an attacker controlling the backend or intercepting the SSE stream could inject arbitrary URLs that execute scripts inside your app frame. Gate the URL with a strict HTTPS origin allowlist and remove allow-same-origin unless absolutely required.

🔒 Suggested fix (least-privilege + allowlist)
+const TRUSTED_STREAM_ORIGINS = new Set([ + 'https://www.crunchyroll.com', + 'https://www.netflix.com', + 'https://www.amazon.com/Prime-Video', + 'https://www.hulu.com', + 'https://www.funimation.com', + 'https://www.hidive.com', + 'https://www.disneyplus.com', + 'https://www.max.com', +]) + +function getTrustedStreamingUrl(raw?: string): string | null { + if (!raw) return null + try { + const u = new URL(raw) + if (u.protocol !== 'https:') return null + return TRUSTED_STREAM_ORIGINS.has(u.origin) ? u.toString() : null + } catch { + return null + } +} + export function PlatformCard({ agent }: PlatformCardProps) { + const trustedStreamingUrl = getTrustedStreamingUrl(agent.streamingUrl) ... - {agent.streamingUrl && (agent.status === 'connecting' || agent.status === 'browsing') && ( + {trustedStreamingUrl && (agent.status === 'connecting' || agent.status === 'browsing') && ( <div className="relative aspect-video w-full overflow-hidden rounded-md border bg-muted"> <iframe - src={agent.streamingUrl} + src={trustedStreamingUrl} className="h-full w-full" title={`${agent.platformName} live view`} - sandbox="allow-same-origin allow-scripts allow-forms" + sandbox="allow-scripts allow-forms" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@anime-watch-hub/components/platform-card.tsx` around lines 69 - 73, The iframe is rendering agent.streamingUrl directly and uses a permissive sandbox ("allow-same-origin allow-scripts allow-forms"); validate and gate the URL before rendering by enforcing a strict HTTPS origin allowlist and a safe URL format (e.g., hostname check + https scheme) where the SSE assigns state (the useAnimeSearch hook / the code that sets agent.streamingUrl), and remove dangerous sandbox flags (drop allow-same-origin and allow-scripts/allow-forms unless explicitly needed); only render the <iframe> in PlatformCard when the streamingUrl has passed the allowlist/validation and use a minimal sandbox (no same-origin/scripts/forms) to follow least privilege. 
Comment on lines +60 to +83
if (data.type === 'STREAMING_URL' && data.streaming_url) {
updateAgent(platform.id, {
status: 'browsing',
streamingUrl: data.streamingUrl,
streamingUrl: data.streaming_url,
statusMessage: 'Browsing platform...',
})
}

if (data.type === 'STATUS' && data.message) {
updateAgent(platform.id, { statusMessage: data.message })
if (data.type === 'PROGRESS' && data.purpose) {
updateAgent(platform.id, { statusMessage: data.purpose })
}

if (data.type === 'COMPLETE') {
let result = {
available: false,
message: 'Check completed',
if (data.status === 'failed') {
updateAgent(platform.id, {
status: 'error',
statusMessage: data.error?.message ?? 'Automation failed',
streamingUrl: undefined,
})
} else {
updateAgent(platform.id, {
status: 'complete',
result: data.result,
statusMessage: undefined,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash set -euo pipefail echo "== Documented Mino SSE fields ==" rg -n -C2 'streamingUrl|type":"STATUS"|resultJson' anime-watch-hub/docs/mino-api-integration.md echo echo "== Current client parser ==" sed -n '56,85p' anime-watch-hub/hooks/use-anime-search.ts echo echo "== Server proxy behavior ==" sed -n '88,97p' anime-watch-hub/app/api/check-platform/route.ts echo echo "== Downstream UI dependence on agent.result.available ==" rg -n -C2 'result\?\.available' anime-watch-hub/components/platform-card.tsx

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 4228


Fix schema mismatch between Mino SSE and client parser.

The documented Mino SSE schema (lines 256–265 in anime-watch-hub/docs/mino-api-integration.md and concrete examples at lines 395–407) sends:

  • streamingUrl as a direct field (not under type: 'STREAMING_URL')
  • type: 'STATUS' with message for progress updates
  • resultJson (stringified) in COMPLETE events

The hook parser (lines 60–83 in anime-watch-hub/hooks/use-anime-search.ts) currently looks for:

  • type: 'STREAMING_URL' with streaming_url (field structure mismatch)
  • type: 'PROGRESS' with purpose (type mismatch)
  • result field (schema has resultJson)

Since /api/check-platform/route.ts proxies the upstream stream unchanged, the parser drops all streaming URL events and progress updates, and sets result: undefined on completion. This causes anime-watch-hub/components/platform-card.tsx (lines 22, 42) to render "Not Found" regardless of the actual search result.

🔧 Proposed compatibility fix
- if (data.type === 'STREAMING_URL' && data.streaming_url) { + const streamingUrl = data.streamingUrl ?? data.streaming_url + if (streamingUrl) { updateAgent(platform.id, { status: 'browsing', - streamingUrl: data.streaming_url, + streamingUrl, statusMessage: 'Browsing platform...', }) } - if (data.type === 'PROGRESS' && data.purpose) { - updateAgent(platform.id, { statusMessage: data.purpose }) + const progressMessage = + data.type === 'STATUS' + ? data.message + : data.type === 'PROGRESS' + ? data.purpose + : undefined + if (progressMessage) { + updateAgent(platform.id, { statusMessage: progressMessage }) } if (data.type === 'COMPLETE') { if (data.status === 'failed') { updateAgent(platform.id, { @@ } else { + const result = + data.result ?? + (typeof data.resultJson === 'string' + ? JSON.parse(data.resultJson) + : data.resultJson) + updateAgent(platform.id, { status: 'complete', - result: data.result, + result, statusMessage: undefined, streamingUrl: undefined, }) } }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@anime-watch-hub/hooks/use-anime-search.ts` around lines 60 - 83, The SSE parser in use-anime-search.ts is using the wrong event shape; update the handling in the event dispatching (the code that currently checks for data.type === 'STREAMING_URL' / 'PROGRESS' / 'COMPLETE') to match the documented Mino schema: treat streamingUrl as a top-level field on events (if data.streamingUrl exists, call updateAgent(platform.id, { status: 'browsing', streamingUrl: data.streamingUrl, statusMessage: 'Browsing platform...' })), treat progress updates as type === 'STATUS' and use data.message for statusMessage (updateAgent(platform.id, { statusMessage: data.message })), and for COMPLETE events read data.resultJson (string) and JSON.parse it into result before calling updateAgent(platform.id, { status: 'complete', result: parsedResult, statusMessage: undefined }); also preserve the error branch for COMPLETE when data.status === 'failed' but read error message from data.error?.message as before. Ensure you reference these symbols: the SSE parsing block in use-anime-search.ts and the updateAgent(platform.id, ...) calls. 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants