feat(web): paste-a-URL handler — add an arbitrary video + summarize (Feature 2)
POST /paste: parse the video id, fetch metadata via the VideoFetcher port (Data API, ungated), upsert a subscription-less row scoped to the user (idempotent = dedup), and — unless already summarized — RequestSummarize + start immediate processing through the SAME globalFetchGate as the Summarize button. Explicit paste overrides the recency window; a captionless video degrades to the honest 'no transcript' terminal state via the engine (ADR-010). Invalid URL -> 400, not-found -> 404, both add nothing. Route mounts only when a Fetcher is wired. Moves the video-not-found sentinel to domain (shared by adapter + web, no cross-adapter coupling). Tests: valid add+queue, invalid, not-found, dedup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,10 +3,16 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrVideoNotFound is returned when a video id resolves to no video (deleted,
|
||||
// private, or a typo'd paste). Defined in domain so adapters and the web layer
|
||||
// share one sentinel without coupling to each other.
|
||||
var ErrVideoNotFound = errors.New("video not found")
|
||||
|
||||
// ErrChannelUnavailable is returned by a VideoSource when a channel's upload
|
||||
// playlist returns HTTP 404 — the channel was deleted or made private. The runner
|
||||
// stores these so the account page can surface them to the user.
|
||||
|
||||
Reference in New Issue
Block a user