Skip to content

Commit

Permalink
Merge pull request #31 from ShareASmile/fix-yt-like-count-legacy
Browse files Browse the repository at this point in the history
[YT] Fix "Could not get like count"
  • Loading branch information
ShareASmile authored Dec 10, 2023
2 parents 5f3f617 + 9f7ab40 commit 1ef6c72
Showing 1 changed file with 79 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -430,73 +430,34 @@ public long getLikeCount() throws ParsingException {
return -1;
}

String likesString = "";
String likesString = null;

try {
final JsonArray topLevelButtons = getVideoPrimaryInfoRenderer()
final List<JsonObject> topLevelButtons = getVideoPrimaryInfoRenderer()
.getObject("videoActions")
.getObject("menuRenderer")
.getArray("topLevelButtons");

// Try first with the new video actions buttons data structure
JsonObject likeToggleButtonRenderer = topLevelButtons.stream()
.getArray("topLevelButtons")
.stream()
.filter(JsonObject.class::isInstance)
.map(JsonObject.class::cast)
.map(button -> button.getObject("segmentedLikeDislikeButtonRenderer")
.getObject("likeButton")
.getObject("toggleButtonRenderer"))
.filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
.collect(Collectors.toList());

likesString = topLevelButtons.stream()
.map(btn -> btn.getObject("segmentedLikeDislikeButtonViewModel")
.getObject("likeButtonViewModel")
.getObject("likeButtonViewModel")
.getObject("toggleButtonViewModel")
.getObject("toggleButtonViewModel")
.getObject("defaultButtonViewModel")
.getObject("buttonViewModel")
.getString("accessibilityText"))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);

// Use the old video actions buttons data structure if the new one isn't returned
if (likeToggleButtonRenderer == null) {
/*
In the old video actions buttons data structure, there are 3 ways to detect whether
a button is the like button, using its toggleButtonRenderer:
- checking whether toggleButtonRenderer.targetId is equal to watch-like;
- checking whether toggleButtonRenderer.defaultIcon.iconType is equal to LIKE;
- checking whether
toggleButtonRenderer.toggleButtonSupportedData.toggleButtonIdData.id
is equal to TOGGLE_BUTTON_ID_TYPE_LIKE.
*/
likeToggleButtonRenderer = topLevelButtons.stream()
.filter(JsonObject.class::isInstance)
.map(JsonObject.class::cast)
.map(topLevelButton -> topLevelButton.getObject("toggleButtonRenderer"))
.filter(toggleButtonRenderer -> toggleButtonRenderer.getString("targetId")
.equalsIgnoreCase("watch-like")
|| toggleButtonRenderer.getObject("defaultIcon")
.getString("iconType")
.equalsIgnoreCase("LIKE")
|| toggleButtonRenderer.getObject("toggleButtonSupportedData")
.getObject("toggleButtonIdData")
.getString("id")
.equalsIgnoreCase("TOGGLE_BUTTON_ID_TYPE_LIKE"))
.findFirst()
.orElseThrow(() -> new ParsingException(
"The like button is missing even though ratings are enabled"));
}

// Use one of the accessibility strings available (this one has the same path as the
// one used for comments' like count extraction)
likesString = likeToggleButtonRenderer.getObject("accessibilityData")
.getObject("accessibilityData")
.getString("label");

// Use the other accessibility string available which contains the exact like count
if (likesString == null) {
likesString = likeToggleButtonRenderer.getObject("accessibility")
.getString("label");
}

// Last method: use the defaultText's accessibility data, which contains the exact like
// count too, except when it is equal to 0, where a localized string is returned instead
// Old - pre Dec 2023 way
if (likesString == null) {
likesString = likeToggleButtonRenderer.getObject("defaultText")
.getObject("accessibility")
.getObject("accessibilityData")
.getString("label");
likesString = getPreDec2023LikeString(topLevelButtons);
}

// If ratings are allowed and the likes string is null, it means that we couldn't
Expand All @@ -519,6 +480,67 @@ public long getLikeCount() throws ParsingException {
}
}

protected String getPreDec2023LikeString(final List<JsonObject> topLevelButtons)
throws ParsingException {
// Try first with the new video actions buttons data structure
JsonObject likeToggleButtonRenderer = topLevelButtons.stream()
.map(button -> button.getObject("segmentedLikeDislikeButtonRenderer")
.getObject("likeButton")
.getObject("toggleButtonRenderer"))
.filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
.findFirst()
.orElse(null);

// Use the old video actions buttons data structure if the new one isn't returned
if (likeToggleButtonRenderer == null) {
/*
In the old video actions buttons data structure, there are 3 ways to detect whether
a button is the like button, using its toggleButtonRenderer:
- checking whether toggleButtonRenderer.targetId is equal to watch-like;
- checking whether toggleButtonRenderer.defaultIcon.iconType is equal to LIKE;
- checking whether
toggleButtonRenderer.toggleButtonSupportedData.toggleButtonIdData.id
is equal to TOGGLE_BUTTON_ID_TYPE_LIKE.
*/
likeToggleButtonRenderer = topLevelButtons.stream()
.map(topLevelButton -> topLevelButton.getObject("toggleButtonRenderer"))
.filter(toggleButtonRenderer -> "watch-like".equalsIgnoreCase(
toggleButtonRenderer.getString("targetId"))
|| "LIKE".equalsIgnoreCase(
toggleButtonRenderer.getObject("defaultIcon")
.getString("iconType"))
|| "TOGGLE_BUTTON_ID_TYPE_LIKE".equalsIgnoreCase(
toggleButtonRenderer.getObject("toggleButtonSupportedData")
.getObject("toggleButtonIdData")
.getString("id")))
.findFirst()
.orElseThrow(() -> new ParsingException(
"The like button is missing even though ratings are enabled"));
}

// Use one of the accessibility strings available (this one has the same path as the
// one used for comments' like count extraction)
String likesString = likeToggleButtonRenderer.getObject("accessibilityData")
.getObject("accessibilityData")
.getString("label");

// Use the other accessibility string available which contains the exact like count
if (likesString == null) {
likesString = likeToggleButtonRenderer.getObject("accessibility")
.getString("label");
}

// Last method: use the defaultText's accessibility data, which contains the exact like
// count too, except when it is equal to 0, where a localized string is returned instead
if (likesString == null) {
likesString = likeToggleButtonRenderer.getObject("defaultText")
.getObject("accessibility")
.getObject("accessibilityData")
.getString("label");
}
return likesString;
}

@Nonnull
@Override
public String getUploaderUrl() throws ParsingException {
Expand Down

0 comments on commit 1ef6c72

Please sign in to comment.