Skip to content

Commit daf5674

Browse files
committed
Add ability to identify short-form StreamInfoItems
1 parent 3d31416 commit daf5674

8 files changed

Lines changed: 603 additions & 0 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,4 +324,16 @@ public String getShortDescription() throws ParsingException {
324324

325325
return null;
326326
}
327+
328+
@Override
329+
public boolean isShortFormContent() throws ParsingException {
330+
try {
331+
final String webPageType = videoInfo.getObject("navigationEndpoint")
332+
.getObject("commandMetadata").getObject("webCommandMetadata")
333+
.getString("webPageType");
334+
return !isNullOrEmpty(webPageType) && webPageType.equals("WEB_PAGE_TYPE_SHORTS");
335+
} catch (final Exception e) {
336+
throw new ParsingException("Could not determine if short-form content", e);
337+
}
338+
}
327339
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public class StreamInfoItem extends InfoItem {
4242
private String uploaderUrl = null;
4343
private String uploaderAvatarUrl = null;
4444
private boolean uploaderVerified = false;
45+
private boolean shortFormContent = false;
4546

4647
public StreamInfoItem(final int serviceId,
4748
final String url,
@@ -130,6 +131,15 @@ public void setUploaderVerified(final boolean uploaderVerified) {
130131
this.uploaderVerified = uploaderVerified;
131132
}
132133

134+
public boolean isShortFormContent() {
135+
return shortFormContent;
136+
}
137+
138+
public void setShortFormContent(final boolean shortFormContent) {
139+
this.shortFormContent = shortFormContent;
140+
}
141+
142+
133143
@Override
134144
public String toString() {
135145
return "StreamInfoItem{"

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,14 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor {
127127
default String getShortDescription() throws ParsingException {
128128
return null;
129129
}
130+
131+
/**
132+
* Check if the stream is a short-form content
133+
*
134+
* @return {@code true} if the stream is a short-form content
135+
* @throws ParsingException thrown if there is an error in the extraction
136+
*/
137+
default boolean isShortFormContent() throws ParsingException {
138+
return false;
139+
}
130140
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ public StreamInfoItem extract(final StreamInfoItemExtractor extractor) throws Pa
9898
} catch (final Exception e) {
9999
addError(e);
100100
}
101+
try {
102+
resultItem.setShortFormContent(extractor.isShortFormContent());
103+
} catch (final Exception e) {
104+
addError(e);
105+
}
101106

102107
return resultItem;
103108
}

extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,41 @@ public void testVideoDescription() throws IOException, ExtractionException {
379379
assertNotNull(((StreamInfoItem) items.get(0)).getShortDescription());
380380
}
381381
}
382+
383+
public static class ShortFormContent extends DefaultSearchExtractorTest {
384+
private static SearchExtractor extractor;
385+
private static final String QUERY = "#shorts";
386+
387+
@BeforeAll
388+
public static void setUp() throws Exception {
389+
YoutubeTestsUtils.ensureStateless();
390+
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "shorts"));
391+
extractor = YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
392+
extractor.fetchPage();
393+
}
394+
395+
@Override public SearchExtractor extractor() { return extractor; }
396+
@Override public StreamingService expectedService() { return YouTube; }
397+
@Override public String expectedName() { return QUERY; }
398+
@Override public String expectedId() { return QUERY; }
399+
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
400+
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
401+
@Override public String expectedSearchString() { return QUERY; }
402+
@Nullable @Override public String expectedSearchSuggestion() { return null; }
403+
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
404+
405+
@Test
406+
public void testVideoDescription() throws IOException, ExtractionException {
407+
final List<InfoItem> items = extractor.getInitialPage().getItems();
408+
boolean hasShortFormContent = false;
409+
for (InfoItem item : items) {
410+
if (((StreamInfoItem) item).isShortFormContent()) {
411+
hasShortFormContent = true;
412+
break;
413+
}
414+
}
415+
416+
assertTrue(hasShortFormContent);
417+
}
418+
}
382419
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"request": {
3+
"httpMethod": "GET",
4+
"url": "https://www.youtube.com/sw.js",
5+
"headers": {
6+
"Origin": [
7+
"https://www.youtube.com"
8+
],
9+
"Referer": [
10+
"https://www.youtube.com"
11+
],
12+
"Accept-Language": [
13+
"en-GB, en;q\u003d0.9"
14+
]
15+
},
16+
"localization": {
17+
"languageCode": "en",
18+
"countryCode": "GB"
19+
}
20+
},
21+
"response": {
22+
"responseCode": 200,
23+
"responseMessage": "",
24+
"responseHeaders": {
25+
"access-control-allow-credentials": [
26+
"true"
27+
],
28+
"access-control-allow-origin": [
29+
"https://www.youtube.com"
30+
],
31+
"alt-svc": [
32+
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000,h3-Q050\u003d\":443\"; ma\u003d2592000,h3-Q046\u003d\":443\"; ma\u003d2592000,h3-Q043\u003d\":443\"; ma\u003d2592000,quic\u003d\":443\"; ma\u003d2592000; v\u003d\"46,43\""
33+
],
34+
"cache-control": [
35+
"private, max-age\u003d0"
36+
],
37+
"content-type": [
38+
"text/javascript; charset\u003dutf-8"
39+
],
40+
"cross-origin-opener-policy-report-only": [
41+
"same-origin; report-to\u003d\"youtube_main\""
42+
],
43+
"date": [
44+
"Mon, 17 Oct 2022 20:46:09 GMT"
45+
],
46+
"expires": [
47+
"Mon, 17 Oct 2022 20:46:09 GMT"
48+
],
49+
"p3p": [
50+
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
51+
],
52+
"permissions-policy": [
53+
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
54+
],
55+
"report-to": [
56+
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
57+
],
58+
"server": [
59+
"ESF"
60+
],
61+
"set-cookie": [
62+
"YSC\u003d6BKzjAdnbq0; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
63+
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dTue, 21-Jan-2020 20:46:09 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
64+
"CONSENT\u003dPENDING+680; expires\u003dWed, 16-Oct-2024 20:46:09 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
65+
],
66+
"strict-transport-security": [
67+
"max-age\u003d31536000"
68+
],
69+
"x-content-type-options": [
70+
"nosniff"
71+
],
72+
"x-frame-options": [
73+
"SAMEORIGIN"
74+
],
75+
"x-xss-protection": [
76+
"0"
77+
]
78+
},
79+
"responseBody": "\n self.addEventListener(\u0027install\u0027, event \u003d\u003e {\n event.waitUntil(self.skipWaiting());\n });\n self.addEventListener(\u0027activate\u0027, event \u003d\u003e {\n event.waitUntil(\n self.clients.claim().then(() \u003d\u003e self.registration.unregister()));\n });\n ",
80+
"latestUrl": "https://www.youtube.com/sw.js"
81+
}
82+
}

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/search/shorts/generated_mock_1.json

Lines changed: 76 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)