Skip to content

Commit 61ce041

Browse files
committed
[YouTube] Support handles and all custom channel names
More non-channel paths have been also added to the excluded custom name paths, documentation and exception messages have been improved and fixed in some places, and the licence header of YoutubeChannelLinkHandlerFactory has been moved to its beginning and updated.
1 parent ffffb04 commit 61ce041

1 file changed

Lines changed: 56 additions & 38 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeChannelLinkHandlerFactory.java

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,46 @@
1-
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
2-
3-
import java.util.regex.Pattern;
4-
import org.schabi.newpipe.extractor.exceptions.ParsingException;
5-
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
6-
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
7-
import org.schabi.newpipe.extractor.utils.Utils;
8-
9-
import java.net.URL;
10-
import java.util.List;
11-
121
/*
132
* Created by Christian Schabesberger on 25.07.16.
143
*
154
* Copyright (C) Christian Schabesberger 2018 <chrźis.schabesberger@mailbox.org>
16-
* YoutubeChannelLinkHandlerFactory.java is part of NewPipe.
5+
* YoutubeChannelLinkHandlerFactory.java is part of NewPipe Extractor.
176
*
18-
* NewPipe is free software: you can redistribute it and/or modify
7+
* NewPipe Extractor is free software: you can redistribute it and/or modify
198
* it under the terms of the GNU General Public License as published by
209
* the Free Software Foundation, either version 3 of the License, or
2110
* (at your option) any later version.
2211
*
23-
* NewPipe is distributed in the hope that it will be useful,
12+
* NewPipe Extractor is distributed in the hope that it will be useful,
2413
* but WITHOUT ANY WARRANTY; without even the implied warranty of
25-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2615
* GNU General Public License for more details.
2716
*
2817
* You should have received a copy of the GNU General Public License
29-
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
18+
* along with NewPipe Extractor. If not, see <https://www.gnu.org/licenses/>.
3019
*/
3120

21+
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
22+
23+
import java.util.regex.Pattern;
24+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
25+
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
26+
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
27+
import org.schabi.newpipe.extractor.utils.Utils;
28+
29+
import javax.annotation.Nonnull;
30+
import java.net.URL;
31+
import java.util.List;
32+
33+
import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
34+
3235
public final class YoutubeChannelLinkHandlerFactory extends ListLinkHandlerFactory {
3336

3437
private static final YoutubeChannelLinkHandlerFactory INSTANCE
3538
= new YoutubeChannelLinkHandlerFactory();
3639

37-
private static final Pattern EXCLUDED_SEGMENTS =
38-
Pattern.compile("playlist|watch|attribution_link|watch_popup|embed|feed|select_site");
40+
private static final Pattern EXCLUDED_SEGMENTS = Pattern.compile(
41+
// CHECKSTYLE:OFF
42+
"playlist|watch|attribution_link|watch_popup|embed|feed|select_site|account|reporthistory|redirect");
43+
// CHECKSTYLE:ON
3944

4045
private YoutubeChannelLinkHandlerFactory() {
4146
}
@@ -45,10 +50,10 @@ public static YoutubeChannelLinkHandlerFactory getInstance() {
4550
}
4651

4752
/**
48-
* Returns URL to channel from an ID
53+
* Returns the URL to a channel from an ID.
4954
*
50-
* @param id Channel ID including e.g. 'channel/'
51-
* @return URL to channel
55+
* @param id the channel ID including e.g. 'channel/'
56+
* @return the URL to the channel
5257
*/
5358
@Override
5459
public String getUrl(final String id,
@@ -58,16 +63,26 @@ public String getUrl(final String id,
5863
}
5964

6065
/**
61-
* Returns true if path conform to
62-
* custom short channel URLs like youtube.com/yourcustomname
66+
* Checks whether the given path conforms to custom short channel URLs like
67+
* {@code youtube.com/yourcustomname}.
6368
*
64-
* @param splitPath path segments array
65-
* @return true - if value conform to short channel URL, false - not
69+
* @param splitPath the path segments array
70+
* @return whether the value conform to short channel URLs
6671
*/
67-
private boolean isCustomShortChannelUrl(final String[] splitPath) {
72+
private boolean isCustomShortChannelUrl(@Nonnull final String[] splitPath) {
6873
return splitPath.length == 1 && !EXCLUDED_SEGMENTS.matcher(splitPath[0]).matches();
6974
}
7075

76+
/**
77+
* Checks whether the given path conforms to handle URLs like {@code youtube.com/@yourhandle}.
78+
*
79+
* @param splitPath the path segments array
80+
* @return whether the value conform to handle URLs
81+
*/
82+
private boolean isHandle(@Nonnull final String[] splitPath) {
83+
return splitPath.length > 0 && splitPath[0].startsWith("@");
84+
}
85+
7186
@Override
7287
public String getId(final String url) throws ParsingException {
7388
try {
@@ -77,35 +92,38 @@ public String getId(final String url) throws ParsingException {
7792
if (!Utils.isHTTP(urlObj) || !(YoutubeParsingHelper.isYoutubeURL(urlObj)
7893
|| YoutubeParsingHelper.isInvidioURL(urlObj)
7994
|| YoutubeParsingHelper.isHooktubeURL(urlObj))) {
80-
throw new ParsingException("the URL given is not a Youtube-URL");
95+
throw new ParsingException("The URL given is not a YouTube URL");
8196
}
8297

83-
// remove leading "/"
98+
// Remove leading "/"
8499
path = path.substring(1);
100+
85101
String[] splitPath = path.split("/");
86102

87-
// Handle custom short channel URLs like youtube.com/yourcustomname
88-
if (isCustomShortChannelUrl(splitPath)) {
103+
if (isHandle(splitPath)) {
104+
// Handle YouTube handle URLs like youtube.com/@yourhandle
105+
return splitPath[0];
106+
} else if (isCustomShortChannelUrl(splitPath)) {
107+
// Handle custom short channel URLs like youtube.com/yourcustomname
89108
path = "c/" + path;
90109
splitPath = path.split("/");
91110
}
92111

93-
if (!path.startsWith("user/")
94-
&& !path.startsWith("channel/")
112+
if (!path.startsWith("user/") && !path.startsWith("channel/")
95113
&& !path.startsWith("c/")) {
96-
throw new ParsingException("the URL given is neither a channel nor an user");
114+
throw new ParsingException(
115+
"The given URL is not a channel, a user or a handle URL");
97116
}
98117

99118
final String id = splitPath[1];
100119

101-
if (id == null || !id.matches("[A-Za-z0-9_-]+")) {
102-
throw new ParsingException("The given id is not a Youtube-Video-ID");
120+
if (isBlank(id)) {
121+
throw new ParsingException("The given ID is not a YouTube channel or user ID");
103122
}
104123

105124
return splitPath[0] + "/" + id;
106-
} catch (final Exception exception) {
107-
throw new ParsingException("Error could not parse url :" + exception.getMessage(),
108-
exception);
125+
} catch (final Exception e) {
126+
throw new ParsingException("Could not parse URL :" + e.getMessage(), e);
109127
}
110128
}
111129

0 commit comments

Comments
 (0)