|
13 | 13 | import org.schabi.newpipe.extractor.utils.Parser; |
14 | 14 | import org.schabi.newpipe.extractor.utils.Utils; |
15 | 15 |
|
| 16 | +import javax.annotation.Nonnull; |
16 | 17 | import javax.annotation.Nullable; |
17 | 18 | import java.time.Instant; |
18 | 19 | import java.time.OffsetDateTime; |
@@ -290,85 +291,86 @@ public long getViewCount() throws ParsingException { |
290 | 291 | return -1; |
291 | 292 | } |
292 | 293 |
|
293 | | - final String viewCount = getTextFromObject(videoInfo.getObject("viewCountText")); |
| 294 | + // Ignore all exceptions, as the view count can be hidden by creators, and so cannot be |
| 295 | + // found in this case |
294 | 296 |
|
295 | | - if (!isNullOrEmpty(viewCount)) { |
| 297 | + final String viewCountText = getTextFromObject(videoInfo.getObject("viewCountText")); |
| 298 | + if (!isNullOrEmpty(viewCountText)) { |
296 | 299 | try { |
297 | | - // These approaches are language dependent |
298 | | - if (viewCount.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { |
299 | | - return 0; |
300 | | - } else if (viewCount.toLowerCase().contains("recommended")) { |
301 | | - return -1; |
302 | | - } |
303 | | - |
304 | | - return Long.parseLong(Utils.removeNonDigitCharacters(viewCount)); |
| 300 | + return getViewCountFromViewCountText(viewCountText, false); |
305 | 301 | } catch (final Exception ignored) { |
306 | | - // Ignore all exceptions, as we can fall back to accessibility data |
307 | 302 | } |
308 | 303 | } |
309 | 304 |
|
310 | 305 | // Try parsing the real view count from accessibility data, if that's not a running |
311 | 306 | // livestream (the view count is returned and not the count of people watching currently |
312 | 307 | // the livestream) |
313 | 308 | if (getStreamType() != StreamType.LIVE_STREAM) { |
314 | | - final String videoInfoTitleAccessibilityData = videoInfo.getObject("title") |
315 | | - .getObject("accessibility") |
316 | | - .getObject("accessibilityData") |
317 | | - .getString("label", ""); |
318 | | - |
319 | | - if (videoInfoTitleAccessibilityData.toLowerCase().endsWith(NO_VIEWS_LOWERCASE)) { |
320 | | - return 0; |
321 | | - } |
322 | | - |
323 | 309 | try { |
324 | | - return Long.parseLong(Utils.removeNonDigitCharacters( |
325 | | - // This approach is language dependent |
326 | | - Parser.matchGroup1(ACCESSIBILITY_DATA_VIEW_COUNT_REGEX, |
327 | | - videoInfoTitleAccessibilityData))); |
| 310 | + return getViewCountFromAccessibilityData(); |
328 | 311 | } catch (final Exception ignored) { |
329 | | - // Ignore all exceptions, as the view count can be hidden by creators, and so |
330 | | - // cannot be found in this case |
331 | 312 | } |
332 | 313 | } |
333 | 314 |
|
334 | 315 | // Fallback to a short view count, always used for livestreams (see why above) |
335 | | - try { |
| 316 | + if (videoInfo.has("videoInfo")) { |
336 | 317 | // Returned in playlists, in the form: view count separator upload date |
337 | | - if (videoInfo.has("videoInfo")) { |
338 | | - final String videoInfoViewCountText = videoInfo.getObject("videoInfo") |
| 318 | + try { |
| 319 | + return getViewCountFromViewCountText(videoInfo.getObject("videoInfo") |
339 | 320 | .getArray("runs") |
340 | 321 | .getObject(0) |
341 | | - .getString("text", ""); |
342 | | - if (videoInfoViewCountText.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { |
343 | | - return 0; |
344 | | - } |
345 | | - |
346 | | - return Utils.mixedNumberWordToLong(videoInfoViewCountText); |
| 322 | + .getString("text", ""), true); |
| 323 | + } catch (final Exception ignored) { |
347 | 324 | } |
| 325 | + } |
348 | 326 |
|
| 327 | + if (videoInfo.has("shortViewCountText")) { |
349 | 328 | // Returned everywhere but in playlists, used by the website to show view counts |
350 | | - if (videoInfo.has("shortViewCountText")) { |
351 | | - final String shortVideoViewCountText = |
| 329 | + try { |
| 330 | + final String shortViewCountText = |
352 | 331 | getTextFromObject(videoInfo.getObject("shortViewCountText")); |
353 | | - if (isNullOrEmpty(shortVideoViewCountText)) { |
354 | | - return -1; |
| 332 | + if (!isNullOrEmpty(shortViewCountText)) { |
| 333 | + return getViewCountFromViewCountText(shortViewCountText, true); |
355 | 334 | } |
356 | | - |
357 | | - if (shortVideoViewCountText.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { |
358 | | - return 0; |
359 | | - } |
360 | | - |
361 | | - return Utils.mixedNumberWordToLong(shortVideoViewCountText); |
| 335 | + } catch (final Exception ignored) { |
362 | 336 | } |
363 | | - } catch (final Exception ignored) { |
364 | | - // Ignore all exceptions, as the view count can be hidden by creators, and so cannot be |
365 | | - // found in this case |
366 | 337 | } |
367 | 338 |
|
368 | 339 | // No view count extracted: return -1, as the view count can be hidden by creators on videos |
369 | 340 | return -1; |
370 | 341 | } |
371 | 342 |
|
| 343 | + private long getViewCountFromViewCountText(@Nonnull final String viewCountText, |
| 344 | + final boolean isMixedNumber) |
| 345 | + throws NumberFormatException, ParsingException { |
| 346 | + // These approaches are language dependent |
| 347 | + if (viewCountText.toLowerCase().contains(NO_VIEWS_LOWERCASE)) { |
| 348 | + return 0; |
| 349 | + } else if (viewCountText.toLowerCase().contains("recommended")) { |
| 350 | + return -1; |
| 351 | + } |
| 352 | + |
| 353 | + return isMixedNumber ? Utils.mixedNumberWordToLong(viewCountText) |
| 354 | + : Long.parseLong(Utils.removeNonDigitCharacters(viewCountText)); |
| 355 | + } |
| 356 | + |
| 357 | + private long getViewCountFromAccessibilityData() |
| 358 | + throws NumberFormatException, Parser.RegexException { |
| 359 | + // These approaches are language dependent |
| 360 | + final String videoInfoTitleAccessibilityData = videoInfo.getObject("title") |
| 361 | + .getObject("accessibility") |
| 362 | + .getObject("accessibilityData") |
| 363 | + .getString("label", ""); |
| 364 | + |
| 365 | + if (videoInfoTitleAccessibilityData.toLowerCase().endsWith(NO_VIEWS_LOWERCASE)) { |
| 366 | + return 0; |
| 367 | + } |
| 368 | + |
| 369 | + return Long.parseLong(Utils.removeNonDigitCharacters( |
| 370 | + Parser.matchGroup1(ACCESSIBILITY_DATA_VIEW_COUNT_REGEX, |
| 371 | + videoInfoTitleAccessibilityData))); |
| 372 | + } |
| 373 | + |
372 | 374 | @Override |
373 | 375 | public String getThumbnailUrl() throws ParsingException { |
374 | 376 | return getThumbnailUrlFromInfoItem(videoInfo); |
|
0 commit comments