@@ -117,6 +117,10 @@ $(".ui.dashboard .content").on("click", ".download-success, .course-encrypted",
117
117
$ ( this ) . parents ( ".course" ) . find ( ".download-status" ) . show ( ) ;
118
118
} ) ;
119
119
120
+ $ ( ".ui.dashboard .content" ) . on ( "click" , ".save_m3u.button" , function ( e ) {
121
+ e . stopImmediatePropagation ( ) ;
122
+ saveM3u ( $ ( this ) . parents ( ".course" ) ) ;
123
+ } ) ;
120
124
$ ( ".ui.dashboard .content" ) . on ( "click" , ".download.button, .download-error" , function ( e ) {
121
125
e . stopImmediatePropagation ( ) ;
122
126
prepareDownloading ( $ ( this ) . parents ( ".course" ) ) ;
@@ -301,7 +305,7 @@ async function checkLogin(alertExpired = true) {
301
305
ui . busyLogin ( false ) ;
302
306
ui . showDashboard ( ) ;
303
307
304
- Settings . subscriber = utils . toBoolean ( userContext . header . user . enableLabsInPersonalPlan ) ;
308
+ Settings . subscriber = utils . toBoolean ( userContext . header . user . enableLabsInPersonalPlan ) || utils . toBoolean ( userContext . header . user . consumer_subscription_active ) ;
305
309
fetchCourses ( Settings . subscriber ) . then ( ( ) => {
306
310
console . log ( "fetchCourses done" ) ;
307
311
} ) ;
@@ -553,9 +557,10 @@ function renderCourses(response, isResearch = false) {
553
557
$coursesItems . append ( courseElements ) ;
554
558
555
559
if ( response . next ) {
560
+ const dataUrl = Array . isArray ( response . next ) ? response . next : [ response . next ] ;
556
561
// added loadMore Button
557
562
$coursesSection . append (
558
- `<button class="ui basic blue fluid load-more button disposable" data-url=${ response . next } >
563
+ `<button class="ui basic blue fluid load-more button disposable" data-url=${ JSON . stringify ( dataUrl ) } >
559
564
${ translate ( "Load More" ) }
560
565
</button>`
561
566
) ;
@@ -707,6 +712,7 @@ async function fetchCourseContent(courseId, courseName, courseUrl) {
707
712
} else {
708
713
709
714
switch ( ( lecture . quality || "" ) . toLowerCase ( ) ) {
715
+ case "" :
710
716
case "auto" :
711
717
case "highest" :
712
718
lecture . quality = streams . maxQuality ;
@@ -715,10 +721,10 @@ async function fetchCourseContent(courseId, courseName, courseUrl) {
715
721
lecture . quality = streams . minQuality ;
716
722
break ;
717
723
default :
718
- lecture . quality = utils . isNumber ( lecture . quality ) ? lecture . quality : lecture . quality . slice ( 0 , - 1 ) ;
724
+ lecture . quality = utils . isNumber ( lecture . quality ) ? lecture . quality : lecture . quality . slice ( 0 , - 1 ) ;
719
725
}
720
726
721
- if ( ! streams . sources [ lecture . quality ] ) {
727
+ if ( lecture . quality && ! streams . sources [ lecture . quality ] ) {
722
728
if ( utils . isNumber ( lecture . quality ) && streams . maxQuality != "auto" ) {
723
729
const source = utils . getClosestValue ( streams . sources , lecture . quality ) ;
724
730
lecture . quality = source ?. key || streams . maxQuality ;
@@ -801,18 +807,26 @@ async function fetchCourses(isSubscriber) {
801
807
function loadMore ( loadMoreButton ) {
802
808
const $button = $ ( loadMoreButton ) ;
803
809
const $courses = $button . prev ( ".courses.items" ) ;
804
- const url = $button . data ( "url" ) ;
810
+ const url = [ ... $button . data ( "url" ) ] ;
805
811
806
812
ui . busyLoadCourses ( true ) ;
807
813
udemyService
808
- . fetchLoadMore ( url )
814
+ . fetchLoadMore ( url [ 0 ] )
809
815
. then ( ( resp ) => {
810
816
$courses . append ( ...resp . results . map ( ( course ) => createCourseElement ( course , false ) ) ) ;
811
817
if ( ! resp . next ) {
812
- $button . remove ( ) ;
818
+ if ( url . length > 1 ) {
819
+ $button . data ( "url" , [ url [ 1 ] ] ) ;
820
+ } else {
821
+ $button . remove ( ) ;
822
+ }
813
823
} else {
814
- $button . data ( "url" , resp . next ) ;
815
- }
824
+ if ( url . length > 1 ) {
825
+ $button . data ( "url" , [ resp . next , url [ 1 ] ] ) ;
826
+ } else {
827
+ $button . data ( "url" , [ resp . next ] ) ;
828
+ }
829
+ }
816
830
} )
817
831
. catch ( ( e ) => {
818
832
const statusCode = ( e . response ?. status || 0 ) . toString ( ) + ( e . code ? ` :${ e . code } ` : "" ) ;
@@ -966,6 +980,68 @@ function removeCurseDownloads(courseId) {
966
980
} ) ;
967
981
}
968
982
983
+ async function saveM3u ( $course ) {
984
+ ui . prepareDownloading ( $course ) ;
985
+
986
+ const courseId = $course . attr ( "course-id" ) ;
987
+ const courseName = $course . find ( ".coursename" ) . text ( ) ;
988
+ const courseUrl = `https://${ Settings . subDomain } .udemy.com${ $course . attr ( "course-url" ) } ` ;
989
+
990
+ console . clear ( ) ;
991
+
992
+ let courseData = null ;
993
+ try {
994
+ courseData = await fetchCourseContent ( courseId , courseName , courseUrl ) ;
995
+ if ( ! courseData ) {
996
+ // ui.showProgress($course, false);
997
+ return ;
998
+ }
999
+
1000
+ console . log ( courseData ) ;
1001
+ dialog
1002
+ . showSaveDialog ( {
1003
+ title : "Save M3U" ,
1004
+ defaultPath : `${ courseName } .m3u` ,
1005
+ filters : [ { name : "M3U File (*.m3u)" , fileExtension : [ "m3u" ] } ] ,
1006
+ } )
1007
+ . then ( ( result ) => {
1008
+ if ( ! result . canceled ) {
1009
+ let filePath = result . filePath ;
1010
+ if ( ! filePath . endsWith ( ".m3u" ) ) filePath += ".m3u" ;
1011
+
1012
+ let content = "#EXTM3U" ;
1013
+ let index = 0 ;
1014
+ courseData . chapters . forEach ( ( chapter ) => {
1015
+ chapter . lectures . forEach ( ( lecture , lec_index ) => {
1016
+ index ++ ;
1017
+ content += `\n#EXTINF:-1,${ lec_index + 1 } . ${ lecture . name } \n${ lecture . src } ` ;
1018
+
1019
+ if ( lecture . attachments && lecture . attachments . length > 0 )
1020
+ lecture . attachments . forEach ( ( attachment , attach_index ) => {
1021
+ content += `\n#EXTINF:-1,${ lec_index + 1 } .${ attach_index + 1 } ${ attachment . name } \n${ attachment . src } ` ;
1022
+ } )
1023
+ } )
1024
+ } ) ;
1025
+
1026
+ fs . writeFile ( filePath , content , ( error ) => {
1027
+ if ( error ) {
1028
+ appendLog ( "saveM3u_Error" , error ) ;
1029
+ return ;
1030
+ }
1031
+ console . log ( "File successfully create!" ) ;
1032
+ } ) ;
1033
+ }
1034
+ } ) ;
1035
+
1036
+ } catch ( error ) {
1037
+ handleApiError ( error , "ESAVE_M3U" , null , false ) ;
1038
+ ui . busyOff ( ) ;
1039
+ $course . find ( ".prepare-downloading" ) . hide ( ) ;
1040
+ } finally {
1041
+ ui . showProgress ( $course , false ) ;
1042
+ }
1043
+ }
1044
+
969
1045
async function prepareDownloading ( $course , subtitle ) {
970
1046
ui . prepareDownloading ( $course ) ;
971
1047
// ui.showProgress($course, true);
0 commit comments