From 0d249090f8f65f8d4f842cecb99729127c69fed8 Mon Sep 17 00:00:00 2001 From: guotao <1531188409@qq.com> Date: Thu, 28 Nov 2024 16:08:58 +0800 Subject: [PATCH 1/4] feat: Add zsgl platform support and config options --- package-lock.json | 4 +- src/config.ts | 68 +++++++++++++++++++++++++++ src/mooc/zsgl/course.ts | 37 +++++++++++++++ src/mooc/zsgl/platform.ts | 0 src/mooc/zsgl/task.ts | 98 +++++++++++++++++++++++++++++++++++++++ src/mooc/zsgl/utils.ts | 37 +++++++++++++++ src/mooc/zsgl/video.ts | 0 7 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 src/mooc/zsgl/course.ts create mode 100644 src/mooc/zsgl/platform.ts create mode 100644 src/mooc/zsgl/task.ts create mode 100644 src/mooc/zsgl/utils.ts create mode 100644 src/mooc/zsgl/video.ts diff --git a/package-lock.json b/package-lock.json index 0de537e6..45b4b075 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cxmooc-tools", - "version": "3.0.0", + "version": "3.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cxmooc-tools", - "version": "3.0.0", + "version": "3.1.0", "license": "MIT", "dependencies": { "js-base64": "^3.7.5", diff --git a/src/config.ts b/src/config.ts index 9e6fa05e..6e7a0a34 100644 --- a/src/config.ts +++ b/src/config.ts @@ -41,6 +41,10 @@ export class SystemConfig { ], "mooc163": [ "*://www.icourse163.org/learn/*", "*://www.icourse163.org/spoc/learn/*" + ], + "zsgl": [ + "*://zsgl.lzlj.com/#/home/studyDetail?*", + "*://zsgl.lzlj.com/#/home/courseDetail?*" ] } public static config: { [key: string]: PlatformConfig } = { @@ -205,6 +209,70 @@ export class SystemConfig { unit: "秒", value: "5", }], + }, + zsgl: { + name: "知识管理", + items: [{ + title: "zsgl随机答案", + description: "如果题库没有正确的答案会随机选择", + type: "checkbox", + key: "rand_answer", + value: false, + }, { + title: "zsgl自动挂机", + description: "进入一个页面就会自动开始挂机,完成一个任务之后会自动进行下一个", + type: "checkbox", + key: "auto", + value: false, + }, + // { + // title: "视频静音", + // description: "播放视频时,自动开启静音", + // type: "checkbox", + // key: "video_mute", + // value: true, + // }, + { + title: "忽略题目", + description: "自动挂机时,忽略掉题目不做,直接跳过", + type: "checkbox", + key: "answer_ignore", + value: false, + }, { + title: "超级模式", + description: "超星平台下,超级模式会自动将flash播放器换成h5播放器", + type: "checkbox", + key: "super_mode", + value: true, + }, { + title: "播放源", + description: "锁定视频播放源,为空为记录最后一次选中的源(公网1,公网2等)", + type: "text", + key: "video_cdn", + value: "默认" + }, { + title: "播放倍速", + description: "视频播放的倍数,1为正常速度(最高16倍,该功能有一定危险)", + type: "text", + key: "video_multiple", + prompt: "这是一个很危险的功能,建议不要进行调整,如果你想调整播放速度请在下方填写yes(智慧树平台播放速度和视频进度无关,最高只能1.5倍速)", + unit: "倍", + value: "1", + }, { + title: "跳转间隔", + description: "视频(题目,任务点)完成后n分钟再继续下一个任务,可以有小数点,例如:0.5=30秒", + type: "text", + key: "interval", + unit: "分", + value: "1", + }, { + title: "做题间隔", + description: "每一道题之间填写答案的时间间隔", + type: "text", + key: "topic_interval", + unit: "秒", + value: "5", + }], }, }; } diff --git a/src/mooc/zsgl/course.ts b/src/mooc/zsgl/course.ts new file mode 100644 index 00000000..94b400cd --- /dev/null +++ b/src/mooc/zsgl/course.ts @@ -0,0 +1,37 @@ +import { MoocTaskSet } from './../../internal/app/mooc'; +/* + * @Author: guotao + * @Date: 2024-11-28 10:17:42 + * @LastEditors: guotao + * @LastEditTime: 2024-11-28 10:26:08 + * @FilePath: \zsgl-tools\src\mooc\zsgl\course.ts + * @Description: + * + * Copyright (c) 2024 by lzlj, All Rights Reserved. + */ +// + +import { MoocEvent } from "@App/internal/app/mooc"; +import { EventListener } from "@App/internal/utils/event"; +import { CxTask } from '../chaoxing/task'; +import { Task } from '@App/internal/app/task'; + +// 课程任务 +export class zsglCourse extends EventListener implements MoocTaskSet{ + constructor() { + super(); + } + Init(): Promise { + throw new Error('Method not implemented.'); + } + Stop(): Promise { + throw new Error('Method not implemented.'); + } + Next(): Promise { + throw new Error('Method not implemented.'); + } + SetTaskPointer(index: number): void { + throw new Error('Method not implemented.'); + } + protected tasklist:Array +} \ No newline at end of file diff --git a/src/mooc/zsgl/platform.ts b/src/mooc/zsgl/platform.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/mooc/zsgl/task.ts b/src/mooc/zsgl/task.ts new file mode 100644 index 00000000..dcdeae3b --- /dev/null +++ b/src/mooc/zsgl/task.ts @@ -0,0 +1,98 @@ +import { Task, TaskEvent } from "@App/internal/app/task"; +import { CssBtn } from "./utils"; +import { createBtn, get } from "@App/internal/utils/utils"; +import { Application } from "@App/internal/application"; + +export abstract class zsglTask extends Task { + public jobIndex: Number + public taskInfo: any + protected context: any + public done: boolean + public constructor(context:any,taskInfo:any) { + super(); + this.context = context + this.taskInfo = taskInfo + if(this.taskInfo?.job){ + this.done = false + }else{ + this.done = true + } + } + + protected callEvent(event: TaskEvent, ...args: any): void { + if(event == "complete"){ + this.done = true + } + super.callEvent(event, ...args); + } + public async Init(): Promise{ + + } + public Submit(): Promise { + return new Promise(resolve => { + resolve() + }) + } + public Stop(): Promise { + return new Promise(resolve => { + resolve(); + }); + } + public Done(): boolean { + return this.done; + } +} + +export class zsglTaskController{ + public task: zsglTask; + protected prev: HTMLElement; + constructor(prev: HTMLElement, task: zsglTask) { + this.task=task + this.prev = prev + prev.style.textAlign = "center"; + prev.style.width = "100%"; + prev.prepend(this.prev); + this.defaultBtn(); + } + public defaultBtn() { + let startBtn = CssBtn(createBtn(Application.App.config.auto ? "暂停挂机" : "开始挂机", "点击开始自动挂机", "zsgl-btn")); + startBtn.innerText = "开始" + startBtn.onclick = () => { + if (startBtn.innerText == '暂停挂机') { + Application.App.config.auto = false; + startBtn.innerText = "开始挂机"; + startBtn.title = "点击开始自动挂机"; + Application.App.log.Info("挂机停止了"); + } else { + Application.App.config.auto = true; + startBtn.innerText = '暂停挂机'; + startBtn.title = "停止挂机,开始好好学习"; + Application.App.log.Info("挂机开始了"); + this.task.Start(); + } + }; + this.prev.append(startBtn); + } + + public append(el: HTMLElement): void { + this.prev.append(el); + } + + public download(): HTMLElement { + if (!this.task.taskInfo.property.objectid) { + return; + } + let download = CssBtn(createBtn("下载资源", "我要下载下来好好学习", "cx-btn")); + download.style.background = "#999999"; + download.onclick = () => { + (get("https://mooc1-1.chaoxing.com/ananas/status/" + this.task.taskInfo.property.objectid, (data: string) => { + let json = JSON.parse(data); + prompt("如果打开下载失败,请复制下面链接手动下载", json.download); + window.open(json.download); + })).error(() => { + alert("资源信息获取失败"); + }); + }; + return download; + } +} \ No newline at end of file diff --git a/src/mooc/zsgl/utils.ts b/src/mooc/zsgl/utils.ts new file mode 100644 index 00000000..73c31e6b --- /dev/null +++ b/src/mooc/zsgl/utils.ts @@ -0,0 +1,37 @@ + +/** + * 美化按钮 + */ +export function CssBtn(btn: HTMLButtonElement): HTMLButtonElement { + btn.style.outline = 'none'; + btn.style.border = '0'; + btn.style.background = '#7d9d35'; + btn.style.color = '#fff'; + btn.style.borderRadius = '4px'; + btn.style.padding = '2px 8px'; + btn.style.cursor = 'pointer'; + btn.style.fontSize = '12px'; + btn.style.marginLeft = '4px'; + btn.onmousemove = () => { + btn.style.boxShadow = '1px 1px 1px 1px #ccc'; + }; + btn.onmouseout = () => { + btn.style.boxShadow = ''; + }; + return btn; +} + +export function CreateNoteLine(text: string, label: string, append?: HTMLElement, after?: HTMLElement) { + let p = document.createElement("p"); + p.style.color = "red"; + p.style.fontSize = "14px"; + p.className = "prompt-line-" + label; + p.innerHTML = text; + if (append != undefined) { + append.append(p); + } + if (after != undefined) { + after.after(p); + } + return p; +} \ No newline at end of file diff --git a/src/mooc/zsgl/video.ts b/src/mooc/zsgl/video.ts new file mode 100644 index 00000000..e69de29b From b048bbd9ee0cd7d9086698f3462524afb8448c89 Mon Sep 17 00:00:00 2001 From: guotao <1531188409@qq.com> Date: Thu, 28 Nov 2024 16:22:18 +0800 Subject: [PATCH 2/4] =?UTF-8?q?docs:=20=E5=91=BD=E5=90=8D=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=B8=BA=E7=9F=A5=E8=AF=86=E7=AE=A1=E7=90=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 154 +----------------------------------------------------- 1 file changed, 1 insertion(+), 153 deletions(-) diff --git a/README.md b/README.md index 7b3710e9..6925ecfd 100644 --- a/README.md +++ b/README.md @@ -1,156 +1,4 @@

