|
30 | 30 | import java.net.MalformedURLException; |
31 | 31 | import java.net.URL; |
32 | 32 | import java.util.*; |
| 33 | +import java.util.regex.Matcher; |
| 34 | +import java.util.regex.Pattern; |
33 | 35 |
|
34 | 36 | /* |
35 | 37 | * Created by Christian Schabesberger on 06.08.15. |
@@ -162,14 +164,54 @@ public String getDescription() throws ParsingException { |
162 | 164 | } |
163 | 165 | } |
164 | 166 |
|
| 167 | + // onclick="yt.www.watch.player.seekTo(0*3600+00*60+00);return false;" |
| 168 | + // :00 is NOT recognized as a timestamp in description or comments. |
| 169 | + // 0:00 is recognized in both description and comments. |
| 170 | + // https://www.youtube.com/watch?v=4cccfDXu1vA |
| 171 | + private final static Pattern DESCRIPTION_TIMESTAMP_ONCLICK_REGEX = Pattern.compile( |
| 172 | + "seekTo\\(" |
| 173 | + + "(?:(\\d+)\\*3600\\+)?" // hours? |
| 174 | + + "(\\d+)\\*60\\+" // minutes |
| 175 | + + "(\\d+)" // seconds |
| 176 | + + "\\)"); |
| 177 | + |
| 178 | + @SafeVarargs |
| 179 | + private static <T> T coalesce(T... args) { |
| 180 | + for (T arg : args) { |
| 181 | + if (arg != null) return arg; |
| 182 | + } |
| 183 | + throw new IllegalArgumentException("all arguments to coalesce() were null"); |
| 184 | + } |
| 185 | + |
165 | 186 | private String parseHtmlAndGetFullLinks(String descriptionHtml) |
166 | 187 | throws MalformedURLException, UnsupportedEncodingException, ParsingException { |
167 | 188 | final Document description = Jsoup.parse(descriptionHtml, getUrl()); |
168 | 189 | for(Element a : description.select("a")) { |
169 | 190 | final String rawUrl = a.attr("abs:href"); |
170 | 191 | final URL redirectLink = new URL(rawUrl); |
171 | | - final String queryString = redirectLink.getQuery(); |
172 | | - if(queryString != null) { |
| 192 | + |
| 193 | + final Matcher onClickTimestamp; |
| 194 | + final String queryString; |
| 195 | + if ((onClickTimestamp = DESCRIPTION_TIMESTAMP_ONCLICK_REGEX.matcher(a.attr("onclick"))) |
| 196 | + .find()) { |
| 197 | + a.removeAttr("onclick"); |
| 198 | + |
| 199 | + String hours = coalesce(onClickTimestamp.group(1), "0"); |
| 200 | + String minutes = onClickTimestamp.group(2); |
| 201 | + String seconds = onClickTimestamp.group(3); |
| 202 | + |
| 203 | + int timestamp = 0; |
| 204 | + timestamp += Integer.parseInt(hours) * 3600; |
| 205 | + timestamp += Integer.parseInt(minutes) * 60; |
| 206 | + timestamp += Integer.parseInt(seconds); |
| 207 | + |
| 208 | + String setTimestamp = "&t=" + timestamp; |
| 209 | + |
| 210 | + // Even after clicking https://youtu.be/...?t=6, |
| 211 | + // getUrl() is https://www.youtube.com/watch?v=..., never youtu.be, never &t=. |
| 212 | + a.attr("href", getUrl() + setTimestamp); |
| 213 | + |
| 214 | + } else if((queryString = redirectLink.getQuery()) != null) { |
173 | 215 | // if the query string is null we are not dealing with a redirect link, |
174 | 216 | // so we don't need to override it. |
175 | 217 | final String link = |
|
0 commit comments