feat: extend optional HTML feedback to graduate imports in 0.7.8
This commit is contained in:
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:html/dom.dart' as dom;
|
||||
import 'package:html/parser.dart' as html;
|
||||
|
||||
/// An opt-in mail attachment, separate from persistent structured logs.
|
||||
@@ -37,11 +38,18 @@ class SchoolPageDiagnostic {
|
||||
void remember(String content, Uri uri) {
|
||||
clear();
|
||||
try {
|
||||
if (uri.scheme != 'https' ||
|
||||
uri.host != 'eams.uestc.edu.cn' ||
|
||||
uri.port != 443 ||
|
||||
final undergraduate =
|
||||
uri.scheme == 'https' &&
|
||||
uri.port == 443 &&
|
||||
uri.host == 'eams.uestc.edu.cn' &&
|
||||
uri.path.startsWith('/eams/');
|
||||
final graduate =
|
||||
uri.host == 'yjsjy.uestc.edu.cn' &&
|
||||
(uri.scheme == 'https' && uri.port == 443 ||
|
||||
uri.scheme == 'http' && uri.port == 80) &&
|
||||
(uri.path == '/pyxx' || uri.path.startsWith('/pyxx/'));
|
||||
if ((!undergraduate && !graduate) ||
|
||||
uri.userInfo.isNotEmpty ||
|
||||
!uri.path.startsWith('/eams/') ||
|
||||
utf8.encode(content).length > maxBytes) {
|
||||
return;
|
||||
}
|
||||
@@ -50,12 +58,35 @@ class SchoolPageDiagnostic {
|
||||
final tables = doc
|
||||
.querySelectorAll('table')
|
||||
.where(
|
||||
(t) =>
|
||||
t.id == 'manualArrangeCourseTable' ||
|
||||
t.querySelector('tr')?.text.contains('课程序号') == true,
|
||||
(t) => graduate
|
||||
? const ['tbl', 'sample-table-1'].contains(t.id)
|
||||
: t.id == 'manualArrangeCourseTable' ||
|
||||
t.querySelector('tr')?.text.contains('课程序号') == true,
|
||||
)
|
||||
.toList();
|
||||
if (tables.isEmpty) return;
|
||||
final graduateTerms = <dom.Element>[];
|
||||
if (graduate) {
|
||||
for (final table in tables) {
|
||||
final id = table.id == 'tbl' ? 'drpxq' : 'xqbh';
|
||||
final original = doc.querySelector('select#$id');
|
||||
if (original == null) continue;
|
||||
final select = dom.Element.tag('select')..id = id;
|
||||
for (final originalOption in original.querySelectorAll('option')) {
|
||||
final option = dom.Element.tag('option')
|
||||
..text = originalOption.text;
|
||||
final value = originalOption.attributes['value'];
|
||||
if (value != null && RegExp(r'^\d{1,6}$').hasMatch(value)) {
|
||||
option.attributes['value'] = value;
|
||||
}
|
||||
if (originalOption.attributes.containsKey('selected')) {
|
||||
option.attributes['selected'] = '';
|
||||
}
|
||||
select.children.add(option);
|
||||
}
|
||||
graduateTerms.add(select);
|
||||
}
|
||||
}
|
||||
final fields = <String, Set<String>>{};
|
||||
void field(String key, String value) {
|
||||
if (const ['semester.id', 'examType.id'].contains(key) &&
|
||||
@@ -83,7 +114,7 @@ class SchoolPageDiagnostic {
|
||||
.join('\n');
|
||||
// Only retain the literal course statements our parser reads. All other
|
||||
// scripts, URL-bearing attributes and form/account fields are omitted.
|
||||
final statements = _courseStatements(script);
|
||||
final statements = undergraduate ? _courseStatements(script) : '';
|
||||
for (final table in tables) {
|
||||
for (final node in table.querySelectorAll(
|
||||
'script,style,link,iframe,object,embed,form,input,textarea,select,button,img,svg,video,audio,source,meta,base',
|
||||
@@ -93,8 +124,16 @@ class SchoolPageDiagnostic {
|
||||
for (final node in [table, ...table.querySelectorAll('*')]) {
|
||||
final attrs = Map<String, String>.from(node.attributes);
|
||||
node.attributes.clear();
|
||||
if (attrs['id'] == 'manualArrangeCourseTable') {
|
||||
node.id = 'manualArrangeCourseTable';
|
||||
final id = attrs['id'];
|
||||
if (node.localName == 'table' &&
|
||||
(id == 'manualArrangeCourseTable' ||
|
||||
graduate && const ['tbl', 'sample-table-1'].contains(id))) {
|
||||
node.id = id!;
|
||||
} else if (graduate &&
|
||||
const ['td', 'th'].contains(node.localName) &&
|
||||
id != null &&
|
||||
RegExp(r'^t[0-7][13579]$').hasMatch(id)) {
|
||||
node.id = id;
|
||||
}
|
||||
for (final key in ['rowspan', 'colspan']) {
|
||||
final value = attrs[key];
|
||||
@@ -108,6 +147,7 @@ class SchoolPageDiagnostic {
|
||||
'$marker<html><head><meta charset="utf-8">'
|
||||
'<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; base-uri \'none\'; form-action \'none\'">'
|
||||
'<title>TPSchedule school diagnostic</title></head><body>'
|
||||
'${graduateTerms.map((t) => t.outerHtml).join()}'
|
||||
'${fields.entries.expand((e) => e.value.map((v) => '<input type="hidden" name="${e.key}" value="$v">')).join()}'
|
||||
'${tables.map((t) => t.outerHtml).join()}'
|
||||
'<script type="application/x-tpschedule-course-data">${statements.replaceAll('<', r'\u003c')}</script></body></html>';
|
||||
|
||||
Reference in New Issue
Block a user