@@ -15,6 +15,7 @@ import packageDetails from '../../../../package.json'
15
15
import {
16
16
buildVTTFileLocally ,
17
17
copyToClipboard ,
18
+ extractNumberFromString ,
18
19
formatDurationAsTimestamp ,
19
20
formatNumber ,
20
21
showToast
@@ -356,31 +357,12 @@ export default defineComponent({
356
357
return
357
358
}
358
359
359
- const playabilityStatus = result . playability_status
360
-
361
- // The apostrophe is intentionally that one (char code 8217), because that is the one YouTube uses
362
- const BOT_MESSAGE = 'Sign in to confirm you’re not a bot'
363
-
364
- if ( playabilityStatus . status === 'UNPLAYABLE' || ( playabilityStatus . status === 'LOGIN_REQUIRED' && playabilityStatus . reason === BOT_MESSAGE ) ) {
365
- if ( playabilityStatus . reason === BOT_MESSAGE ) {
366
- throw new Error ( this . $t ( 'Video.IP block' ) )
367
- }
368
-
369
- let errorText = `[${ playabilityStatus . status } ] ${ playabilityStatus . reason } `
370
-
371
- if ( playabilityStatus . error_screen ) {
372
- errorText += `: ${ playabilityStatus . error_screen . subreason . text } `
373
- }
374
-
375
- throw new Error ( errorText )
376
- }
377
-
378
360
// extract localised title first and fall back to the not localised one
379
361
this . videoTitle = result . primary_info ?. title . text ?? result . basic_info . title
380
- this . videoViewCount = result . basic_info . view_count
362
+ this . videoViewCount = result . basic_info . view_count ?? extractNumberFromString ( result . primary_info . view_count . text )
381
363
382
- this . channelId = result . basic_info . channel_id
383
- this . channelName = result . basic_info . author
364
+ this . channelId = result . basic_info . channel_id ?? result . secondary_info . owner ?. author . id
365
+ this . channelName = result . basic_info . author ?? result . secondary_info . owner ?. author . name
384
366
385
367
if ( result . secondary_info . owner ?. author ) {
386
368
this . channelThumbnail = result . secondary_info . owner . author . best_thumbnail ?. url ?? ''
@@ -396,8 +378,13 @@ export default defineComponent({
396
378
channelId : this . channelId
397
379
} )
398
380
399
- // `result.page[0].microformat.publish_date` example value: `2023-08-12T08:59:59-07:00`
400
- this . videoPublished = new Date ( result . page [ 0 ] . microformat . publish_date ) . getTime ( )
381
+ if ( result . page [ 0 ] . microformat ?. publish_date ) {
382
+ // `result.page[0].microformat.publish_date` example value: `2023-08-12T08:59:59-07:00`
383
+ this . videoPublished = new Date ( result . page [ 0 ] . microformat . publish_date ) . getTime ( )
384
+ } else {
385
+ // text date Jan 1, 2000, not as accurate but better than nothing
386
+ this . videoPublished = new Date ( result . primary_info . published ) . getTime ( )
387
+ }
401
388
402
389
if ( result . secondary_info ?. description . runs ) {
403
390
try {
@@ -421,7 +408,7 @@ export default defineComponent({
421
408
this . thumbnail = `https://i.ytimg.com/vi/${ this . videoId } /maxres3.jpg`
422
409
break
423
410
default :
424
- this . thumbnail = result . basic_info . thumbnail [ 0 ] . url
411
+ this . thumbnail = result . basic_info . thumbnail ?. [ 0 ] . url ?? `https://i.ytimg.com/vi/ ${ this . videoId } /maxresdefault.jpg`
425
412
break
426
413
}
427
414
@@ -465,7 +452,7 @@ export default defineComponent({
465
452
} )
466
453
}
467
454
} else {
468
- chapters = this . extractChaptersFromDescription ( result . basic_info . short_description )
455
+ chapters = this . extractChaptersFromDescription ( result . basic_info . short_description ?? result . secondary_info . description . text )
469
456
}
470
457
471
458
if ( chapters . length > 0 ) {
@@ -481,6 +468,51 @@ export default defineComponent({
481
468
482
469
this . videoChapters = chapters
483
470
471
+ const playabilityStatus = result . playability_status
472
+
473
+ // The apostrophe is intentionally that one (char code 8217), because that is the one YouTube uses
474
+ const BOT_MESSAGE = 'Sign in to confirm you’re not a bot'
475
+
476
+ if ( playabilityStatus . status === 'UNPLAYABLE' || playabilityStatus . status === 'LOGIN_REQUIRED' ) {
477
+ if ( playabilityStatus . error_screen ?. offer_id === 'sponsors_only_video' ) {
478
+ // Members-only videos can only be watched while logged into a Google account that is a paid channel member
479
+ // so there is no point trying any other backends as it will always fail
480
+ this . errorMessage = this . $t ( 'Video.MembersOnly' )
481
+ this . customErrorIcon = [ 'fas' , 'money-check-dollar' ]
482
+ this . isLoading = false
483
+ this . updateTitle ( )
484
+ return
485
+ } else if ( playabilityStatus . reason === 'Sign in to confirm your age' || ( result . has_trailer && result . getTrailerInfo ( ) === null ) ) {
486
+ // Age-restricted videos can only be watched while logged into a Google account that is age-verified
487
+ // so there is no point trying any other backends as it will always fail
488
+ this . errorMessage = this . $t ( 'Video.AgeRestricted' )
489
+ this . isLoading = false
490
+ this . updateTitle ( )
491
+ return
492
+ }
493
+
494
+ let errorText
495
+
496
+ if ( playabilityStatus . reason === BOT_MESSAGE || playabilityStatus . reason === 'Please sign in' ) {
497
+ errorText = this . $t ( 'Video.IP block' )
498
+ } else {
499
+ errorText = `[${ playabilityStatus . status } ] ${ playabilityStatus . reason } `
500
+
501
+ if ( playabilityStatus . error_screen ?. subreason ) {
502
+ errorText += `: ${ playabilityStatus . error_screen . subreason . text } `
503
+ }
504
+ }
505
+
506
+ if ( this . backendFallback ) {
507
+ throw new Error ( errorText )
508
+ } else {
509
+ this . errorMessage = errorText
510
+ this . isLoading = false
511
+ this . updateTitle ( )
512
+ return
513
+ }
514
+ }
515
+
484
516
if ( ! this . hideLiveChat && this . isLive && result . livechat ) {
485
517
this . liveChat = result . getLiveChat ( )
486
518
} else {
@@ -700,7 +732,6 @@ export default defineComponent({
700
732
}
701
733
}
702
734
703
- // this.errorMessage = 'Test error message'
704
735
this . isLoading = false
705
736
this . updateTitle ( )
706
737
} catch ( err ) {
0 commit comments