Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YT] Fix "Could not get like count" #30

Merged
merged 1 commit into from
Dec 10, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading