47
47
// @match *://*.bilibili.com/*
48
48
// @match *://my.mail.ru/*
49
49
// @match *://*.bitchute.com/*
50
- // @match *://*.coursera.org/learn/ *
50
+ // @match *://*.coursera.org/*
51
51
// @match *://*.udemy.com/course/*
52
52
// @match *://*.tiktok.com/*
53
53
// @match *://*.douyin.com/*
@@ -1574,7 +1574,7 @@ class Chaimu {
1574
1574
defaultDuration : 343 ,
1575
1575
minChunkSize : 5295308 ,
1576
1576
loggerLevel : 1 ,
1577
- version : "2.1.7 " ,
1577
+ version : "2.1.8 " ,
1578
1578
} ) ;
1579
1579
1580
1580
; // ./node_modules/@vot .js/shared/dist/types/logger.js
@@ -5452,8 +5452,7 @@ class PatreonHelper extends BaseHelper {
5452
5452
class RedditHelper extends BaseHelper {
5453
5453
API_ORIGIN = "https://www.reddit.com" ;
5454
5454
async getContentUrl ( videoId ) {
5455
- if ( ! this . service . additionalData ||
5456
- this . service . additionalData !== "old" ) {
5455
+ if ( this . service ?. additionalData !== "old" ) {
5457
5456
return document . querySelector ( "shreddit-player-2" ) ?. src ;
5458
5457
}
5459
5458
const playerEl = document . querySelector ( "[data-hls-url]" ) ;
@@ -5855,8 +5854,8 @@ class CoursehunterLikeHelper extends BaseHelper {
5855
5854
if ( courseId !== undefined ) {
5856
5855
return String ( courseId ) ;
5857
5856
}
5858
- const inputEl = document . querySelector ( 'input[name="course_id"]' ) ;
5859
- return inputEl ? inputEl . value : undefined ;
5857
+ return document . querySelector ( 'input[name="course_id"]' )
5858
+ ? .value ;
5860
5859
}
5861
5860
async getLessonsData ( courseId ) {
5862
5861
const lessons = window . lessons ;
@@ -6074,46 +6073,69 @@ class SapHelper extends BaseHelper {
6074
6073
}
6075
6074
}
6076
6075
6077
- ; // ./node_modules/@vot .js/ext/dist/helpers/linkedin .js
6076
+ ; // ./node_modules/@vot .js/ext/dist/helpers/videojs .js
6078
6077
6079
6078
6080
6079
6081
- class LinkedinHelper extends BaseHelper {
6080
+ class VideoJSHelper extends BaseHelper {
6081
+ SUBTITLE_SOURCE = "videojs" ;
6082
+ SUBTITLE_FORMAT = "vtt" ;
6082
6083
static getPlayer ( ) {
6083
- const videoEl = document . querySelector ( ".video-js" ) ;
6084
- if ( ! videoEl ) {
6085
- return undefined ;
6086
- }
6087
- return videoEl . player ;
6084
+ return document . querySelector ( ".video-js" )
6085
+ ?. player ;
6088
6086
}
6089
- async getVideoData ( videoId ) {
6087
+ getVideoDataByPlayer ( videoId ) {
6090
6088
try {
6091
- const player = LinkedinHelper . getPlayer ( ) ;
6089
+ const player = VideoJSHelper . getPlayer ( ) ;
6092
6090
if ( ! player ) {
6093
6091
throw new Error ( `Video player doesn't have player option, videoId ${ videoId } ` ) ;
6094
6092
}
6095
- const { cache_ : { sources, duration } , textTracks_ : { tracks_ } , } = player ;
6096
- const videoUrl = sources . find ( ( source ) => source . type === "video/mp4" ) ;
6093
+ const duration = player . duration ( ) ;
6094
+ const sources = Array . isArray ( player . currentSources )
6095
+ ? player . currentSources
6096
+ : player . getCache ( ) ?. sources ;
6097
+ const { tracks_ : tracks } = player . textTracks ( ) ;
6098
+ const videoUrl = sources . find ( ( source ) => source . type === "video/mp4" || source . type === "video/webm" ) ;
6097
6099
if ( ! videoUrl ) {
6098
6100
throw new Error ( `Failed to find video url for videoID ${ videoId } ` ) ;
6099
6101
}
6100
- const url = new URL ( videoUrl . src ) ;
6101
- const subtitles = tracks_ . map ( ( track ) => ( {
6102
+ const subtitles = tracks
6103
+ . filter ( ( track ) => track . src )
6104
+ . map ( ( track ) => ( {
6102
6105
language : normalizeLang ( track . language ) ,
6103
- source : "linkedin" ,
6104
- format : "vtt" ,
6106
+ source : this . SUBTITLE_SOURCE ,
6107
+ format : this . SUBTITLE_FORMAT ,
6105
6108
url : track . src ,
6106
6109
} ) ) ;
6107
6110
return {
6108
- url : proxyMedia ( url ) ,
6111
+ url : videoUrl . src ,
6109
6112
duration,
6110
6113
subtitles,
6111
6114
} ;
6112
6115
}
6113
6116
catch ( err ) {
6114
- Logger . error ( "Failed to get linkedin video data" , err . message ) ;
6117
+ Logger . error ( "Failed to get videojs video data" , err . message ) ;
6118
+ return undefined ;
6119
+ }
6120
+ }
6121
+ }
6122
+
6123
+ ; // ./node_modules/@vot .js/ext/dist/helpers/linkedin.js
6124
+
6125
+
6126
+ class LinkedinHelper extends VideoJSHelper {
6127
+ SUBTITLE_SOURCE = "linkedin" ;
6128
+ async getVideoData ( videoId ) {
6129
+ const data = this . getVideoDataByPlayer ( videoId ) ;
6130
+ if ( ! data ) {
6115
6131
return undefined ;
6116
6132
}
6133
+ const { url, duration, subtitles } = data ;
6134
+ return {
6135
+ url : proxyMedia ( new URL ( url ) ) ,
6136
+ duration,
6137
+ subtitles,
6138
+ } ;
6117
6139
}
6118
6140
async getVideoId ( url ) {
6119
6141
return / \/ l e a r n i n g \/ ( ( [ ^ / ] + ) \/ ( [ ^ / ] + ) ) / . exec ( url . pathname ) ?. [ 1 ] ;
@@ -6531,23 +6553,12 @@ class VKHelper extends BaseHelper {
6531
6553
return undefined ;
6532
6554
}
6533
6555
const videoView = Videoview ;
6534
- return videoView . getPlayerObject
6535
- ? videoView . getPlayerObject . call ( undefined )
6536
- : undefined ;
6537
- }
6538
- getDefault ( videoId ) {
6539
- if ( ! this . service ) {
6540
- return undefined ;
6541
- }
6542
- return {
6543
- url : this . service . url + videoId ,
6544
- duration : undefined ,
6545
- } ;
6556
+ return videoView ?. getPlayerObject ?. call ( undefined ) ;
6546
6557
}
6547
6558
async getVideoData ( videoId ) {
6548
6559
const player = VKHelper . getPlayer ( ) ;
6549
6560
if ( ! player ) {
6550
- return this . getDefault ( videoId ) ;
6561
+ return this . returnBaseData ( videoId ) ;
6551
6562
}
6552
6563
try {
6553
6564
const { description : descriptionHTML , duration, md_title : title , } = player . vars ;
@@ -6577,7 +6588,7 @@ class VKHelper extends BaseHelper {
6577
6588
}
6578
6589
catch ( err ) {
6579
6590
Logger . error ( `Failed to get VK video data, because: ${ err . message } ` ) ;
6580
- return this . getDefault ( videoId ) ;
6591
+ return this . returnBaseData ( videoId ) ;
6581
6592
}
6582
6593
}
6583
6594
async getVideoId ( url ) {
@@ -7168,8 +7179,9 @@ class UdemyHelper extends BaseHelper {
7168
7179
7169
7180
7170
7181
7171
- class CourseraHelper extends BaseHelper {
7182
+ class CourseraHelper extends VideoJSHelper {
7172
7183
API_ORIGIN = "https://www.coursera.org/api" ;
7184
+ SUBTITLE_SOURCE = "coursera" ;
7173
7185
async getCourseData ( courseId ) {
7174
7186
try {
7175
7187
const response = await this . fetch ( `${ this . API_ORIGIN } /onDemandCourses.v1/${ courseId } ` ) ;
@@ -7181,74 +7193,75 @@ class CourseraHelper extends BaseHelper {
7181
7193
return undefined ;
7182
7194
}
7183
7195
}
7184
- getPlayer ( ) {
7185
- return document . querySelector ( ".vjs-v8" ) ;
7186
- }
7187
- getPlayerData ( ) {
7188
- return this . getPlayer ( ) ?. player ;
7189
- }
7190
- findVideoUrl ( sources ) {
7191
- return sources ?. find ( ( src ) => src . type === "video/mp4" ) ?. src ;
7192
- }
7193
- findSubtitleUrl ( captions , detectedLanguage ) {
7194
- let subtitle = captions ?. find ( ( caption ) => normalizeLang ( caption . srclang ) === detectedLanguage ) ;
7195
- if ( ! subtitle ) {
7196
- subtitle =
7197
- captions ?. find ( ( caption ) => normalizeLang ( caption . srclang ) === "en" ) ||
7198
- captions ?. [ 0 ] ;
7199
- }
7200
- return subtitle ?. src ;
7196
+ static getPlayer ( ) {
7197
+ return super . getPlayer ( ) ;
7201
7198
}
7202
7199
async getVideoData ( videoId ) {
7203
- const playerData = this . getPlayerData ( ) ;
7204
- if ( ! playerData ) {
7205
- Logger . error ( "Failed to find player data" ) ;
7200
+ const data = this . getVideoDataByPlayer ( videoId ) ;
7201
+ if ( ! data ) {
7206
7202
return undefined ;
7207
7203
}
7208
- const { cache_ : { duration } , options_ : { courseId, tracks, sources } , } = playerData ;
7209
- const videoUrl = this . findVideoUrl ( sources ) ;
7210
- if ( ! videoUrl ) {
7211
- Logger . error ( "Failed to find .mp4 video file in sources" , sources ) ;
7212
- return undefined ;
7204
+ const { options_ : options } = CourseraHelper . getPlayer ( ) ?? { } ;
7205
+ if ( ! data . subtitles ?. length && options ) {
7206
+ data . subtitles = options . tracks . map ( ( track ) => ( {
7207
+ url : track . src ,
7208
+ language : normalizeLang ( track . srclang ) ,
7209
+ source : this . SUBTITLE_SOURCE ,
7210
+ format : this . SUBTITLE_FORMAT ,
7211
+ } ) ) ;
7212
+ }
7213
+ const courseId = options ?. courseId ;
7214
+ if ( ! courseId ) {
7215
+ return data ;
7213
7216
}
7214
7217
let courseLang = "en" ;
7215
7218
const courseData = await this . getCourseData ( courseId ) ;
7216
7219
if ( courseData ) {
7217
7220
const { primaryLanguageCodes : [ primaryLangauge ] , } = courseData ;
7218
- courseLang = primaryLangauge ? normalizeLang ( primaryLangauge ) : "en" ;
7221
+ courseLang = primaryLangauge
7222
+ ? normalizeLang ( primaryLangauge )
7223
+ : "en" ;
7219
7224
}
7220
7225
if ( ! availableLangs . includes ( courseLang ) ) {
7221
7226
courseLang = "en" ;
7222
7227
}
7223
- const subtitleUrl = this . findSubtitleUrl ( tracks , courseLang ) ;
7228
+ const subtitleItem = data . subtitles . find ( ( subtitle ) => subtitle . language === courseLang ) ??
7229
+ data . subtitles ?. [ 0 ] ;
7230
+ const subtitleUrl = subtitleItem ?. url ;
7224
7231
if ( ! subtitleUrl ) {
7225
- Logger . warn ( "Failed to find subtitle file in tracks" , tracks ) ;
7226
- }
7232
+ Logger . warn ( "Failed to find any subtitle file" ) ;
7233
+ }
7234
+ const { url, duration } = data ;
7235
+ const translationHelp = subtitleUrl
7236
+ ? [
7237
+ {
7238
+ target : "subtitles_file_url" ,
7239
+ targetUrl : subtitleUrl ,
7240
+ } ,
7241
+ {
7242
+ target : "video_file_url" ,
7243
+ targetUrl : url ,
7244
+ } ,
7245
+ ]
7246
+ : null ;
7227
7247
return {
7228
7248
...( subtitleUrl
7229
7249
? {
7230
7250
url : this . service ?. url + videoId ,
7231
- translationHelp : [
7232
- {
7233
- target : "subtitles_file_url" ,
7234
- targetUrl : subtitleUrl ,
7235
- } ,
7236
- {
7237
- target : "video_file_url" ,
7238
- targetUrl : videoUrl ,
7239
- } ,
7240
- ] ,
7251
+ translationHelp,
7241
7252
}
7242
7253
: {
7243
- url : videoUrl ,
7244
- translationHelp : null ,
7254
+ url,
7255
+ translationHelp,
7245
7256
} ) ,
7246
7257
detectedLanguage : courseLang ,
7247
7258
duration,
7248
7259
} ;
7249
7260
}
7250
7261
async getVideoId ( url ) {
7251
- return / l e a r n \/ ( [ ^ / ] + ) \/ l e c t u r e \/ ( [ ^ / ] + ) / . exec ( url . pathname ) ?. [ 0 ] ;
7262
+ const matched = / l e a r n \/ ( [ ^ / ] + ) \/ l e c t u r e \/ ( [ ^ / ] + ) / . exec ( url . pathname ) ??
7263
+ / l e c t u r e \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) / . exec ( url . pathname ) ;
7264
+ return matched ?. [ 0 ] ;
7252
7265
}
7253
7266
}
7254
7267
@@ -7265,18 +7278,18 @@ class CloudflareStreamHelper extends BaseHelper {
7265
7278
7266
7279
7267
7280
class DouyinHelper extends BaseHelper {
7268
- getPlayer ( ) {
7281
+ static getPlayer ( ) {
7269
7282
if ( typeof player === "undefined" ) {
7270
7283
return undefined ;
7271
7284
}
7272
7285
return player ;
7273
7286
}
7274
7287
async getVideoData ( videoId ) {
7275
- const xgPlayer = this . getPlayer ( ) ;
7288
+ const xgPlayer = DouyinHelper . getPlayer ( ) ;
7276
7289
if ( ! xgPlayer ) {
7277
7290
return undefined ;
7278
7291
}
7279
- const { url : sources , duration, lang, isLive : isStream } = xgPlayer . config ;
7292
+ const { config : { url : sources , duration, lang, isLive : isStream } , } = xgPlayer ;
7280
7293
if ( ! sources ) {
7281
7294
return undefined ;
7282
7295
}
@@ -7298,11 +7311,7 @@ class DouyinHelper extends BaseHelper {
7298
7311
if ( pathId ) {
7299
7312
return pathId ;
7300
7313
}
7301
- const xgPlayer = this . getPlayer ( ) ;
7302
- if ( ! xgPlayer ) {
7303
- return undefined ;
7304
- }
7305
- return xgPlayer . config . vid ;
7314
+ return DouyinHelper . getPlayer ( ) ?. config . vid ;
7306
7315
}
7307
7316
}
7308
7317
@@ -7356,16 +7365,7 @@ class LoomHelper extends BaseHelper {
7356
7365
return undefined ;
7357
7366
}
7358
7367
const release = SENTRY_RELEASE ;
7359
- return release ?. id ;
7360
- }
7361
- getDefault ( videoId ) {
7362
- if ( ! this . service ) {
7363
- return undefined ;
7364
- }
7365
- return {
7366
- url : this . service . url + videoId ,
7367
- duration : undefined ,
7368
- } ;
7368
+ return release . id ;
7369
7369
}
7370
7370
async getVideoData ( videoId ) {
7371
7371
try {
@@ -7407,7 +7407,7 @@ class LoomHelper extends BaseHelper {
7407
7407
}
7408
7408
catch ( err ) {
7409
7409
Logger . error ( `Failed to get Loom video data, because: ${ err . message } ` ) ;
7410
- return this . getDefault ( videoId ) ;
7410
+ return this . returnBaseData ( videoId ) ;
7411
7411
}
7412
7412
}
7413
7413
async getVideoId ( url ) {
@@ -7774,6 +7774,7 @@ async function getVideoData(service, opts = {}) {
7774
7774
7775
7775
7776
7776
7777
+
7777
7778
; // ./node_modules/@vot .js/ext/dist/index.js
7778
7779
7779
7780
0 commit comments