-网课小工具(重制版) +知识管理系统工具

- -![GitHub stars](https://img.shields.io/github/stars/chettoy/cxmooc-tools.svg) -![GitHub tag](https://img.shields.io/github/v/tag/chettoy/cxmooc-tools.svg?label=version) -[![Edge add-on](https://img.shields.io/badge/dynamic/json?label=edge%20add-on&color=brightgreen&prefix=v&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fonjbbeifafonkjcpaeeelbfbidfdpcoa)](https://microsoftedge.microsoft.com/addons/detail/onjbbeifafonkjcpaeeelbfbidfdpcoa) -[![Edge rating](https://img.shields.io/badge/dynamic/json?label=edge%20rating&color=brightgreen&suffix=%20/%205&query=%24.averageRating&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fonjbbeifafonkjcpaeeelbfbidfdpcoa)](https://microsoftedge.microsoft.com/addons/detail/onjbbeifafonkjcpaeeelbfbidfdpcoa) -[![Edge users](https://img.shields.io/badge/dynamic/json?label=edge%20users&query=%24.activeInstallCount&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fonjbbeifafonkjcpaeeelbfbidfdpcoa)](https://microsoftedge.microsoft.com/addons/detail/onjbbeifafonkjcpaeeelbfbidfdpcoa) -[![Chrome](https://img.shields.io/badge/chrome-old%20version-yellowgreen)](https://chrome.google.com/webstore/detail/%E8%B6%85%E6%98%9F%E6%85%95%E8%AF%BE%E5%B0%8F%E5%B7%A5%E5%85%B7/kkicgcijebblepmephnfganiiochecfl?hl=zh-CN) -[![FireFox](https://img.shields.io/badge/firefox-old%20version-yellowgreen)](https://addons.mozilla.org/zh-CN/firefox/addon/%E8%B6%85%E6%98%9F%E6%85%95%E8%AF%BE%E5%B0%8F%E5%B7%A5%E5%85%B7/) -[![tampermonkey](https://img.shields.io/badge/tampermonkey-old%20version-yellowgreen)](https://bbs.tampermonkey.net.cn/thread-61-1-1.html) -![GitHub All Releases](https://img.shields.io/github/downloads/chettoy/cxmooc-tools/total) -[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fchettoy%2Fcxmooc-tools.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fchettoy%2Fcxmooc-tools?ref=badge_shield) - -
- -- [关于网课小工具](#关于网课小工具) -- [从应用商店下载](#从应用商店下载) -- [功能支持列表](#功能支持列表) -- [适配列表](#适配列表) -- [参与开发](#参与开发) - - [环境](#环境) - - [Build](#build) - - [贡献流程](#贡献流程) -- [题库](#题库) -- [关于反馈](#关于反馈) -- [免责声明](#免责声明) - -## 关于重制版 - -在原有基础上 -- 更新了全部依赖 (webpack5, vue3, vuepress2, ...) -- 替换了一些弃用的库和方法 -- 内置了WebAssembly模块以还原超星网页中的字体混淆 -- 添加了题库镜像 (基于actix-web开发的备用接口) -- 其他细节优化 -- 迁移至 Manifest V3 版本规范(浏览器扩展可以重新上架啦) -- 以及版本号提升至3.0.0 - -## 关于网课小工具 - -一个 超星(学习通)/智慧树(知到)/中国大学mooc 刷课工具,火狐,谷歌,油猴支持.全自动任务,视频倍速秒过,作业考试题库,验证码自动打码(੧ᐛ੭挂科模式,启动) -**如果觉得好用,顺手点个 Star 吧 ❤❤❤** - -**仓库地址:[chettoy/cxmooc-tools](https://github.com/chettoy/cxmooc-tools)** ![GitHub Repo stars](https://img.shields.io/github/stars/chettoy/cxmooc-tools?style=social) - -**原作地址:[CodFrm/cxmooc-tools](https://github.com/CodFrm/cxmooc-tools)** - -## 从应用商店下载 - -[Edge商店](https://microsoftedge.microsoft.com/addons/detail/onjbbeifafonkjcpaeeelbfbidfdpcoa) (已上架) - -[Chrome商店](https://chrome.google.com/webstore/detail/%E8%B6%85%E6%98%9F%E6%85%95%E8%AF%BE%E5%B0%8F%E5%B7%A5%E5%85%B7/kkicgcijebblepmephnfganiiochecfl?hl=zh-CN) (旧版) - -[FireFox商店](https://addons.mozilla.org/zh-CN/firefox/addon/%E8%B6%85%E6%98%9F%E6%85%95%E8%AF%BE%E5%B0%8F%E5%B7%A5%E5%85%B7/) (旧版) - -[油猴](https://bbs.tampermonkey.net.cn/thread-61-1-1.html) (旧版) - -## 功能支持列表 - -> 详情请看使用文档,不同平台所支持的功能不尽相同 - -- [x] 视频挂机 - -- [ ] 视频秒过 - -- [x] 视频倍速 - -- [x] 静音播放 - -- [x] 任务答题 - -- [x] 作业答题 - -以上功能建议使用 [FxxkStar](https://github.com/chettoy/FxxkStar) 效果更佳 - -- [x] 自动阅读 - -- [ ] 自动填写验证码 - -- [x] 考试答题 - -## 适配列表 - -- [x] Chrome for PC -- [x] Microsoft Edge for PC -- [ ] Firefox for PC (未测试) -- [ ] Firefox for Mobile (未测试) -- [x] QQ 浏览器 for PC -- [ ] Tampermonkey (未测试) - -## 参与开发 - -> 如果你想参与开发,请阅读下面内容,如果只是使用本扩展,请移步 **[使用文档(旧版)](https://cx.icodef.com/)** - -### 环境 - -* Node.js & npm -- Rust & cargo -- wasm-pack - -### Build - -```bash -git clone https://github.com/chettoy/cxmooc-tools.git -cd cxmooc-tools -npm install -npm run build -# 开发模式请使用 -npm run dev -# 打包生成扩展和脚本 -npm run pack -# 生成文档 -npm run docs:build -npm run docs:dev -``` - -> 由于 `chaoxing-rs`(超星协议的rust实现) 未发布,编译前请暂时删去`webpack.config.js`中的`WasmPackPlugin`部分以跳过wasm模块的重新构建 - -### 贡献流程 - -1. `Fork Repo` -2. 发起`Pull Request`,并简要描述更改内容。 -3. `CI 检查通过` -4. `CodeReview` -5. 合并到项目仓库 - -## 题库 - -1. 题库大部分答案来源于用户答题后的页面采集,**所以需要有人第一次做过**,后来的人才能搜索到题目。 -2. 可以配置随机题目,当题库中没有的题目则会自动随机选择一个选项 -3. 考试题库收集,需要考试完毕后,进入考试答案页面,扩展会自动收集. - -题库记录提示: - -![](/dist/images/3.webp) - -## 关于反馈 - -您可以通过Issues反馈,反馈时请尽量提供足够明确的信息。 - -## 免责声明 - -本项目完全开源,免费,仅供技术学习和交流,**开发者团队并未授权任何组织、机构以及个人将其用于商业或者盈利性质的活动。也从未使用本项目进行任何盈利性活动。未来也不会将其用于开展营利性业务。个人或者组织,机构如果使用本项目产生的各类纠纷,法律问题,均由其本人承担。** - -如果您开始使用本项目,即视为同意项目免责声明中的一切条款,条款更新不再另行通知。**开发者仅接受和捐赠者之间不构成购买或雇佣关系的捐赠或者赞赏。** 如果您选择捐赠此项目,我们会列出一份捐赠者名单(包含捐赠金额,日期),但不会公布您的捐赠账号。如果您选择捐赠,那么我将视之为您完全自愿的,没有任何雇佣,购买关系的捐赠。 - -The project is completely open source, free, and is for technical learning and communication only. **The developer team does not authorize any organization, organization, or individual to use it for commercial or profitable activities. Never use this project for any profitable activities. It will not be used for profit-making business in the future. Individuals or organizations and organizations that use the various disputes arising from the project and legal issues shall be borne by themselves.** - -If you start using this project, you are deemed to agree to all the terms in the project disclaimer, and the terms are updated without further notice. **Developers only accept donations or appreciations that do not constitute a purchase or employment relationship with the donor.** If you choose to donate this item, we will list a list of donors (including donation amount, date), but will not announce your donation account. If you choose to donate, then I will treat you as completely voluntary, without any employment, donation of the relationship. - -## License - -[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fchettoy%2Fcxmooc-tools.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fchettoy%2Fcxmooc-tools?ref=badge_large) From 818689aed667168d8614013cfa5ebc70857f7726 Mon Sep 17 00:00:00 2001 From: guotao <1531188409@qq.com> Date: Thu, 28 Nov 2024 17:08:06 +0800 Subject: [PATCH 3/4] feat: Implement zsglCourse task handling and Init method --- src/mooc/zsgl/course.ts | 107 +++++++++++++++++++++++++++++++++-- src/mooc/zsgl/factory.ts | 118 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 src/mooc/zsgl/factory.ts diff --git a/src/mooc/zsgl/course.ts b/src/mooc/zsgl/course.ts index 94b400cd..6e1971e6 100644 --- a/src/mooc/zsgl/course.ts +++ b/src/mooc/zsgl/course.ts @@ -3,7 +3,7 @@ import { MoocTaskSet } from './../../internal/app/mooc'; * @Author: guotao * @Date: 2024-11-28 10:17:42 * @LastEditors: guotao - * @LastEditTime: 2024-11-28 10:26:08 + * @LastEditTime: 2024-11-28 17:04:33 * @FilePath: \zsgl-tools\src\mooc\zsgl\course.ts * @Description: * @@ -15,23 +15,120 @@ import { MoocEvent } from "@App/internal/app/mooc"; import { EventListener } from "@App/internal/utils/event"; import { CxTask } from '../chaoxing/task'; import { Task } from '@App/internal/app/task'; +import { zsglTask } from '@App/mooc/zsgl/task'; +import { Application } from '@App/internal/application'; // 课程任务 export class zsglCourse extends EventListener implements MoocTaskSet{ + protected taskList: Array + protected attachments:Array constructor() { super(); } - Init(): Promise { - throw new Error('Method not implemented.'); + public Init(): Promise { + + return new Promise((resolve, reject) => { + let first = true; + Application.App.log.Debug('zsglCourse Init'); + document.addEventListener("load", ev => { + let el = (ev.target); + if (el.id == 'iframe'){ + Application.App.log.Debug('zsglCourse Init iframe loaded'); + this.OperateCard(el) + first && resolve(undefined) + first=false + } + },true) + }); } Stop(): Promise { throw new Error('Method not implemented.'); } + protected taskIndex: number = 0; Next(): Promise { - throw new Error('Method not implemented.'); + return new Promise((resolve, reject) => { + if (this.taskIndex > this.taskList.length) { + resolve(this.taskList[this.taskList.length]) + this.taskIndex++ + } + this.addEventListener("reload", async () => { + resolve(await this.Next()) + }) + this.nextPage(null); + }) + } + protected afterPage(): HTMLElement { + //感觉奇葩的方法... + let els = document.querySelectorAll("div.ncells > *:not(.currents) > .orange01"); + let now = document.querySelector("div.ncells > .currents"); + for (let i = 0; i < els.length; i++) { + if (now.getBoundingClientRect().top < els[i].getBoundingClientRect().top) { + return els[i]; + } + } + return null; } + protected nextPage(num: number) { + let el = document.querySelector("span.currents ~ span") || document.querySelector(".prev_next.next"); + if (el != undefined) { + return el.click(); + } + + //只往后执行 + el = this.afterPage(); + if (el == undefined) { + //进行有锁任务查找 + if (document.querySelector("div.ncells > *:not(.currents) > .lock") == undefined) { + return this.callEvent("complete"); + } + return setTimeout(() => { + if (num > 5) { + return this.callEvent("error", "被锁卡住了,请手动处理"); + } + Application.App.log.Info("等待解锁"); + this.nextPage(num + 1); + }, 5000); + } + (el.parentElement.querySelector("a>span")).click(); + } + SetTaskPointer(index: number): void { throw new Error('Method not implemented.'); } - protected tasklist:Array + + // 操作任务卡,一个页面会包含很多任务,取出来 + public async OperateCard(iframe: HTMLIFrameElement) { + let iframeWindow: any = iframe.contentWindow; + // 判断任务的参数 + if (iframeWindow.mArg == undefined) { + let match = iframeWindow.document.body.innerHTML.match(/try{\s+?mArg = (.*?);/); + if (!match) { + return; + } + iframeWindow.mArg = JSON.parse(match[1]); + } + // 任务的属性 + this.attachments = >iframeWindow.mArg.attachments; + this.taskList = new Array(); + // 构建任务 + for (let index = 0; index < this.attachments.length; index++) { + let value = this.attachments[index]; + value.defaults = >iframeWindow.mArg.defaults; + let task: zsglTask; + // 任务工厂去创建对应的任务对象 + task = TaskFactory.CreateCourseTask(iframeWindow, value); + if (!task) { + Application.App.log.Debug("!task: " + JSON.stringify(value)); + continue; + } + task.jobIndex = index; + this.taskList.push(task); + task.addEventListener("complete", () => { + this.callEvent("taskComplete", index, task); + }); + await task.Init(); + } + this.taskIndex = 0; + this.callEvent("reload"); + } } \ No newline at end of file diff --git a/src/mooc/zsgl/factory.ts b/src/mooc/zsgl/factory.ts new file mode 100644 index 00000000..e6a20998 --- /dev/null +++ b/src/mooc/zsgl/factory.ts @@ -0,0 +1,118 @@ +import { Application } from "@App/internal/application"; +import { zsglTask } from "./task"; + + +// 任务工厂,创建对应的任务 +export class TaskFactory { + public static fix_zsglsecret(document: Document): number { + let captures: RegExpMatchArray = document.documentElement.outerHTML + .match(/url\('data:application\/font-ttf;charset=utf-8;base64,(.*?)'\)/); + Application.App.log.Debug("zsglsecret", document.documentElement); + Application.App.log.Debug("zsglsecret", captures); + Application.App.log.Debug(".zsglsecret", document.querySelectorAll(".font-zsglsecret")); + if (!captures || captures.length < 2) return -1; + let zsglsecret: string = captures[1]; + let t0 = Date.now(); + const zsgluncover = zsglUncover.new_default(); + let t1 = Date.now(); + Application.App.log.Info(`[fxxk] 解压默认数据 (${(t1 - t0) / 1000}s)`); + let t2 = Date.now(); + let trans: Map = zsgluncover.get_translate(zsglsecret); + let fix_count = 0; + const doFix = (nodes: NodeListOf) => { + nodes.forEach(n => { + if (n.nodeType === 3) { // text + let text = n; + if (text.data.trim().length === 0) { + return; + } + trans.forEach((v, k) => { + let offset = text.data.indexOf(k); + while (offset != -1) { + text.replaceData(offset, k.length, v); + fix_count += 1; + offset = text.data.indexOf(k, offset + v.length); + } + }); + } else if (n.hasChildNodes()) { + doFix(n.childNodes); + } + }); + }; + document.querySelectorAll(".font-zsglsecret").forEach(el => doFix(el.childNodes)); + let t3 = Date.now(); + Application.App.log.Info(`修复乱码 ${fix_count} 个字 (${(t3 - t2) / 1000}s)`); + return trans.size; + } + + public static CreateCourseTask(context: any, taskinfo: any): zsglTask { + if (taskinfo.property.module == "insertaudio") { + taskinfo.type = "audio"; + } + //TODO:优化 + if (taskinfo.type != "video" && taskinfo.type != "workid" && taskinfo.type != "document" + && taskinfo.type != "audio") { + return null; + } + let task: zsglTask; + let taskIframe = (context).document.querySelector( + "iframe[jobid='" + taskinfo.jobid + "']" + ); + let prev: HTMLElement; + if (taskIframe == undefined) { + taskIframe = (context).document.querySelector( + "iframe[data*='" + taskinfo.property.mid + "'],iframe[objectid='" + taskinfo.property.objectid + "']" + ); + prev = document.createElement("div"); + taskIframe.parentElement.prepend(prev); + } else { + prev = taskIframe.previousElementSibling + } + switch (taskinfo.type) { + case "video": { + let bar = new zsglVideoControlBar(prev, new Video(taskIframe.contentWindow, taskinfo)); + task = bar.task; + (