feat: 故障推送 / 公需课自动重学 / 插件解耦,发版 v0.0.8
体检修复:启动日志不再打印 AUTH_TOKEN、密钥可清空、推送失败不占整段冷却、目录名与文案统一成 plugins/。
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
"""登录链路:base64 账号密码、图形验证码识别、ITLMS 换票。"""
|
||||
import base64
|
||||
import re
|
||||
import time
|
||||
|
||||
from . import http
|
||||
|
||||
_OCR = None
|
||||
|
||||
|
||||
def b64(text):
|
||||
return base64.b64encode(str(text).encode("utf-8")).decode()
|
||||
|
||||
|
||||
def ocr():
|
||||
"""4 位图形验证码:ddddocr 离线识别。"""
|
||||
global _OCR
|
||||
if _OCR is None:
|
||||
try:
|
||||
import ddddocr
|
||||
except Exception as e:
|
||||
raise RuntimeError("登录要过图形验证码,需要先装 ddddocr(pip install ddddocr):%s" % e)
|
||||
_OCR = ddddocr.DdddOcr(show_ad=False)
|
||||
return _OCR
|
||||
|
||||
|
||||
def captcha(s):
|
||||
raw = s.get(http.G + "/login/readCaptcha.action?d=%.6f" % time.time(), timeout=30).text
|
||||
return base64.b64decode(raw.strip().strip('"').split(",", 1)[-1])
|
||||
|
||||
|
||||
def login_error(s):
|
||||
html = s.get(http.G + "/login.jsp", timeout=30).text
|
||||
m = re.search(r'id="errorText"[^>]*>([^<]*)<', html)
|
||||
return (m.group(1).strip() if m else "")
|
||||
|
||||
|
||||
def sso(s):
|
||||
"""jsglpt 会话换 ITLMS 票,票按 `ITLMS-xxx||ticketId` 两段交给 jsxx。
|
||||
|
||||
交接入口来自 jsglpt 首页那个隐藏表单:
|
||||
`GET https://jsxx.gds.edu.cn/nts/loginToStoreByAccount?ticket=&ticketId=`
|
||||
"""
|
||||
r = s.post(http.G + "/teacher/ssoItlmsGxkTicket.action?verificaCode=true&page=", timeout=30)
|
||||
ticket = (r.text or "").strip()
|
||||
if not ticket.startswith("ITLMS-") or "||" not in ticket:
|
||||
raise http.expired("取 ITLMS 票失败:%s" % (ticket[:80] or "空响应"))
|
||||
t, tid = ticket.split("||", 1)
|
||||
q = s.get(http.X + "/nts/loginToStoreByAccount", params={"ticket": t, "ticketId": tid}, timeout=30)
|
||||
if "logout" not in q.text and "我的课程" not in q.text:
|
||||
raise http.expired("带票进学习平台失败,票可能已失效")
|
||||
return s
|
||||
Reference in New Issue
Block a user