Skip to content

Commit b8e12dd

Browse files
committed
[YouTube] Implement emergency meta info
YouTube provides that meta info panel when users search for really sensitive content like suicide (e.g. "blue whale"). It contains: - an encouragement as title (e.g. "We are with you") - a phone number as action - details about how to call the phone number (e.g. availability) - an url pointing to the website of an association Also add a test that just checks if a meta info is properly extracted
1 parent 91419ec commit b8e12dd

2 files changed

Lines changed: 80 additions & 4 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,16 @@
2525
import static org.schabi.newpipe.extractor.utils.Utils.HTTPS;
2626
import static org.schabi.newpipe.extractor.utils.Utils.getStringResultFromRegexArray;
2727
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
28+
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
2829

2930
import com.grack.nanojson.JsonArray;
3031
import com.grack.nanojson.JsonBuilder;
3132
import com.grack.nanojson.JsonObject;
3233
import com.grack.nanojson.JsonParser;
3334
import com.grack.nanojson.JsonParserException;
3435
import com.grack.nanojson.JsonWriter;
35-
import org.jsoup.nodes.Entities;
3636

37+
import org.jsoup.nodes.Entities;
3738
import org.schabi.newpipe.extractor.Image;
3839
import org.schabi.newpipe.extractor.Image.ResolutionLevel;
3940
import org.schabi.newpipe.extractor.MetaInfo;
@@ -71,6 +72,7 @@
7172
import java.util.Optional;
7273
import java.util.Random;
7374
import java.util.Set;
75+
import java.util.function.Consumer;
7476
import java.util.regex.Pattern;
7577
import java.util.stream.Collectors;
7678
import java.util.stream.Stream;
@@ -1080,6 +1082,16 @@ public static String getAttributedDescription(
10801082
.replaceAll(" {2}", "  ");
10811083
}
10821084

1085+
@Nonnull
1086+
public static String getTextFromObjectOrThrow(final JsonObject textObject, final String error)
1087+
throws ParsingException {
1088+
final String result = getTextFromObject(textObject);
1089+
if (result == null) {
1090+
throw new ParsingException("Could not extract text: " + error);
1091+
}
1092+
return result;
1093+
}
1094+
10831095
@Nullable
10841096
public static String getTextFromObject(final JsonObject textObject) {
10851097
return getTextFromObject(textObject, false);
@@ -1664,11 +1676,16 @@ public static List<MetaInfo> getMetaInfo(@Nonnull final JsonArray contents)
16641676
.getObject("infoPanelContentRenderer")));
16651677
}
16661678
if (sectionContent.has("clarificationRenderer")) {
1667-
metaInfo.add(getClarificationRendererContent(sectionContent
1679+
metaInfo.add(getClarificationRenderer(sectionContent
16681680
.getObject("clarificationRenderer")
16691681
));
16701682
}
1671-
1683+
if (sectionContent.has("emergencyOneboxRenderer")) {
1684+
getEmergencyOneboxRenderer(
1685+
sectionContent.getObject("emergencyOneboxRenderer"),
1686+
metaInfo::add
1687+
);
1688+
}
16721689
}
16731690
}
16741691
}
@@ -1709,7 +1726,7 @@ private static MetaInfo getInfoPanelContent(@Nonnull final JsonObject infoPanelC
17091726
}
17101727

17111728
@Nonnull
1712-
private static MetaInfo getClarificationRendererContent(
1729+
private static MetaInfo getClarificationRenderer(
17131730
@Nonnull final JsonObject clarificationRenderer) throws ParsingException {
17141731
final MetaInfo metaInfo = new MetaInfo();
17151732

@@ -1762,6 +1779,55 @@ private static MetaInfo getClarificationRendererContent(
17621779
return metaInfo;
17631780
}
17641781

1782+
@Nonnull
1783+
private static void getEmergencyOneboxRenderer(
1784+
@Nonnull final JsonObject emergencyOneboxRenderer,
1785+
final Consumer<MetaInfo> addMetaInfo
1786+
) throws ParsingException {
1787+
final List<JsonObject> supportRenderers = emergencyOneboxRenderer.entrySet().stream()
1788+
.filter((a) -> a.getValue() instanceof JsonObject
1789+
&& ((JsonObject) a.getValue()).has("singleActionEmergencySupportRenderer"))
1790+
.map((a) -> ((JsonObject) a.getValue())
1791+
.getObject("singleActionEmergencySupportRenderer"))
1792+
.collect(Collectors.toList());
1793+
1794+
if (supportRenderers.isEmpty()) {
1795+
throw new ParsingException("Could not extract any meta info from emergency renderer");
1796+
}
1797+
1798+
for (final JsonObject r : supportRenderers) {
1799+
final MetaInfo metaInfo = new MetaInfo();
1800+
1801+
// usually an encouragement like "We are with you"
1802+
final String title = getTextFromObjectOrThrow(r.getObject("title"), "title");
1803+
// usually a phone number
1804+
final String action = getTextFromObjectOrThrow(r.getObject("actionText"), "action");
1805+
// usually details about the phone number
1806+
final String details = getTextFromObjectOrThrow(r.getObject("detailsText"), "details");
1807+
// usually the name of an association
1808+
final String urlText = getTextFromObjectOrThrow(r.getObject("navigationText"),
1809+
"urlText");
1810+
1811+
metaInfo.setTitle(title);
1812+
metaInfo.setContent(new Description(details + "\n" + action, Description.PLAIN_TEXT));
1813+
metaInfo.addUrlText(urlText);
1814+
1815+
// usually the webpage of the association
1816+
final String url = getUrlFromNavigationEndpoint(r.getObject("navigationEndpoint"));
1817+
if (url == null) {
1818+
throw new ParsingException("Could not extract emergency renderer url");
1819+
}
1820+
1821+
try {
1822+
metaInfo.addUrl(new URL(replaceHttpWithHttps(url)));
1823+
} catch (final MalformedURLException e) {
1824+
throw new ParsingException("Could not parse emergency renderer url", e);
1825+
}
1826+
1827+
addMetaInfo.accept(metaInfo);
1828+
}
1829+
}
1830+
17651831
/**
17661832
* Sometimes, YouTube provides URLs which use Google's cache. They look like
17671833
* {@code https://webcache.googleusercontent.com/search?q=cache:CACHED_URL}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,5 +446,15 @@ public static void setUp() throws Exception {
446446
@Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
447447
@Override public String expectedSearchString() { return QUERY; }
448448
@Nullable @Override public String expectedSearchSuggestion() { return null; }
449+
450+
@Test
451+
@Override
452+
public void testMetaInfo() throws Exception {
453+
final List<MetaInfo> metaInfoList = extractor().getMetaInfo();
454+
455+
// the meta info will have different text and language depending on where in the world
456+
// the connection is established from, so we can't check the actual content
457+
assertEquals(1, metaInfoList.size());
458+
}
449459
}
450460
}

0 commit comments

Comments
 (0)