From 888de49edd39913116028ac1d173f2b6e0feab09 Mon Sep 17 00:00:00 2001 From: 1fexd <58902674+1fexd@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:28:27 +0200 Subject: [PATCH] feat(Sync for Reddit): Add `Fix video downloads` patch (#710) --- .../FixRedditVideoDownloadPatch.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch.java diff --git a/app/src/main/java/app/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch.java b/app/src/main/java/app/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch.java new file mode 100644 index 0000000000..f1701ae9dd --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch.java @@ -0,0 +1,77 @@ +package app.revanced.integrations.syncforreddit; + +import android.util.Pair; +import androidx.annotation.Nullable; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; + +/** + * @noinspection unused + */ +public class FixRedditVideoDownloadPatch { + private static @Nullable Pair getBestMpEntry(Element element) { + var representations = element.getElementsByTagName("Representation"); + var entries = new ArrayList>(); + + for (int i = 0; i < representations.getLength(); i++) { + Element representation = (Element) representations.item(i); + var bandwidthStr = representation.getAttribute("bandwidth"); + try { + var bandwidth = Integer.parseInt(bandwidthStr); + var baseUrl = representation.getElementsByTagName("BaseURL").item(0); + if (baseUrl != null) { + entries.add(new Pair<>(bandwidth, baseUrl.getTextContent())); + } + } catch (NumberFormatException ignored) { + } + } + + if (entries.isEmpty()) { + return null; + } + + Collections.sort(entries, (e1, e2) -> e2.first - e1.first); + return entries.get(0); + } + + private static String[] parse(byte[] data) throws ParserConfigurationException, IOException, SAXException { + var adaptionSets = DocumentBuilderFactory + .newInstance() + .newDocumentBuilder() + .parse(new ByteArrayInputStream(data)) + .getElementsByTagName("AdaptationSet"); + + String videoUrl = null; + String audioUrl = null; + + for (int i = 0; i < adaptionSets.getLength(); i++) { + Element element = (Element) adaptionSets.item(i); + var contentType = element.getAttribute("contentType"); + var bestEntry = getBestMpEntry(element); + if (bestEntry == null) continue; + + if (contentType.equalsIgnoreCase("video")) { + videoUrl = bestEntry.second; + } else if (contentType.equalsIgnoreCase("audio")) { + audioUrl = bestEntry.second; + } + } + + return new String[]{videoUrl, audioUrl}; + } + + public static String[] getLinks(byte[] data) { + try { + return parse(data); + } catch (ParserConfigurationException | IOException | SAXException e) { + return new String[]{null, null}; + } + } +}