From bd79b921e874411a0fd2d6e397a455ae2a91c9dd Mon Sep 17 00:00:00 2001 From: AudricV <74829229+AudricV@users.noreply.github.com> Date: Mon, 20 Feb 2023 17:15:20 +0100 Subject: [PATCH] [YouTube] Refactor the code to get stream items' view count This refactoring avoids code duplication as much as possible. --- .../YoutubeStreamInfoItemExtractor.java | 98 ++++++++++--------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index c5842323b..1607e0a0f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -13,6 +13,7 @@ import org.schabi.newpipe.extractor.utils.JsonUtils; import org.schabi.newpipe.extractor.utils.Parser; import org.schabi.newpipe.extractor.utils.Utils; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.time.Instant; import java.time.OffsetDateTime; @@ -290,20 +291,14 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { return -1; } - final String viewCount = getTextFromObject(videoInfo.getObject("viewCountText")); + // Ignore all exceptions, as the view count can be hidden by creators, and so cannot be + // found in this case - if (!isNullOrEmpty(viewCount)) { + final String viewCountText = getTextFromObject(videoInfo.getObject("viewCountText")); + if (!isNullOrEmpty(viewCountText)) { try { - // These approaches are language dependent - if (viewCount.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { - return 0; - } else if (viewCount.toLowerCase().contains("recommended")) { - return -1; - } - - return Long.parseLong(Utils.removeNonDigitCharacters(viewCount)); + return getViewCountFromViewCountText(viewCountText, false); } catch (final Exception ignored) { - // Ignore all exceptions, as we can fall back to accessibility data } } @@ -311,64 +306,71 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { // livestream (the view count is returned and not the count of people watching currently // the livestream) if (getStreamType() != StreamType.LIVE_STREAM) { - final String videoInfoTitleAccessibilityData = videoInfo.getObject("title") - .getObject("accessibility") - .getObject("accessibilityData") - .getString("label", ""); - - if (videoInfoTitleAccessibilityData.toLowerCase().endsWith(NO_VIEWS_LOWERCASE)) { - return 0; - } - try { - return Long.parseLong(Utils.removeNonDigitCharacters( - // This approach is language dependent - Parser.matchGroup1(ACCESSIBILITY_DATA_VIEW_COUNT_REGEX, - videoInfoTitleAccessibilityData))); + return getViewCountFromAccessibilityData(); } catch (final Exception ignored) { - // Ignore all exceptions, as the view count can be hidden by creators, and so - // cannot be found in this case } } // Fallback to a short view count, always used for livestreams (see why above) - try { + if (videoInfo.has("videoInfo")) { // Returned in playlists, in the form: view count separator upload date - if (videoInfo.has("videoInfo")) { - final String videoInfoViewCountText = videoInfo.getObject("videoInfo") + try { + return getViewCountFromViewCountText(videoInfo.getObject("videoInfo") .getArray("runs") .getObject(0) - .getString("text", ""); - if (videoInfoViewCountText.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { - return 0; - } - - return Utils.mixedNumberWordToLong(videoInfoViewCountText); + .getString("text", ""), true); + } catch (final Exception ignored) { } + } + if (videoInfo.has("shortViewCountText")) { // Returned everywhere but in playlists, used by the website to show view counts - if (videoInfo.has("shortViewCountText")) { - final String shortVideoViewCountText = + try { + final String shortViewCountText = getTextFromObject(videoInfo.getObject("shortViewCountText")); - if (isNullOrEmpty(shortVideoViewCountText)) { - return -1; + if (!isNullOrEmpty(shortViewCountText)) { + return getViewCountFromViewCountText(shortViewCountText, true); } - - if (shortVideoViewCountText.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { - return 0; - } - - return Utils.mixedNumberWordToLong(shortVideoViewCountText); + } catch (final Exception ignored) { } - } catch (final Exception ignored) { - // Ignore all exceptions, as the view count can be hidden by creators, and so cannot be - // found in this case } // No view count extracted: return -1, as the view count can be hidden by creators on videos return -1; } + private long getViewCountFromViewCountText(@Nonnull final String viewCountText, + final boolean isMixedNumber) + throws NumberFormatException, ParsingException { + // These approaches are language dependent + if (viewCountText.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { + return 0; + } else if (viewCountText.toLowerCase().contains("recommended")) { + return -1; + } + + return isMixedNumber ? Utils.mixedNumberWordToLong(viewCountText) + : Long.parseLong(Utils.removeNonDigitCharacters(viewCountText)); + } + + private long getViewCountFromAccessibilityData() + throws NumberFormatException, Parser.RegexException { + // These approaches are language dependent + final String videoInfoTitleAccessibilityData = videoInfo.getObject("title") + .getObject("accessibility") + .getObject("accessibilityData") + .getString("label", ""); + + if (videoInfoTitleAccessibilityData.toLowerCase().endsWith(NO_VIEWS_LOWERCASE)) { + return 0; + } + + return Long.parseLong(Utils.removeNonDigitCharacters( + Parser.matchGroup1(ACCESSIBILITY_DATA_VIEW_COUNT_REGEX, + videoInfoTitleAccessibilityData))); + } + @Override public String getThumbnailUrl() throws ParsingException { return getThumbnailUrlFromInfoItem(videoInfo);