Errors and exceptions
Extraction failures are checked exceptions. Everything below derives from ExtractionException (which extends Exception), so the compiler forces callers to handle them, and the type itself carries the meaning.
The hierarchy
ExtractionException
├─ ParsingException
│ ├─ ContentNotAvailableException
│ │ ├─ GeographicRestrictionException
│ │ ├─ AgeRestrictedContentException
│ │ ├─ PaidContentException
│ │ ├─ PrivateContentException
│ │ ├─ SoundCloudGoPlusContentException
│ │ ├─ YoutubeMusicPremiumContentException
│ │ ├─ AccountTerminatedException (carries a Reason)
│ │ ├─ LiveNotStartException
│ │ └─ VideoNotReleaseException
│ ├─ ContentNotSupportedException
│ ├─ FoundAdException
│ ├─ AntiBotException
│ └─ NeedLoginException
└─ ReCaptchaException (carries the challenge url)What to throw when
ParsingException: the page loaded but a field is missing or shaped wrong. Wrap IO and JSON failures in it.ContentNotAvailableExceptionand its subclasses: the content exists but this client cannot have it. The subclass says why, and the app maps it to a specific message:GeographicRestrictionException,AgeRestrictedContentException,PaidContentException,PrivateContentException,AccountTerminatedException(with aReason),LiveNotStartException/VideoNotReleaseExceptionfor not-yet-live and premieres, plus service-specific ones (SoundCloudGoPlusContentException,YoutubeMusicPremiumContentException).
ContentNotSupportedException: the extractor does not handle this kind of content, for example a channel with no supported tabs.FoundAdException: the link is an ad URL; thrown straight from the link handler.ReCaptchaException: the service demands a captcha; it carries theurlso the app can present the challenge.
Real throw sites
YoutubeStreamExtractor inspects the player error reason and raises the right one:
java
if (message.contains("private")) throw new PrivateContentException("This video is private");
if (reason.contains("Premieres in")) throw new VideoNotReleaseException(reason);SoundcloudStreamExtractor turns a "SNIP" policy into SoundCloudGoPlusContentException; YoutubeStreamLinkHandlerFactory throws FoundAdException for doubleclick hosts. This precision is what StreamInfo.getInfo relies on when it disambiguates age-restricted from country-blocked (see Extraction flow).
