File indexing completed on 2025-02-02 04:47:49

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Soul Trace <S-trace@list.ru>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 package org.kde.kdeconnect.Helpers;
0008 
0009 import org.apache.commons.lang3.StringUtils;
0010 
0011 import java.net.MalformedURLException;
0012 import java.net.URL;
0013 import java.util.Locale;
0014 
0015 public class VideoUrlsHelper {
0016     private static final int SECONDS_IN_MINUTE = 60;
0017     private static final int MINUTES_IN_HOUR = 60;
0018     private static final int SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR;
0019 
0020     public static URL formatUriWithSeek(String address, long position)
0021             throws MalformedURLException {
0022         URL url = new URL(address);
0023         position /= 1000; // Convert ms to seconds
0024         if (position <= 0) {
0025             return url; // nothing to do
0026         }
0027         String host = url.getHost().toLowerCase();
0028 
0029         // Most common settings as defaults:
0030         String parameter = "t="; // Characters before timestamp
0031         String timestamp = Long.toString(position); // Timestamp itself
0032         String trailer = ""; // Characters after timestamp
0033         // true  - search/add to query URL part (between ? and # signs),
0034         // false - search/add timestamp to ref (anchor) URL part (after # sign),
0035         boolean inQuery = true;
0036         // true - We know how to format URL with seek timestamp, false - not
0037         boolean seekUrl = false;
0038 
0039         // Override defaults if necessary
0040         if (StringUtils.containsAny(host, "youtube.com", "youtu.be", "pornhub.com")) {
0041             seekUrl = true;
0042             url = stripTimestampS(url, parameter, trailer, inQuery);
0043         } else if (host.contains("vimeo.com")) {
0044             seekUrl = true;
0045             trailer = "s";
0046             url = stripTimestampS(url, parameter, trailer, inQuery);
0047         } else if (host.contains("dailymotion.com")) {
0048             seekUrl = true;
0049             parameter = "start=";
0050             url = stripTimestampS(url, parameter, trailer, inQuery);
0051         } else if (host.contains("twitch.tv")) {
0052             seekUrl = true;
0053             timestamp = formatTimestampHMS(position, true);
0054             url = stripTimestampHMS(url, parameter, trailer, inQuery);
0055         }
0056 
0057         if (seekUrl) {
0058             url = formatUrlWithSeek(url, timestamp, parameter, trailer, inQuery);
0059         }
0060         return url;
0061     }
0062 
0063     // Returns timestamp in 1h2m34s or 01h02m34s (according to padWithZeroes)
0064     private static String formatTimestampHMS(long seconds, boolean padWithZeroes) {
0065         if (seconds == 0) {
0066             return "0s";
0067         }
0068 
0069         int sec = (int) (seconds % SECONDS_IN_MINUTE);
0070         int min = (int) ((seconds / SECONDS_IN_MINUTE) % MINUTES_IN_HOUR);
0071         int hour = (int) (seconds / SECONDS_IN_HOUR);
0072 
0073         String hours = hour > 0 ? hour + "h" : "";
0074         String mins = min > 0 || hour > 0 ? min + "m" : "";
0075         String secs = sec + "s";
0076 
0077         String value;
0078         if (padWithZeroes) {
0079             String hoursPad = hour > 9 ? "" : "0";
0080             String minsPad = min > 9 ? "" : "0";
0081             String secsPad = sec > 9 ? "" : "0";
0082             value = hoursPad + hours + minsPad + mins + secsPad + secs;
0083         } else {
0084             value = hours + mins + secs;
0085         }
0086         return value;
0087 
0088     }
0089 
0090     // Remove timestamp in 01h02m34s or 1h2m34s or 02m34s or 2m34s or 01s or 1s format.
0091     // Can also nandle rimestamps in 1234s format if called with 's' trailer
0092     private static URL stripTimestampHMS(URL url, String parameter, String trailer, boolean inQuery)
0093             throws MalformedURLException {
0094         String regex = parameter + "([\\d]+[hH])?([\\d]+[mM])?[\\d]+[sS]" + trailer + "&?";
0095         return stripTimestampCommon(url, inQuery, regex);
0096     }
0097 
0098 
0099     // Remove timestamp in 1234 format
0100     private static URL stripTimestampS(URL url, String parameter, String trailer, boolean inQuery)
0101             throws MalformedURLException {
0102         String regex = parameter + "[\\d]+" + trailer + "&?";
0103         return stripTimestampCommon(url, inQuery, regex);
0104     }
0105 
0106     private static URL stripTimestampCommon(URL url, boolean inQuery, String regex)
0107             throws MalformedURLException {
0108         String value;
0109         if (inQuery) {
0110             value = url.getQuery();
0111         } else {
0112             value = url.getRef();
0113         }
0114         if (value == null) {
0115             return url;
0116         }
0117         String newValue = value.replaceAll(regex, "");
0118         String replaced = url.toString().replaceFirst(value, newValue);
0119         if (inQuery && replaced.endsWith("&")) {
0120             replaced = replaced.substring(0, replaced.length() - 1);
0121         }
0122         return new URL(replaced);
0123     }
0124 
0125     private static URL formatUrlWithSeek(URL url, String position, String parameter, String trailer,
0126                                          boolean inQuery) throws MalformedURLException {
0127         String value;
0128         String separator;
0129         String newValue;
0130         if (inQuery) {
0131             value = url.getQuery();
0132             separator = "?";
0133         } else {
0134             value = url.getRef();
0135             separator = "#";
0136         }
0137         if (value == null) {
0138             newValue = String.format(Locale.getDefault(), "%s%s%s%s%s",
0139                     url, separator, parameter, position, trailer);
0140             return new URL(newValue);
0141         }
0142         if (inQuery) {
0143             newValue = String.format(Locale.getDefault(), "%s&%s%s%s",
0144                     value, parameter, position, trailer);
0145         } else {
0146             newValue = String.format(Locale.getDefault(), "%s%s%s",
0147                     parameter, position, trailer);
0148         }
0149         return new URL(url.toString().replaceFirst(value, newValue));
0150     }
0151 }