SHOW:
|
|
- or go back to the newest paste.
1 | var downloadedFilesCounter = 0; | |
2 | var numOfChunksToDownload; | |
3 | var downloadQueue = []; | |
4 | var currentDownloadName; | |
5 | var status = "idle"; | |
6 | var theWindow = null; | |
7 | var firstTimeOpenWindow = 1; | |
8 | ||
9 | var chunksBaseUrl, quality, chunksURLQuery; | |
10 | ||
11 | function updataStatus(){ | |
12 | downloadedFilesCounter++; | |
13 | let completedPercentage = (downloadedFilesCounter / (numOfChunksToDownload+1) ) ; | |
14 | let fullWidth = $("#progressBar"+downloadQueue[0].playlistid).width(); | |
15 | let percentageDivWidth = $("#progressBarPercent"+downloadQueue[0].playlistid).width(); | |
16 | let updatedWidth = parseInt(completedPercentage*fullWidth); | |
17 | if ( updatedWidth > percentageDivWidth) | |
18 | $("#progressBarPercent"+downloadQueue[0].playlistid).css("width", updatedWidth); | |
19 | if ( downloadedFilesCounter == (numOfChunksToDownload+1) ) | |
20 | $("#progressBarPercent"+downloadQueue[0].playlistid).css({"background-color": "#e91e63", "width":"100%"}).text("ההורדה הושלמה!"); | |
21 | else | |
22 | $("#progressBarPercent"+downloadQueue[0].playlistid).text("בהורדה: " + parseInt(completedPercentage*100) + "%"); | |
23 | } | |
24 | ||
25 | var tmrCheckPlaylistLoad; | |
26 | var currentOpenCollectionId = $("#ovc_collections_list").find("li.active").find("a").attr("c-value"); | |
27 | addDownloadButtons(currentOpenCollectionId); | |
28 | ||
29 | // add click event for all download buttons | |
30 | $(document).on("click", ".downloadButton", function(){ | |
31 | var url = "https://opal.openu.ac.il/mod/ouilvideocollection/actions.php"; | |
32 | var context = $(this).attr('context'); | |
33 | var playlistId = $(this).attr('playlistid'); | |
34 | downloadQueue.push( { context: context, playlistid: playlistId } ); | |
35 | ||
36 | // add progress bar | |
37 | let videoTop = $("#playlist"+playlistId).find(".ovc_playlist_border"); | |
38 | let progressBarDiv = $("<div id='progressBar"+playlistId+"'></div>").css({"background-color": "#01579B"}); | |
39 | let progressBarPercentDiv = $("<div id='progressBarPercent"+playlistId+"'>ממתין להתחלת הורדה... <a href='javascript:void(0);' class='cancelDownload' context="+context+" playlistid="+playlistId+" style='color:lightgreen;font-size: 120%;margin-right:10px;'><b>בטל</b></a></div>").css({"color": "white"}); | |
40 | progressBarDiv.append(progressBarPercentDiv); | |
41 | videoTop.prepend(progressBarDiv); | |
42 | ||
43 | $(".downloadButton[playlistid="+playlistId+"]").hide(); | |
44 | ||
45 | getVideosOnQueue(); | |
46 | }); | |
47 | ||
48 | // add click event for all cancel download buttons | |
49 | $(document).on("click", ".cancelDownload", function(){ | |
50 | var playlistId = $(this).attr('playlistid'); | |
51 | downloadQueue = downloadQueue.filter(video => video.playlistid !== playlistId ); | |
52 | $("#progressBar"+playlistId).remove(); | |
53 | $(".downloadButton[playlistid="+playlistId+"]").show(); | |
54 | }); | |
55 | ||
56 | ||
57 | // automatically add download buttons when a new collection is loaded | |
58 | function onPlaylistLoad(){ | |
59 | $(".collection_link").each(function(){ | |
60 | $(this).on("click", function(){ | |
61 | var cValue = $(this).attr("c-value"); | |
62 | tmrCheckPlaylistLoad = setInterval(function(){handleCollectionChange(cValue)}, 300); | |
63 | }); | |
64 | }); | |
65 | } | |
66 | onPlaylistLoad(); | |
67 | ||
68 | function handleCollectionChange (cValue) { | |
69 | if( $('#collection'+cValue).is(':visible') ){ | |
70 | addDownloadButtons(cValue); | |
71 | clearInterval(tmrCheckPlaylistLoad); | |
72 | } | |
73 | } | |
74 | ||
75 | // adds download buttons to an open collection( a collection that has been loaded ) | |
76 | function addDownloadButtons(collectionId) { | |
77 | // add buttons only if not been added before | |
78 | if ( $( "#collection"+collectionId ).find("button").length == 0 ) { | |
79 | var collectionDiv = $("#collection"+collectionId); | |
80 | var currentContext = collectionDiv.attr("cid"); | |
81 | var videoCount = 0; | |
82 | collectionDiv.children().each(function(i) { | |
83 | let videoDescription = $(this).find("span.instructor_row"); | |
84 | let currentPlaylistId = $(this).attr("id").substring(8); | |
85 | let buttonElement = $("<button></button>").text("הורד סרטון").attr('class','downloadButton').attr('context',currentContext).attr('playlistid',currentPlaylistId); | |
86 | buttonElement.css({"margin-right":"10px","background":"rgb(202, 60, 60)","color":"white","borderRadius":"4px","textShadow":"0 1px 1px rgba(0, 0, 0, 0.2)"}); | |
87 | videoDescription.append(buttonElement); | |
88 | }); | |
89 | } | |
90 | } | |
91 | ||
92 | ||
93 | function getPlaylistFile(context, playlistid){ | |
94 | var courseIdStart = $('.coursename_header').children()[0].href.indexOf("id="); | |
95 | var courseIdNum = $('.coursename_header').children()[0].href.substring(courseIdStart+3); | |
96 | jQuery.ajax({ | |
97 | type: "POST", | |
98 | url: "https://opal.openu.ac.il/mod/ouilvideocollection/actions.php", | |
99 | data: {action: "getplaylist", context: context, playlistid: playlistid, course: courseIdNum}, | |
100 | success: function(data) { | |
101 | let anotherURL = "https://opal.openu.ac.il/local/ouil_video/player.php?mediaid=" + data.media.cipher; | |
102 | currentDownloadName = data.title; | |
103 | ||
104 | $.get(anotherURL, function(data) { | |
105 | let mediaStart = data.indexOf("media: "); | |
106 | let mediaEnd = data.indexOf("\"", mediaStart+11); | |
107 | let myMedia = data.substring(mediaStart+8, mediaEnd); | |
108 | let url = myMedia; | |
109 | ||
110 | $.get(url, function(data) { | |
111 | let playlistStart = data.indexOf("file=")+5; | |
112 | let playlistEnd = data.indexOf("\"", playlistStart+8); | |
113 | var playlistURL = data.substring(playlistStart+1, playlistEnd).replace("&", "&"); | |
114 | let url = playlistURL; | |
115 | ||
116 | $.get(url, function(data) { | |
117 | let baseURL = playlistURL.substring(0, playlistURL.indexOf("playlist.")) | |
118 | let quality_list = data.match(/BANDWIDTH=\d+/g).map(function(n){return parseInt(n.replace("BANDWIDTH=", ""))}).sort(function(a,b){ return a-b; }); | |
119 | let highestQuality = quality_list[quality_list.length-1]; | |
120 | let URLQuery = playlistURL.substring(playlistURL.indexOf("?")); | |
121 | ||
122 | chunksBaseUrl = baseURL; | |
123 | quality = highestQuality; | |
124 | chunksURLQuery = URLQuery; | |
125 | let url = chunksBaseUrl+"chunklist_b"+quality+".m3u8"+chunksURLQuery; | |
126 | $.get(url, function(data) { | |
127 | data = data.split("\n"); | |
128 | let lastChunkLine = data[data.length-3]; | |
129 | let lastChunkStart = lastChunkLine.indexOf("_", lastChunkLine.indexOf(quality)); | |
130 | let lastChunkEnd = lastChunkLine.indexOf(".ts"); | |
131 | let lastChunkNum = lastChunkLine.substring(lastChunkStart+1, lastChunkEnd); | |
132 | numOfChunksToDownload = parseInt(lastChunkNum); | |
133 | startVideoDownload(); | |
134 | }); | |
135 | }); | |
136 | }, "text"); | |
137 | }); | |
138 | } | |
139 | }); | |
140 | } | |
141 | ||
142 | function getVideosOnQueue(){ | |
143 | if ( downloadQueue.length > 0 && status === "idle" ){ | |
144 | status = "downloading"; | |
145 | $("#progressBar"+downloadQueue[0].playlistid).css({"background-color": "#ddd"}); | |
146 | $("#progressBarPercent"+downloadQueue[0].playlistid).css({"background-color": "#4CAF50", "display": "inline-block", "font-weight": "bold"}).html("בהורדה: 0%"); | |
147 | getPlaylistFile(downloadQueue[0].context, downloadQueue[0].playlistid); | |
148 | } | |
149 | } | |
150 | ||
151 | function startVideoDownload(){ | |
152 | if ( theWindow === null ){ | |
153 | theWindow = window.open('https://opal.openu.ac.il/'+new Date().getTime(), "", 'toolbar=no,status=no,width=250,height=100'); | |
154 | if (theWindow == null || typeof(theWindow)=='undefined') { | |
155 | alert('יש לאפשר פתיחת חלון נוסף (popup). ליד שורת הכתובת בדפדפן מופיע סימן קטן של אפשרות לאפשר popup,\n יש ללחוץ עליו ולבחור ב "Always allow pop-ups from. לאחר מכאן לרענן את הדף ולהפעיל שוב את הסקריפט. אחרי פעולה זה הסקריפט יפעל כהלכה.'); | |
156 | } | |
157 | } | |
158 | var theDoc = theWindow.document, | |
159 | theScript = document.createElement('script'); | |
160 | ||
161 | function injectThis() { | |
162 | var fileData = []; | |
163 | ||
164 | function addData(data, index){ | |
165 | fileData[index] = data; | |
166 | window.opener.updataStatus(); | |
167 | if ( window.opener.downloadedFilesCounter == (window.opener.numOfChunksToDownload+1) ){ | |
168 | saveDownloadedFile(); | |
169 | setTimeout(function(){window.opener.windowFinishedDownloading()}, 200); | |
170 | } | |
171 | } | |
172 | ||
173 | function startVideoDownload(chunksBaseUrl, quality, chunksURLQuery){ | |
174 | for (i = 0; i <= window.opener.numOfChunksToDownload; i++) { | |
175 | let currentIndex = i; | |
176 | let xhr = new XMLHttpRequest(); | |
177 | let url=chunksBaseUrl+"media_b"+quality+"_"+i+".ts"+chunksURLQuery; | |
178 | xhr.open('GET', url, true); | |
179 | xhr.responseType = 'blob'; | |
180 | xhr.onload = function(e) { | |
181 | addData(xhr.response, currentIndex); | |
182 | } | |
183 | xhr.addEventListener("error", function(){ retryFailedRequest(chunksBaseUrl, quality, chunksURLQuery, currentIndex); }); | |
184 | xhr.send(); | |
185 | } | |
186 | } | |
187 | ||
188 | function retryFailedRequest(chunksBaseUrl, quality, chunksURLQuery, chunkNumber){ | |
189 | let currentIndex = chunkNumber; | |
190 | let xhr = new XMLHttpRequest(); | |
191 | let url = chunksBaseUrl+"media_b"+quality+"_"+currentIndex+".ts"+chunksURLQuery; | |
192 | xhr.open('GET', url, true); | |
193 | xhr.responseType = 'blob'; | |
194 | xhr.onload = function(e) { | |
195 | addData(xhr.response, currentIndex); | |
196 | } | |
197 | xhr.addEventListener("error", function(){ setTimeout(function(){ retryFailedRequest(chunkStartUrl, chunkEndNameWithoutExtension, chunkNumber); }, 5000); }); | |
198 | xhr.send(); | |
199 | } | |
200 | ||
201 | function saveDownloadedFile() { | |
202 | let blob = new Blob(fileData, {type: "video/mp2t"}); | |
203 | let a = document.body.appendChild(document.createElement('a')); | |
204 | let objectURL2 = URL.createObjectURL(blob); | |
205 | a.href = objectURL2; | |
206 | a.download = window.opener.currentDownloadName+".ts"; | |
207 | a.click(); | |
208 | a.remove(a); | |
209 | ||
210 | URL.revokeObjectURL(objectURL2); | |
211 | blob = null; | |
212 | a = null; | |
213 | ||
214 | // reset data for next download | |
215 | fileData = []; | |
216 | window.opener.downloadedFilesCounter = 0; | |
217 | window.opener.status = "idle"; | |
218 | window.opener.downloadQueue.shift(); | |
219 | } | |
220 | ||
221 | startVideoDownload(window.opener.chunksBaseUrl, window.opener.quality, window.opener.chunksURLQuery); | |
222 | } | |
223 | if ( firstTimeOpenWindow ){ | |
224 | theScript.innerHTML = 'window.onload = ' + injectThis.toString() + ';'; | |
225 | firstTimeOpenWindow = 0; | |
226 | } | |
227 | else { | |
228 | theScript.innerHTML = injectThis.toString() + 'injectThis();'; | |
229 | } | |
230 | theDoc.body.appendChild(theScript); | |
231 | } | |
232 | ||
233 | function windowFinishedDownloading(){ | |
234 | if ( downloadQueue.length === 0 ){ | |
235 | theWindow.close(); | |
236 | theWindow = null; | |
237 | firstTimeOpenWindow = 1; | |
238 | } | |
239 | else { | |
240 | theWindow.location.reload(); | |
241 | getVideosOnQueue(); | |
242 | } | |
243 | } |