// ==UserScript==
// @name 破解立知
// @namespace https://ez118.github.io/
// @version 8.0.0
// @description 立知课堂破解工具,提供丰富功能(由上海市某中学的多位青年于2022上海疫情风控时期共同开发、支持、调试和维护)
// @author ZZY_WISU
// @match https://*.imlizhi.com/slive/pc/*
// @match https://easilive.seewo.com/*
// @license GPL3
// @icon https://cstore-en-public-tx.seewo.com/easinote5_public/da0ab8b50ba740babd492b5aa6f2fc7f
// @run-at document-end
// @grant GM_xmlhttpRequest
// @grant GM_download
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @require https://unpkg.com/[email protected]/dist/pako.min.js
// ==/UserScript==
/* 自定义部分 */
let api = "https://s2.imlizhi.com/slive/pc/enow/thumbnail/api/v1/courseware";
let ReaderUrl = "https://easilive.seewo.com/ZZY_WISU/";
let MaxPageNum = 200;
let ShareReaderUrl = "https://pjlz.m-e.top/read/";
let AutoAnswerText = "老师好~😄😄😄";
function ajax(url, func, data) {
let xhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhttp.onreadystatechange = () => {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) func(xhttp.responseText);
else if (xhttp.status === 404) func("");
}
};
xhttp.open("POST", url, true);
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send(data);
};
function OpenExplorer(cid, title, ver) {
if (GM_getValue('Settings')[1] === "1") {
let WinTop = (window.screen.availHeight - 350) / 2;
let WinLeft = (window.screen.availWidth - 640) / 2;
window.open(
`${ReaderUrl}@${cid}@${ver}@${encodeURI(title)}`,
'',
`width=640, height=400, top=${WinTop}, left=${WinLeft}`
);
} else {
window.open(`${ReaderUrl}@${cid}@${ver}@${encodeURI(title)}`);
}
};
function GetReplayList() {
let uid = window.location.href.split("?")[1].split("&")[0].split("=")[1];
let ts = new Date().getTime();
ajax(`../apis.json?actionName=GET_PLAYBACK_DETAIL&ts=${ts}`, restxt => {
if (!restxt) { alert("Oh Shit! 失败了!"); return; }
let jstr = eval(`(${restxt})`);
if (jstr.error_code === 0) {
let OPStr = "";
[0,1,2,3,4,5,6,7,8,9,10].forEach(i => {
try { OPStr += `${i+1}. ${jstr.data.capsuleDetail.cwList[i].cwName}\n`; } catch {}
});
let k = prompt(`请选择需要打开的课件(填数字编号)\n${OPStr}`, "1");
let item = jstr.data.capsuleDetail.cwList[k-1];
OpenExplorer(item.cwId, item.cwName, item.cwVersion);
}
}, `{"courseUid":"${uid}"}`);
};
function GetLiveList(){
let uid = window.location.href.split("?")[1].split("&")[0].split("=")[1];
let ts = new Date().getTime();
ajax(`./apis.json?actionName=GET_COURSE_ACCESS_CODE_LIST&t=${ts}`, restxt => {
if (!restxt) { GetReplayList(); return; }
let jstr = eval(`(${restxt})`);
if (jstr.error_code === 0) {
let OPStr = "";
[0,1,2,3,4,5,6,7,8,9,10].forEach(i => {
try { OPStr += `${i+1}. ${jstr.data[i].name}\n`; } catch {}
});
let k = prompt(`请选择需要打开的课件(填数字编号)\n${OPStr}`, "1");
let item = jstr.data[k-1];
OpenExplorer(item.cid, item.name, item.version);
}
}, `{"courseUid":"${uid}"}`);
};
const UnlockLimit = () => {
try { document.getElementById('enow__non-interacte-hover').style.display = "none"; } catch {}
try { document.getElementsByClassName("enow__teachingtool-hide")[0].className = "enow__teachingtool"; } catch {}
};
const MsgWordNumBreak = () => {
try { document.getElementsByClassName("live-chat-send-msg-txt")[0].removeAttribute("maxlength"); } catch {}
};
const RemoveCover = () => {
try { document.getElementsByClassName('live-poster live-pc-poster')[0].style.visibility = "hidden"; } catch {}
};
const RemoveHand = (mode = "HideHand") => {
try {
let hand = document.getElementsByClassName('live-raise-hand live-pc-raise-hand live-student-raise-hand')[0];
if (mode === "HideHand") hand.style.visibility = "hidden";
else {
hand.style.cssText = "width:25px; height:25px; overflow:hidden; border-radius:10px;";
document.getElementsByClassName('live-raise-hand-item')[0].style.cssText = "width:25px; height:25px;";
}
} catch {}
};
const Settings = () => {
let oldStr = GM_getValue('Settings') || "1000";
let promptText = `【欢迎使用偏好设置】
请依次填写每项(1 开 0 关)
1. 屏蔽广告
2. 弹窗打开课件
3. 骇客模式(解除限制)
4. 自动填充问候语`;
let newStr = prompt(promptText, oldStr);
if (newStr) GM_setValue('Settings', newStr);
};
const GetToken = () => {
try {
let head = document.head.innerHTML;
let tokenStr = head.substring(head.indexOf("window['token']") + 15, head.indexOf("window['cloudAppId']"));
tokenStr = tokenStr.replace(/[^\w]/g, '').trim();
if (tokenStr.length === 32) GM_setValue('AuthToken', tokenStr);
return tokenStr;
} catch {
alert("shit");
}
};
/* 注册(不可用)菜单 */
GM_registerMenuCommand('浏览教师课件', GetLiveList, 'o');
GM_registerMenuCommand('解除操作课件限制', UnlockLimit, 'u');
GM_registerMenuCommand('解除讨论区字符限制', MsgWordNumBreak, 'm');
GM_registerMenuCommand('移除课前等待遮罩', RemoveCover, 'r');
GM_registerMenuCommand('隐藏举手按钮', () => RemoveHand("HideHand"), 'h');
GM_registerMenuCommand('讨论区刷屏', () => {
const Send = (con, rid) => {
let uid = window.location.href.split("?")[1].split("&")[0].split("=")[1];
let ts = new Date().getTime();
ajax(`./apis.json?actionName=CHAT_SEND_QUESTION&t=${ts}`, str => {
if (str) {
let jstr = eval(`(${str})`);
// 不做处理
}
}, `{"roomId":"${rid}","courseUid":"${uid}","text":"${con}"}`);
};
const GetRoomId = () => {
let uid = window.location.href.split("?")[1].split("&")[0].split("=")[1];
let ts = new Date().getTime();
ajax(`./apis.json?actionName=GET_TARGET_COURSE&t=${ts}`, restxt => {
if (!restxt) return;
let jstr = eval(`(${restxt})`);
let rid = jstr.data.roomId;
let con = prompt("请输入发送内容:", "");
if (con === null) return;
let times = parseInt(prompt("请输入发送次数:", "1"),10);
[1,2,3,4,5,6,7,8,9,10].forEach(i => { if (i <= times) Send(con, rid) });
}, `{"courseUid":"${uid}"}`);
};
GetRoomId();
}, 'g');
GM_registerMenuCommand('查看TOKEN(附说明)', () => {
prompt("【查看TOKEN】\n复制以下 TOKEN:", GetToken());
}, 'v');
GM_registerMenuCommand('偏好设置', Settings, 's');
/* 主体自执行部分 */
(() => {
'use strict';
try { console.log(`Settings: ${GM_getValue('Settings')}`); } catch { GM_setValue('Settings', "1000"); }
if (!GM_getValue('Settings')) GM_setValue('Settings', "1000");
let href = window.location.href;
if (href.startsWith(ReaderUrl)) {
let [ , data, adds, title ] = href.split("@");
let version = Number(adds);
let dochtml = "";
let obj = [];
let PageCnt = 0;
let ShareData = "";
GM_xmlhttpRequest({
method: "GET",
url: `${api}?coursewareId=${data}&version=${version}&resolution=960_640`,
headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
onload: (res) => {
let filelist = JSON.parse(res.responseText);
MaxPageNum = filelist.data.length;
filelist.data.forEach(item => { obj[item.pageIndex] = item.downloadUrl; });
filelist.data.forEach((item, idx) => {
if (obj[idx]) {
dochtml += `<img src='${obj[idx]}' title='第${idx+1}页'><br>`;
PageCnt++;
ShareData += obj[idx].replace("https://cstore-private-bs.seewo.com/easinote/encloud-", "").split("?")[0] + ",";
}
});
ShareData = window.btoa(pako.gzip(ShareData.replace("undefined", ""), { to: "string" }));
let script = `<script>function printmode(){
document.querySelector(\".msg\").remove();
document.querySelector(\".share\").remove();
document.querySelector(\"style\").innerText = \"img{ width:100%; margin-top:15px; }\"; setTimeout(window.print(),100);
}</script>`;
let header = `<title>课件浏览器 | ${decodeURI(title)}</title>
<meta charset="utf-8">
<style>body{background-color:rgb(50,54,57);user-select:none;margin:0;}
.ctrl{font-size:14px;border-radius:15px;padding:5px 13px;background-color:rgb(51,51,51);color:#FFF;border:1px solid #CCC;}
.msg{position:fixed;top:15px;left:15px;z-index:5;}
.share{position:fixed;top:15px;right:15px;z-index:5;}
img{width:60%;min-width:600px;margin-top:10px;border-radius:4px;}
.printBtn{margin:10px;}a{color:#FFF;text-decoration:none;}</style>`;
let body = `<body>
<div class="ctrl msg"> 共${PageCnt}页 </div>
<div class="ctrl share" title="右键此处,复制分享链接">
<a href="${ShareReaderUrl}#${ShareData}" target="_blank">分享</a>
</div>
<center>${dochtml}
<button onclick="this.remove();printmode();" class="ctrl printBtn">打印 & PDF 存储模式</button>
</center>
</body>`;
document.write(header + script + body);
},
onerror: () => {
document.write("<title>出现问题</title><h2>抱歉,无法获取课件</h2><hr><b>请专心听课吧。</b>");
}
});
} else if (href.split("/")[3] === "preview" || href.split("/")[3] === "course") {
if (GM_getValue('Settings')[0] === "1") {
setTimeout(() => {
try { document.getElementsByClassName('download-app-1s9WLH')[0].remove(); } catch {}
}, 1000);
}
} else if (href.split("/")[3] === "slive" && href.split("/")[5].split("?")[0] === "room") {
GetToken();
setTimeout(() => {
let s = GM_getValue('Settings');
if (s[2] === "1") {
UnlockLimit(); RemoveCover(); RemoveHand("MinimizeHand"); MsgWordNumBreak();
}
if (s[3] === "1") {
let ta = document.getElementsByClassName("live-chat-send-msg-txt")[0];
ta.innerText = AutoAnswerText; ta.focus();
}
if (s[0] === "1") {
try { document.getElementsByClassName('live-download live-topbar-item')[0].style.display = "none"; } catch {}
}
}, 4000);
}
})();