Skip to content
Draft
Show file tree
Hide file tree
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
110 changes: 110 additions & 0 deletions extractor/src/main/java/org/schabi/newpipe/extractor/Creator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package org.schabi.newpipe.extractor;

import java.util.List;
import javax.annotation.Nonnull;

/**
* Class representing a creator of a piece of media that has been extracted.
*/
public final class Creator {

/**
* Constant representing that the amount of subscribers of a {@link Creator} is unknown.
*/
public static final long UNKNOWN_SUBSCRIBER_COUNT = -1;

@Nonnull
private final String name;
@Nonnull
private final String url;
@Nonnull
private final List<Image> avatars;
private final long subscriberCount;
private final boolean isVerified;

/**
* Construct an {@link Creator} instance.
*
* @param name the name of the creator, which should be not null or empty
* @param url the URL to the creator's page, which should be not null
* or empty
* @param avatars the avatar of the creator, possibly in multiple resolutions
* @param subscriberCount the amount of subscribers/followers of the creator
* @param isVerified whether the creator has been verified by the platform
*/
public Creator(@Nonnull final String name,
@Nonnull final String url,
@Nonnull final List<Image> avatars,
final long subscriberCount,
final boolean isVerified) {
this.name = name;
this.url = url;
this.avatars = avatars;
this.subscriberCount = subscriberCount;
this.isVerified = isVerified;
}

/**
* Get the name of the {@link Creator}.
*
* @return the {@link Creator}'s name.
*/
@Nonnull
public String getName() {
return name;
}

/**
* Get the URL of the {@link Creator}.
*
* @return the {@link Creator}'s URL.
*/
@Nonnull
public String getUrl() {
return url;
}

/**
* Get the avatars of the {@link Creator}.
*
* @return the {@link Creator}'s avatars.
*/
@Nonnull
public List<Image> getAvatars() {
return avatars;
}

/**
* Get the amount of subscribers of this {@link Image}.
*
* <p>
* If it is unknown, {@link #UNKNOWN_SUBSCRIBER_COUNT} is returned instead.
* </p>
*
* @return the {@link Creator}'s amount of subscribers or {@link #UNKNOWN_SUBSCRIBER_COUNT}
*/
public long getSubscriberCount() {
return subscriberCount;
}

/**
* Get whether the {@link Creator} has been verified by the platform.
*
* @return whether the {@link Creator} has been verified by the platform
*/
public boolean isVerified() {
return isVerified;
}

/**
* Get a string representation of this {@link Creator} instance.
*
* @return a string representation of this {@link Creator} instance
*/
@Nonnull
@Override
public String toString() {
return "Creator {" + "name=" + name + ", url=" + url + ", avatars=" + avatars
+ ", subscriberCount=" + subscriberCount + ", isVerified=" + isVerified + "}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package org.schabi.newpipe.extractor.services.youtube;

import static org.schabi.newpipe.extractor.Creator.UNKNOWN_SUBSCRIBER_COUNT;
import static org.schabi.newpipe.extractor.NewPipe.getDownloader;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.ANDROID_CLIENT_VERSION;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.DESKTOP_CLIENT_PLATFORM;
Expand All @@ -46,6 +47,7 @@
import com.grack.nanojson.JsonWriter;

import org.jsoup.nodes.Entities;
import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.Image.ResolutionLevel;
import org.schabi.newpipe.extractor.downloader.Response;
Expand Down Expand Up @@ -1608,4 +1610,52 @@ public static JsonObject getFirstCollaborator(final JsonObject navigationEndpoin
return null;
}
}

/**
* Gets the first collaborator, which is the channel that owns the video,
* i.e. the video is displayed on their channel page.
*
* @param navigationEndpoint JSON object for the navigationEndpoint
* @return The first collaborator in the JSON object or {@code null}
*/
@Nullable
public static List<Creator> getCollaborators(final JsonObject navigationEndpoint)
throws ParsingException {
// CHECKSTYLE:OFF
final JsonArray listItems = JsonUtils.getArray(navigationEndpoint, "showDialogCommand.panelLoadingStrategy.inlineContent.dialogViewModel.customContent.listViewModel.listItems");
// CHECKSTYLE:ON

return listItems
.streamAsJsonObjects()
.map(item -> {
final JsonObject channel = item.getObject("listItemViewModel");

final String url = getUrlFromNavigationEndpoint(
channel.getObject("rendererContext")
.getObject("commandContext")
.getObject("onTap")
.getObject("innertubeCommand"));
final List<Image> avatars = getImagesFromThumbnailsArray(
channel.getObject("leadingAccessory")
.getObject("avatarViewModel")
.getObject("image")
.getArray("sources"));

long subscriberCount = UNKNOWN_SUBSCRIBER_COUNT;
try {
final String content = channel.getObject("subtitle").getString("content");
subscriberCount = Utils.mixedNumberWordToLong(content.split("•")[1]);
} catch (final NumberFormatException | ParsingException e) { }

return new Creator(
channel.getObject("title").getString("content"),
url,
avatars,
subscriberCount,
YoutubeParsingHelper.hasArtistOrVerifiedIconBadgeAttachment(
channel.getObject("title").getArray("attachmentRuns"))
);
})
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonWriter;

import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.MetaInfo;
Expand Down Expand Up @@ -1684,6 +1685,21 @@ public List<MetaInfo> getMetaInfo() throws ParsingException {
.getArray("contents"));
}

@Nonnull
@Override
public List<Creator> getCreators() throws ParsingException {
final JsonObject navigationEndpoint = JsonUtils.getObject(getVideoSecondaryInfoRenderer(),
"owner.videoOwnerRenderer.navigationEndpoint");

if (!navigationEndpoint.has("showDialogCommand")) {
// video has only one creator
return List.of(new Creator(getUploaderName(), getUploaderUrl(),
getUploaderAvatars(), getUploaderSubscriberCount(), isUploaderVerified()));
}

return YoutubeParsingHelper.getCollaborators(navigationEndpoint);
}

/**
* Set the {@link PoTokenProvider} instance to be used for fetching {@code poToken}s.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.schabi.newpipe.extractor.services.youtube.extractors;

import static org.schabi.newpipe.extractor.Creator.UNKNOWN_SUBSCRIBER_COUNT;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailsFromInfoItem;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray;
Expand All @@ -27,6 +28,7 @@
import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject;

import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.localization.DateWrapper;
Expand Down Expand Up @@ -502,4 +504,18 @@ public ContentAvailability getContentAvailability() throws ParsingException {
return ContentAvailability.AVAILABLE;
}

@Nonnull
@Override
public List<Creator> getCreators() throws ParsingException {
final JsonObject navigationEndpoint = videoInfo.getObject("shortBylineText")
.getArray("runs").getObject(0).getObject("navigationEndpoint");

if (!navigationEndpoint.has("showDialogCommand")) {
// video has only one creator
return List.of(new Creator(getUploaderName(), getUploaderUrl(),
getUploaderAvatars(), UNKNOWN_SUBSCRIBER_COUNT, isUploaderVerified()));
}

return YoutubeParsingHelper.getCollaborators(navigationEndpoint);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package org.schabi.newpipe.extractor.stream;

import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.InfoItemsCollector;
Expand Down Expand Up @@ -593,6 +594,16 @@ public ContentAvailability getContentAvailability() throws ParsingException {
return ContentAvailability.UNKNOWN;
}

/**
* Gets the creators of the stream.
*
* @return The creators of the stream.
*/
@Nonnull
public List<Creator> getCreators() throws ParsingException {
return List.of();
}

public enum Privacy {
PUBLIC,
UNLISTED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package org.schabi.newpipe.extractor.stream;

import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.InfoItem;
Expand Down Expand Up @@ -335,6 +336,11 @@ private static void extractOptionalData(final StreamInfo streamInfo,
} catch (final Exception e) {
streamInfo.addError(e);
}
try {
streamInfo.setCreators(extractor.getCreators());
} catch (final Exception e) {
streamInfo.addError(e);
}

streamInfo.setRelatedItems(ExtractorHelper.getRelatedItemsOrLogError(streamInfo,
extractor));
Expand Down Expand Up @@ -388,6 +394,7 @@ private static void extractOptionalData(final StreamInfo streamInfo,
private boolean shortFormContent = false;
@Nonnull
private ContentAvailability contentAvailability = ContentAvailability.AVAILABLE;
private List<Creator> creators = List.of();

/**
* Preview frames, e.g. for the storyboard / seekbar thumbnail preview
Expand Down Expand Up @@ -743,4 +750,13 @@ public ContentAvailability getContentAvailability() {
public void setContentAvailability(@Nonnull final ContentAvailability availability) {
this.contentAvailability = availability;
}

@Nonnull
public List<Creator> getCreators() {
return creators;
}

public void setCreators(@Nonnull final List<Creator> creators) {
this.creators = creators;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package org.schabi.newpipe.extractor.stream;

import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.localization.DateWrapper;
Expand Down Expand Up @@ -49,6 +50,8 @@ public class StreamInfoItem extends InfoItem {
private boolean shortFormContent = false;
@Nonnull
private ContentAvailability contentAvailability = ContentAvailability.AVAILABLE;
@Nonnull
private List<Creator> creators = List.of();

public StreamInfoItem(final int serviceId,
final String url,
Expand Down Expand Up @@ -162,6 +165,23 @@ public void setContentAvailability(@Nonnull final ContentAvailability availabili
this.contentAvailability = availability;
}

/**
* Gets the creators of the stream.
*
* @return The creators of the stream.
*/
@Nonnull
public List<Creator> getCreators() {
return creators;
}

/**
* Sets the creators of the stream.
*/
public void setCreators(@Nonnull final List<Creator> creators) {
this.creators = creators;
}

@Override
public String toString() {
return "StreamInfoItem{"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package org.schabi.newpipe.extractor.stream;

import org.schabi.newpipe.extractor.Creator;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.InfoItemExtractor;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
Expand Down Expand Up @@ -162,4 +163,16 @@ default boolean isShortFormContent() throws ParsingException {
default ContentAvailability getContentAvailability() throws ParsingException {
return ContentAvailability.UNKNOWN;
}


/**
* Get the creators/collaborators of the stream.
*
* @return The stream's creators
* @throws ParsingException if there is an error in the extraction
*/
@Nonnull
default List<Creator> getCreators() throws ParsingException {
return List.of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ public StreamInfoItem extract(final StreamInfoItemExtractor extractor) throws Pa
} catch (final Exception e) {
addError(e);
}
try {
resultItem.setCreators(extractor.getCreators());
} catch (final Exception e) {
addError(e);
}

return resultItem;
}
Expand Down
Loading