// ==UserScript== // @name chinahrt继续教育;chinahrt全自动刷课;解除系统限制; // @version 4.0.0 // @namespace https://github.com/yikuaibaiban/chinahrt // @description 【❤全自动刷课❤】功能可自由配置,只需将视频添加到播放列表,后续刷课由系统自动完成;使用教程:https://www.cnblogs.com/ykbb/p/16695563.html // @author yikuaibaiban;https://www.cnblogs.com/ykbb/;https://github.com/yikuaibaiban // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAArFJREFUWEftlttPE0EUxr+9ddtdYOXSSmmlFFoasSFemmg0qYkIMfGF/9J/wTeN0cSYGBHEBBIoLSIU0VrKpe1eagaySWVmutu+GJPO4+5cfvOdc745wkGl3sI/HEIf4L9ToHrqoHLi4LTRgmm1IAhAMCDgmi4ibEgQhe4SyncOFA9tFMoWaucO9wRJFDAZlpCeUKAq/kA8AY7PHKwWmqic+i8WRRaQTciIj8qeFB0Bjo4dvN9ooOX/7L8OnLshYybaWQouALn5m/XeD3dJ5qcCSEQkrhJcgLfrdabshV8mvtdsPEoEPeV1JzzOqhjSROZ8JsBO2cJa0WQueLFSQ6lqYWpYQT4ZQnSQfzt3g+iwhFw64B/g9VqDm+0uANlNkYB8UkMupnqqkc+qMBgqUAqQOiex5412AHdOJhzAUlqDpvBNIBOXMTtBJyQF0El+ciALgHwfUEUspjTMjrGzPmKIuJ+hlaIA1ksmtg+srhRon7wwE0IuTieoHhTwZJ7+TgGsbDexe2T3DJAdV/E8o1HriTMu3QlR3ymAz4UmSj96A1AkActzOqZH6DD4BtjYM7G5130IYkMynmV0jHHqfXRQxMObPnKg/NvGh81mVyG4HQ1gcVYH22out5oel3Fr0kcVOC3g5cdz2JxH72oVPE1ruDfh7QMPMirCBo3IdMIvRfPi6WUNF2BMl0Aynjii1yAGRIyINZgADRN4tVa/aDiujnfFOg5PbCykNAyp/roPYsPEjn0DkInfflr4tMV+D7xu3P4/eV1GNsFXqWM/sLVv4usuvyK8QGIjEu6m2I+Qu9azIyKt2OoOvyp4EF439w1AJpLmhHjDfoVvUO6GJOHSMZkb86vAngq0L6ieOSA+UalddsWWfZmkA0ERhi4iYkjMUusUqq4AvGLey/8+QF+BP0npcPDdfTv7AAAAAElFTkSuQmCC // @match http://*.chinahrt.com/* // @match https://*.chinahrt.com/* // @match http://videoadmin.chinahrt.com.cn/videoPlay/play* // @match http://videoadmin.chinahrt.com/videoPlay/play* // @match https://videoadmin.chinahrt.com.cn/videoPlay/play* // @match https://videoadmin.chinahrt.com/videoPlay/play* // // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_addValueChangeListener // @grant GM_notification // @grant GM_addStyle // // @license GPL // @downloadURL none // ==/UserScript== class VueHandler { static getInstance() { return document.querySelector("article")?.__vue__ } static pageCategory() { const path = this.getInstance()?.$route?.path; if (path === "/v_courseDetails") { return General.pageCategory.detail } return General.pageCategory.other } static registerRouterChange() { this.getInstance().$router.afterEach((to, from, failure) => { PlayPage.removeConfigBox(); PlayPage.removePlaylistBox(); PlayPage.removeFeedbackBox(); PlayPage.removeNoticeBox(); experimentalHandler.removeExperimentalBox(); DetailPage.removeCanPlaylist(); if (to.path === "/v_courseDetails") { DetailPage.appendToCanPlaylist(this.getCourses()) } }) } static getCourses() { let results = []; let query = this.getInstance()?.$route?.query; const chapters = this.getInstance()?._data?.pageData?.course?.chapter_list; if (chapters && chapters.length > 0) { for (let i = 0; i < chapters.length; i++) { const sections = chapters[i]?.section_list; if (sections && sections.length > 0) { for (let j = 0; j < sections.length; j++) { const section = sections[j]; const url = window.location.protocol + "//" + window.location.host + window.location.pathname + "#/v_video?platformId=" + query.platformId + "&trainplanId=" + query.trainplanId + "&courseId=" + query.courseId + "§ionId=" + section.id; results.push({ title: section.name, url: url, status: section.study_status + "( " + section.studyTimeStr + " )" }) } } } } return results } } class BasicHandler { static pageCategory() { const href = window.location.href; if (href.indexOf("/course/play_video") > -1 || href.indexOf("/videoPlay/play") > -1) { return General.pageCategory.play } if (href.indexOf("/course/preview") > -1) { return General.pageCategory.detail } return General.pageCategory.other } static findPageCourses() { let results = []; if (this.pageCategory() === General.pageCategory.detail) { const allLinks = document.querySelectorAll("a"); for (let i = 0; i < allLinks.length; i++) { const element = allLinks[i]; if (element.href.indexOf("/course/play_video") > -1) { results.push({title: element.innerText, url: element.href, status: $(element).prev().text()}) } } } return results } static generateBoxItem(item, parent) { let box = document.createElement("div"); box.className = "item"; let title = document.createElement("p"); title.innerText = item.title; title.className = "title"; box.appendChild(title); for (let i = 0; i < item.options.length; i++) { const option = item.options[i]; let label = document.createElement("label"); label.innerText = option.text; box.appendChild(label); let input = document.createElement("input"); input.type = "radio"; input.name = item.name; input.value = option.value; input.checked = item.action() === option.value; input.onclick = function () { item.action(option.value) }; label.appendChild(input) } if (item.remark) { let remark = document.createElement("p"); remark.innerText = item.remark; remark.className = "remark"; box.appendChild(remark) } parent.appendChild(box) } } class General { static coursesKey = "courses"; static pageCategory = {play: 0, detail: 1, other: 99}; static addCourse(value) { if (!value.title || !value.url) { this.notification("课程添加失败,缺少必要参数。"); return false } let courses = this.courses(); if (this.courseAdded(courses, value.url)) { this.notification("课程已经在播放列表中。"); return false } courses.push({title: value.title, url: value.url}); this.courses(courses); return true } static removeCourse(index) { let courses = this.courses(); if (Number.isNaN(index)) { for (let i = courses.length; i >= 0; i--) { const element = courses[i]; let jsonHref = element.url; let jsonSectionId = jsonHref.match(/sectionId=([^&]*)/)[1]; let jsonCourseId = jsonHref.match(/courseId=([^&]*)/)[1]; let jsonTrainplanId = jsonHref.match(/trainplanId=([^&]*)/)[1]; let href = window.location.href; let sectionId = href.match(/sectionId=([^&]*)/)[1]; let courseId = href.match(/courseId=([^&]*)/)[1]; let trainplanId = href.match(/trainplanId=([^&]*)/)[1]; if (jsonCourseId === courseId && jsonSectionId === sectionId && jsonTrainplanId === trainplanId) { courses.splice(i, 1) } } } else { courses.splice(index, 1) } this.courses(courses) } static courseAdded(courses, url) { if (courses && Array.isArray(courses)) { return courses.findIndex(value => value.url === url) > -1 } return this.courses().findIndex(value => value.url === url) > -1 } static getValue(key, defaultValue) { return GM_getValue(key, defaultValue) } static setValue(key, value) { GM_setValue(key, value); return value } static autoPlay(value) { if (value !== undefined) { General.setValue("autoPlay", value); if (value) { if (player) { player.videoPlay() } } return value } else { return General.getValue("autoPlay", true) } } static mute(value) { if (value !== undefined) { General.setValue("mute", value); if (player) { if (value) { player.videoMute() } else { player.videoEscMute() } } return value } else { return General.getValue("mute", true) } } static drag(value) { if (value !== undefined) { General.setValue("drag", value); if (player) { player.changeConfig("config", "timeScheduleAdjust", value) } return value } else { return General.getValue("drag", 5) } } static speed(value) { if (attrset) { attrset.playbackRate = 1 } if (value !== undefined) { General.setValue("speed", value); if (player) { player.changePlaybackRate(value) } return value } else { return General.getValue("speed", 1) } } static playModel(value) { return value !== undefined ? General.setValue("play_mode", value) : General.getValue("play_mode", 0) } static notification(content) { GM_notification({ text: content, title: "Chinahrt自动刷课", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAArFJREFUWEftlttPE0EUxr+9ddtdYOXSSmmlFFoasSFemmg0qYkIMfGF/9J/wTeN0cSYGBHEBBIoLSIU0VrKpe1eagaySWVmutu+GJPO4+5cfvOdc745wkGl3sI/HEIf4L9ToHrqoHLi4LTRgmm1IAhAMCDgmi4ibEgQhe4SyncOFA9tFMoWaucO9wRJFDAZlpCeUKAq/kA8AY7PHKwWmqic+i8WRRaQTciIj8qeFB0Bjo4dvN9ooOX/7L8OnLshYybaWQouALn5m/XeD3dJ5qcCSEQkrhJcgLfrdabshV8mvtdsPEoEPeV1JzzOqhjSROZ8JsBO2cJa0WQueLFSQ6lqYWpYQT4ZQnSQfzt3g+iwhFw64B/g9VqDm+0uANlNkYB8UkMupnqqkc+qMBgqUAqQOiex5412AHdOJhzAUlqDpvBNIBOXMTtBJyQF0El+ciALgHwfUEUspjTMjrGzPmKIuJ+hlaIA1ksmtg+srhRon7wwE0IuTieoHhTwZJ7+TgGsbDexe2T3DJAdV/E8o1HriTMu3QlR3ymAz4UmSj96A1AkActzOqZH6DD4BtjYM7G5130IYkMynmV0jHHqfXRQxMObPnKg/NvGh81mVyG4HQ1gcVYH22out5oel3Fr0kcVOC3g5cdz2JxH72oVPE1ruDfh7QMPMirCBo3IdMIvRfPi6WUNF2BMl0Aynjii1yAGRIyINZgADRN4tVa/aDiujnfFOg5PbCykNAyp/roPYsPEjn0DkInfflr4tMV+D7xu3P4/eV1GNsFXqWM/sLVv4usuvyK8QGIjEu6m2I+Qu9azIyKt2OoOvyp4EF439w1AJpLmhHjDfoVvUO6GJOHSMZkb86vAngq0L6ieOSA+UalddsWWfZmkA0ERhi4iYkjMUusUqq4AvGLey/8+QF+BP0npcPDdfTv7AAAAAElFTkSuQmCC" }) } static courses(value) { if (value) { if (!Array.isArray(value)) { this.notification("保存课程数据失败,数据格式异常。"); return [] } return General.setValue(this.coursesKey, value) } let courses = General.getValue(this.coursesKey, []); if (!Array.isArray(courses)) { return [] } return courses } } class PlayPage { static#configBoxId = "configBox"; static#playlistBoxId = "playlistBox"; static#feedbackBoxId = "feedbackBox"; static#configContent = [{ title: "自动播放", name: "autoPlay", action: General.autoPlay, remark: "", options: [{text: "是", value: true}, {text: "否", value: false}] }, { title: "静音", name: "mute", action: General.mute, remark: "注意:不静音,视频可能会出现不会自动播放", options: [{text: "是", value: true}, {text: "否", value: false}] }, { title: "拖放", name: "drag", action: General.drag, remark: "注意:慎用此功能,后台可能会检测播放数据。", options: [{text: "还原", value: 5}, {text: "启用", value: 1}] }, { title: "播放速度", name: "speed", action: General.speed, remark: "注意:慎用此功能,后台可能会检测播放数据。", options: [{text: "0.5倍", value: 0}, {text: "正常", value: 1}, {text: "1.25倍", value: 2}, { text: "1.5倍", value: 3 }, {text: "2倍", value: 4}] }]; static playerInit() { player.changeControlBarShow(true); player.changeConfig("config", "timeScheduleAdjust", General.drag()); if (General.mute()) { player.videoMute() } else { player.videoEscMute() } player.changePlaybackRate(General.speed()); if (General.autoPlay()) { player.videoPlay() } } static init() { removePauseBlur(); PlayPage.createConfigBox(); PlayPage.createPlaylistBox(); PlayPage.createFeedbackBox(); experimentalHandler.createExperimentalBox(); GM_addValueChangeListener(General.coursesKey, function (name, oldValue, newValue, remote) { PlayPage.removePlaylistBox(); PlayPage.createPlaylistBox() }); PlayPage.playerInit(); player.addListener("loadedmetadata", PlayPage.playerInit); player.addListener("ended", function () { General.removeCourse(window.location.href); let courses = General.courses(); if (courses.length === 0) { General.notification("所有视频已经播放完毕") } else { General.notification("即将播放下一个视频:" + courses[0].title); window.top.location.href = courses[0].url } }); player.addListener("time", function (t) { experimentalHandler.timeHandler(t) }) } static #getConfigBox() { return document.getElementById(this.#configBoxId) } static #getPlaylistBox() { return document.getElementById(this.#playlistBoxId) } static #getFeedbackBox() { return document.getElementById(this.#feedbackBoxId) } static createConfigBox() { const existBox = this.#getConfigBox(); if (existBox) { return existBox } let configBox = document.createElement("div"); configBox.id = this.#configBoxId; configBox.className = "configBox"; document.body.appendChild(configBox); let title = document.createElement("div"); title.innerText = "视频控制配置"; title.className = "title"; configBox.appendChild(title); for (let i = 0; i < this.#configContent.length; i++) { const element = this.#configContent[i]; BasicHandler.generateBoxItem(element, configBox) } return configBox } static removeConfigBox() { const configBox = this.#getConfigBox(); if (configBox) { configBox.remove() } } static createPlaylistBox() { const existBox = this.#getPlaylistBox(); if (existBox) { return existBox } let playlistBox = document.createElement("div"); playlistBox.id = this.#playlistBoxId; playlistBox.className = "playlistBox"; document.body.appendChild(playlistBox); let oneClear = document.createElement("button"); oneClear.innerText = "一键清空"; oneClear.className = "oneClear"; oneClear.onclick = function () { if (confirm("确定要清空播放列表么?")) { General.courses([]) } }; playlistBox.appendChild(oneClear); let title = document.createElement("div"); title.innerText = "视频列表"; title.className = "title"; playlistBox.appendChild(title); const courses = General.courses(); for (let i = 0; i < courses.length; i++) { const course = courses[i]; let childTitle = document.createElement("p"); childTitle.innerText = course.title; childTitle.title = course.title; childTitle.className = "child_title"; playlistBox.appendChild(childTitle); let childBtn = document.createElement("button"); childBtn.innerText = "移除"; childBtn.type = "button"; childBtn.setAttribute("data", i); childBtn.className = "child_remove"; childBtn.onclick = function () { if (confirm("确定要删除这个视频任务么?")) { General.removeCourse(this.getAttribute("data")) } }; playlistBox.appendChild(childBtn) } } static removePlaylistBox() { const playlistBox = this.#getPlaylistBox(); if (playlistBox) { playlistBox.remove() } } static createFeedbackBox() { const existBox = this.#getFeedbackBox(); if (existBox) { return existBox } let box = document.createElement("div"); box.className = "feedbackBox"; document.body.appendChild(box); let changelog = document.createElement("div"); changelog.className = "changelog"; changelog.innerHTML = "1.本次重构了所有代码。
" + "2.修复了鼠标移出视频会暂停的问题。
" + "3.增加了'一键添加'到播放列表与'一键清空'的功能。
" + "4.修复一些已知错误。
"; box.appendChild(changelog); let notice = document.createElement("div"); notice.innerHTML = "点击课程详情页中的插件提供的【添加到播放列表】按钮添加需要自动播放的课程。
受到浏览器策略影响第一次可能无法自动播放,请手动点击播放或在控制配置中设置为静音,再刷新。"; notice.className = "notice"; box.appendChild(notice); const links = [{title: "使用教程", link: "https://www.cnblogs.com/ykbb/p/16695563.html"}, { title: "博客园", link: "https://www.cnblogs.com/ykbb/" }, {title: "留言", link: "https://msg.cnblogs.com/send/ykbb"}, { title: "GitHub", link: "https://github.com/yikuaibaiban/chinahrt-autoplay/issues" }]; for (const link of links) { let a = document.createElement("a"); a.innerText = link.title; a.target = "_blank"; a.href = link.link; a.className = "link"; box.appendChild(a) } return box } static removeFeedbackBox() { this.#getFeedbackBox()?.remove() } } class DetailPage { static#canPlaylistId = "canPlaylist"; static createCanPlaylist() { const existBox = document.getElementById(this.#canPlaylistId); if (existBox) { return existBox } let playlist = document.createElement("div"); playlist.id = this.#canPlaylistId; playlist.className = "canPlaylist"; let oneClick = document.createElement("button"); oneClick.innerText = "一键添加"; oneClick.type = "button"; oneClick.className = "oneClick"; oneClick.onclick = function () { const items = playlist.getElementsByClassName("item"); for (let item of items) { const buttons = item.getElementsByTagName("button"); for (let button of buttons) { if (button.disabled) { continue } button.click() } } }; playlist.appendChild(oneClick); playlist.addEventListener("clear", function () { while (playlist.firstChild) { playlist.removeChild(playlist.firstChild) } }); playlist.addEventListener("append", function (data) { let child = document.createElement("div"); child.className = "item"; this.appendChild(child); let title = document.createElement("p"); title.innerText = data.detail.title; title.title = data.detail.title; title.className = "title"; child.appendChild(title); let status = document.createElement("p"); status.innerText = data.detail.status; status.title = data.detail.status; status.className = "status"; child.appendChild(status); let added = General.courseAdded(undefined, data.detail.url); let addBtn = document.createElement("button"); addBtn.innerText = added ? "已在列表中" : "添加到播放列表"; addBtn.type = "button"; addBtn.disabled = added; addBtn.className = added ? "addBtn disable" : "addBtn"; addBtn.onclick = function () { if (General.addCourse(data.detail)) { this.setAttribute("disabled", true); this.setAttribute("class", "addBtn disable"); this.innerText = "已在列表中" } }; child.appendChild(addBtn) }); document.body.append(playlist); return playlist } static removeCanPlaylist() { document.getElementById(this.#canPlaylistId)?.remove() } static appendToCanPlaylist(courses) { const box = document.getElementById(this.#canPlaylistId); if (Array.isArray(courses) && box) { for (let i = 0; i < courses.length; i++) { let course = courses[i]; box.dispatchEvent(new CustomEvent("append", {detail: course})) } } } } class experimentalHandler { static#experimentalBoxId = "experimentalBox"; static#experimentalContent = [{ title: "播放模式", name: "playMode", action: General.playModel, remark: "", options: [{text: "正常", value: 0}, { text: "二段播放", value: 3, title: "将视频分为二段:开始,结束各播放90秒" }, {text: "三段播放", value: 1, title: "将视频分为三段:开始,中间,结束各播放90秒"}, { text: "秒播", value: 2, title: "将视频分为两段:开始,结束各播放一秒" }] }]; static #getExperimentalBox() { return document.getElementById(this.#experimentalBoxId) } static createExperimentalBox() { const existBox = this.#getExperimentalBox(); if (existBox) { return existBox } let box = document.createElement("div"); box.className = "experimentalBox"; document.body.appendChild(box); let tip = document.createElement("div"); tip.innerText = "此功能只适用个别地区。无法使用的就不要使用了。"; tip.className = "tip"; box.appendChild(tip); for (let i = 0; i < this.#experimentalContent.length; i++) { BasicHandler.generateBoxItem(this.#experimentalContent[i], box) } } static removeExperimentalBox() { const box = this.#getExperimentalBox(); if (box) { box.remove() } } static timeHandler(t) { if (player !== undefined) { let videoDuration = parseInt(player.getMetaDate().duration); if (General.playModel() === 1) { if (videoDuration <= 270) { return } var videoMiddleStart = videoDuration / 2 - 45; var videoMiddleEnd = videoDuration / 2 + 45; var videoEndStart = videoDuration - 90; if (t > 90 && t < videoMiddleStart) { player.videoSeek(videoMiddleStart); return } if (t > videoMiddleEnd && t < videoEndStart) { player.videoSeek(videoEndStart); return } return } if (General.playModel() === 2) { if (t > 1 && t < videoDuration - 1) { player.videoSeek(videoDuration - 1) } return } if (General.playModel() === 3) { if (videoDuration <= 180) { return } if (t > 90 && t < videoDuration - 90) { player.videoSeek(videoDuration - 90) } } } else { General.notification("找不到播放器") } } } window.onload = function () { setTimeout(function () { let inVue; try { inVue = Vue !== undefined; console.log("当前模式:Vue", window.location.href) } catch (e) { inVue = false; console.log("当前模式:JQuery", window.location.href) } const pageCategory = inVue ? VueHandler.pageCategory() : BasicHandler.pageCategory(); if (pageCategory === General.pageCategory.play || General.pageCategory.detail === pageCategory) { GM_addStyle(".canPlaylist{width:300px;height:500px;position:fixed;top:100px;background:#fff;right:80px;border:1px solid #c1c1c1;overflow-y:auto}.canPlaylist .oneClick{margin:0 auto;width:100%;border:0;padding:6px 0;background:linear-gradient(180deg,#4bce31,#4bccf2);height:50px;border-radius:5px;color:#fff;font-weight:700;letter-spacing:4px;font-size:18px}.canPlaylist .item{padding:8px;line-height:150%;border-bottom:1px solid #c1c1c1;margin-bottom:3px}.canPlaylist .item .status,.canPlaylist .item .title{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.canPlaylist .item .status{font-size:12px;color:#c1c1c1}.canPlaylist .item .addBtn{color:#fff;background-color:#4bccf2;border:0;padding:5px 10px;margin-top:4px}.canPlaylist .item .addBtn.disable{color:#000;background-color:#c3c3c3}.configBox{right:0;top:0;height:280px;overflow-y:auto}.configBox>.title{border-bottom:1px solid #ccc;padding:5px}.configBox .item{border-bottom:1px dotted #ccc;padding:5px 0;font-size:14px}.configBox .item .title{padding-bottom:5px;display:inline-block;font-weight:700}.configBox .item .title:after{content:\":\";margin-right:5px}.configBox .item .remark{font-size:12px;color:#c1c1c1}.configBox,.experimentalBox,.playlistBox{position:fixed;width:250px;background-color:#fff;z-index:9999;border:1px solid #ccc}.playlistBox{right:0;top:290px;height:450px;overflow-y:auto}.playlistBox .oneClear{margin:0 auto;width:100%;border:0;padding:6px 0;background:linear-gradient(180deg,#4bce31,#4bccf2);height:50px;border-radius:5px;color:#fff;font-weight:700;letter-spacing:4px;font-size:18px}.playlistBox .title{border-bottom:1px solid #ccc;padding:5px;font-weight:700}.playlistBox .child_title{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.playlistBox .child_remove{color:#fff;background-color:#fd1952;border:0;padding:5px 10px;margin:4px 0 10px}.experimentalBox{right:255px;top:0;height:280px}.experimentalBox .tip{border-bottom:1px solid #ccc;padding:5px;font-weight:700;color:red}.experimentalBox .item,.feedbackBox{font-size:14px}.feedbackBox{font-weight:700;background-color:#fff;padding:4px 7px;position:absolute;top:0;line-height:30px;z-index:99999;display:flex;flex-direction:row;left:30px;flex-wrap:wrap;width:226px}.feedbackBox .link{padding:8px 0 8px 10px}.feedbackBox .notice{font-size:14px;color:red;border-bottom:2px dotted #c1c1c1}.feedbackBox .changelog{margin:10px 0;border-bottom:2px dotted #c1c1c1}.configBox label,.experimentalBox label{margin-right:3px}.configBox label input,.experimentalBox label input{margin-left:2px}"); if (pageCategory === General.pageCategory.play) { let playTimer = setInterval(function () { try { console.log(player); if (player) { PlayPage.init(); clearInterval(playTimer) } } catch (error) { console.log(error); console.log("未获取到播放器") } }, 500) } else if (pageCategory === General.pageCategory.detail) { DetailPage.createCanPlaylist(); if (inVue) { let checkTimer = setInterval(function () { if (VueHandler.getInstance()) { VueHandler.registerRouterChange(); DetailPage.appendToCanPlaylist(VueHandler.getCourses()); clearInterval(checkTimer) } }, 500) } else { DetailPage.appendToCanPlaylist(BasicHandler.findPageCourses()) } } } }, 1e3) };