Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,12 @@ public OffsetDateTime offsetDateTime() {
public boolean isApproximation() {
return isApproximation;
}

@Override
public String toString() {
return "DateWrapper{"
+ "offsetDateTime=" + offsetDateTime
+ ", isApproximation=" + isApproximation
+ '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ public long getLength() {

@Override
public long getTimeStamp() throws ParsingException {
return getTimestampSeconds("(#t=\\d{0,3}h?\\d{0,3}m?\\d{1,3}s?)");
final var timestamp = getTimestampSeconds("(#t=\\d{0,3}h?\\d{0,3}m?\\d{1,3}s?)");
return timestamp == -2 ? 0 : timestamp;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a future PR, you could make getTimestampSeconds() return an Optional<>. Also, all regex-related functions should ideally only take Patterns, so we can avoid rebuilding regexes every time.

}

@Override
Expand Down Expand Up @@ -170,7 +171,7 @@ public List<AudioStream> getAudioStreams() throws ExtractionException {

try {
final JsonArray transcodings = track.getObject("media")
.getArray("transcodings");
.getArray("transcodings");
if (!isNullOrEmpty(transcodings)) {
// Get information about what stream formats are available
extractAudioStreams(transcodings, audioStreams);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.schabi.newpipe.extractor.services.soundcloud.linkHandler;

import java.util.regex.Pattern;

import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper;
Expand All @@ -9,11 +11,18 @@
public final class SoundcloudStreamLinkHandlerFactory extends LinkHandlerFactory {
private static final SoundcloudStreamLinkHandlerFactory INSTANCE
= new SoundcloudStreamLinkHandlerFactory();
private static final String URL_PATTERN = "^https?://(www\\.|m\\.|on\\.)?"
+ "soundcloud.com/[0-9a-z_-]+"
+ "/(?!(tracks|albums|sets|reposts|followers|following)/?$)[0-9a-z_-]+/?([#?].*)?$";
private static final String API_URL_PATTERN = "^https?://api-v2\\.soundcloud.com"
+ "/(tracks|albums|sets|reposts|followers|following)/([0-9a-z_-]+)/";

private static final Pattern URL_PATTERN = Pattern.compile(
"^https?://(?:www\\.|m\\.|on\\.)?"
+ "soundcloud.com/[0-9a-z_-]+"
+ "/(?!(?:tracks|albums|sets|reposts|followers|following)/?$)[0-9a-z_-]+/?(?:[#?].*)?$"
);

private static final Pattern API_URL_PATTERN = Pattern.compile(
"^https?://api-v2\\.soundcloud.com"
+ "/(tracks|albums|sets|reposts|followers|following)/([0-9a-z_-]+)/"
);

private SoundcloudStreamLinkHandlerFactory() {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public Builder() {
}

/**
* Set the identifier of the {@link AudioStream}.
* Set the identifier of the {@link AudioStream} which uniquely identifies the stream,
* e.g. for YouTube this would be the itag
*
* <p>
* It <b>must not be null</b> and should be non empty.
Expand All @@ -108,14 +109,14 @@ public Builder setId(@Nonnull final String id) {
}

/**
* Set the content of the {@link AudioStream}.
*
* Set the content or the URL of the {@link AudioStream}, depending on whether isUrl is
* true
* <p>
* It must not be null, and should be non empty.
* </p>
*
* @param content the content of the {@link AudioStream}
* @param isUrl whether the content is a URL
* @param isUrl whether content is the URL or the actual content of e.g. a DASH manifest
* @return this {@link Builder} instance
*/
public Builder setContent(@Nonnull final String content,
Expand All @@ -126,7 +127,7 @@ public Builder setContent(@Nonnull final String content,
}

/**
* Set the {@link MediaFormat} used by the {@link AudioStream}.
* Set the {@link MediaFormat} used by the {@link AudioStream}, which can be null
*
* <p>
* It should be one of the audio {@link MediaFormat}s ({@link MediaFormat#M4A M4A},
Expand Down Expand Up @@ -278,16 +279,22 @@ public Builder setItagItem(@Nullable final ItagItem itagItem) {
* Build an {@link AudioStream} using the builder's current values.
*
* <p>
* The identifier and the content (and so the {@code isUrl} boolean) properties must have
* The identifier and the content (and thus {@code isUrl}) properties must have
* been set.
* </p>
*
* @return a new {@link AudioStream} using the builder's current values
* @throws IllegalStateException if {@code id}, {@code content} (and so {@code isUrl}) or
* @throws IllegalStateException if {@code id}, {@code content} (and thus {@code isUrl}) or
* {@code deliveryMethod} have been not set, or have been set as {@code null}
*/
@Nonnull
public AudioStream build() {
validateBuild();

return new AudioStream(this);
}

void validateBuild() {
if (id == null) {
throw new IllegalStateException(
"The identifier of the audio stream has been not set or is null. If you "
Expand All @@ -305,64 +312,39 @@ public AudioStream build() {
"The delivery method of the audio stream has been set as null, which is "
+ "not allowed. Pass a valid one instead with setDeliveryMethod.");
}

return new AudioStream(id, content, isUrl, mediaFormat, deliveryMethod, averageBitrate,
manifestUrl, audioTrackId, audioTrackName, audioLocale, audioTrackType,
itagItem);
}
}


/**
* Create a new audio stream.
* Create a new audio stream using the given {@link Builder}.
*
* @param id the identifier which uniquely identifies the stream, e.g. for YouTube
* this would be the itag
* @param content the content or the URL of the stream, depending on whether isUrl is
* true
* @param isUrl whether content is the URL or the actual content of e.g. a DASH
* manifest
* @param format the {@link MediaFormat} used by the stream, which can be null
* @param deliveryMethod the {@link DeliveryMethod} of the stream
* @param averageBitrate the average bitrate of the stream (which can be unknown, see
* {@link #UNKNOWN_BITRATE})
* @param audioTrackId the id of the audio track
* @param audioTrackName the name of the audio track
* @param audioLocale the {@link Locale} of the audio stream, representing its language
* @param itagItem the {@link ItagItem} corresponding to the stream, which cannot be null
* @param manifestUrl the URL of the manifest this stream comes from (if applicable,
* otherwise null)
* @param builder The {@link Builder} to use to create the audio stream
*/
@SuppressWarnings("checkstyle:ParameterNumber")
private AudioStream(@Nonnull final String id,
@Nonnull final String content,
final boolean isUrl,
@Nullable final MediaFormat format,
@Nonnull final DeliveryMethod deliveryMethod,
final int averageBitrate,
@Nullable final String manifestUrl,
@Nullable final String audioTrackId,
@Nullable final String audioTrackName,
@Nullable final Locale audioLocale,
@Nullable final AudioTrackType audioTrackType,
@Nullable final ItagItem itagItem) {
super(id, content, isUrl, format, deliveryMethod, manifestUrl);
if (itagItem != null) {
this.itagItem = itagItem;
this.itag = itagItem.id;
this.quality = itagItem.getQuality();
this.bitrate = itagItem.getBitrate();
this.initStart = itagItem.getInitStart();
this.initEnd = itagItem.getInitEnd();
this.indexStart = itagItem.getIndexStart();
this.indexEnd = itagItem.getIndexEnd();
this.codec = itagItem.getCodec();
AudioStream(final Builder builder) {
super(builder.id,
builder.content,
builder.isUrl,
builder.mediaFormat,
builder.deliveryMethod,
builder.manifestUrl);
if (builder.itagItem != null) {
this.itagItem = builder.itagItem;
this.itag = builder.itagItem.id;
this.quality = builder.itagItem.getQuality();
this.bitrate = builder.itagItem.getBitrate();
this.initStart = builder.itagItem.getInitStart();
this.initEnd = builder.itagItem.getInitEnd();
this.indexStart = builder.itagItem.getIndexStart();
this.indexEnd = builder.itagItem.getIndexEnd();
this.codec = builder.itagItem.getCodec();
}
this.averageBitrate = averageBitrate;
this.audioTrackId = audioTrackId;
this.audioTrackName = audioTrackName;
this.audioLocale = audioLocale;
this.audioTrackType = audioTrackType;
this.averageBitrate = builder.averageBitrate;
this.audioTrackId = builder.audioTrackId;
this.audioTrackName = builder.audioTrackName;
this.audioLocale = builder.audioLocale;
this.audioTrackType = builder.audioTrackType;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ public class Description implements Serializable {

public Description(@Nullable final String content, final int type) {
this.type = type;
if (content == null) {
this.content = "";
} else {
this.content = content;
}
this.content = Objects.requireNonNullElse(content, "");
}

public String getContent() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public Stream(final String id,
* @param streamList the list of {@link Stream}s which will be compared
* @return whether the list already contains one stream with equals stats
*/
public static boolean containSimilarStream(final Stream stream,
public static boolean containSimilarStream(@Nonnull final Stream stream,
final List<? extends Stream> streamList) {
if (isNullOrEmpty(streamList)) {
return false;
Expand Down Expand Up @@ -98,11 +98,9 @@ public static boolean containSimilarStream(final Stream stream,
* @return whether the stream have the same stats or not, based on the criteria above
*/
public boolean equalStats(@Nullable final Stream other) {
if (other == null || mediaFormat == null || other.mediaFormat == null) {
return false;
}
return mediaFormat.id == other.mediaFormat.id && deliveryMethod == other.deliveryMethod
&& isUrl == other.isUrl;
return other != null && mediaFormat != null && other.mediaFormat != null
&& mediaFormat.id == other.mediaFormat.id && deliveryMethod == other.deliveryMethod
&& isUrl == other.isUrl;
}

/**
Expand Down Expand Up @@ -137,6 +135,7 @@ public String getUrl() {
*
* @return the content or URL
*/
@Nonnull
public String getContent() {
return content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ private static void extractOptionalData(final StreamInfo streamInfo,
private String uploaderUrl = "";
@Nonnull
private List<Image> uploaderAvatars = List.of();
private boolean uploaderVerified = false;
private boolean uploaderVerified;
private long uploaderSubscriberCount = -1;

private String subChannelName = "";
Expand All @@ -368,19 +368,19 @@ private static void extractOptionalData(final StreamInfo streamInfo,
private String hlsUrl = "";
private List<InfoItem> relatedItems = List.of();

private long startPosition = 0;
private long startPosition;
private List<SubtitlesStream> subtitles = List.of();

private String host = "";
private StreamExtractor.Privacy privacy;
private String category = "";
private String licence = "";
private String supportInfo = "";
private Locale language = null;
private Locale language;
private List<String> tags = List.of();
private List<StreamSegment> streamSegments = List.of();
private List<MetaInfo> metaInfo = List.of();
private boolean shortFormContent = false;
private boolean shortFormContent;

/**
* Preview frames, e.g. for the storyboard / seekbar thumbnail preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* <p>
* This class is used to construct {@link org.schabi.newpipe.extractor.Image Image}
* instances from a single base URL/path, in order to get all or most image resolutions provided,
* depending of the service and the resolutions provided.
* depending on the service and the resolutions provided.
* </p>
*
* <p>
Expand Down
Loading