diff --git a/Background Tasks/BackgroundTasks.cs b/Background Tasks/BackgroundTasks.cs
index 447e3dc..0b1504a 100644
--- a/Background Tasks/BackgroundTasks.cs
+++ b/Background Tasks/BackgroundTasks.cs
@@ -78,9 +78,6 @@ public async void Run(IBackgroundTaskInstance taskInstance) {
try {
await Appointment.updateDeadlines();
} catch (Exception) { }
- try {
- if (goRemote) { await Appointment.updateLectures(); }
- } catch (Exception) { }
deferral.Complete();
diff --git a/Class Library/Appointment.cs b/Class Library/Appointment.cs
index 8f31d0d..cac9875 100644
--- a/Class Library/Appointment.cs
+++ b/Class Library/Appointment.cs
@@ -95,9 +95,11 @@ public static async Task updateDeadlines() {
foreach (var i in to_be_inserted) {
Debug.WriteLine("[updateDeadlines] inserting " + i.Subject);
+
if (i.StartTime - DateTime.Now < TimeSpan.FromHours(7)) {
+ // WTF ??
Debug.WriteLine("[updateDeadlines] ignoring " + i.Subject);
- continue;
+ // continue;
}
await ddl_cal.SaveAppointmentAsync(i);
}
@@ -140,25 +142,6 @@ public static async Task updateCalendar() {
Debug.WriteLine("[Appointment] calendar finish");
}
- public static async Task updateLectures() { //always force remote
- Debug.WriteLine("[Appointment] lecture begin");
-
- //TODO: possible duplication, lock?
-
- var lectures = await Remote.getHostedLectures();
-
- //get Calendar object
- AppointmentCalendar cal = await getAppointmentCalendar(lec_cal_name, lec_storedKey);
-
- await deleteAllAppointments(cal);
-
- foreach (var lec in lectures) {
- await cal.SaveAppointmentAsync(getAppointment(lec));
- }
-
- Debug.WriteLine("[Appointment] lecture finish");
- }
-
public static async Task updateTimetable(bool forceRemote = false) {
Debug.WriteLine("[Appointment] update start");
@@ -211,27 +194,8 @@ private static Windows.ApplicationModel.Appointments.Appointment getAppointment(
a.StartTime = DateTime.Parse(e.nq + " " + e.kssj);
a.Duration = DateTime.Parse(e.nq + " " + e.jssj) - a.StartTime;
- // 修正考试时间 12 小时制
- if (e.fl == "考试") {
- if (a.StartTime.Hour < 8) {
- a.StartTime += TimeSpan.FromHours(12);
- }
- a.Subject += "考试";
- }
- a.AllDay = false;
- return a;
- }
- private static Windows.ApplicationModel.Appointments.Appointment getAppointment(Lecture l) {
- var a = new Windows.ApplicationModel.Appointments.Appointment();
- a.Subject = l.summary;
- a.Location = l.location;
- a.StartTime = DateTime.Parse(l.dtstart);
- a.Duration = DateTime.Parse(l.dtend) - a.StartTime;
- a.DetailsKind = AppointmentDetailsKind.PlainText;
- a.Details = l.description;
a.AllDay = false;
- a.BusyStatus = AppointmentBusyStatus.Free;
return a;
}
@@ -240,7 +204,7 @@ private static Windows.ApplicationModel.Appointments.Appointment getAppointment(
Regex re = new Regex("&[^;]+;");
a.Subject = re.Replace(e.name, " ");
a.Location = re.Replace(e.course, " ");
- a.StartTime = DateTime.Parse(e.ddl + " 23:59");
+ a.StartTime = DateTime.Parse(e.ddl);
a.AllDay = false;
a.BusyStatus = e.hasBeenFinished ? AppointmentBusyStatus.Free : AppointmentBusyStatus.Tentative;
if (e.hasBeenFinished)
diff --git a/Class Library/Class Library.csproj b/Class Library/Class Library.csproj
index 2cf7602..5176a99 100644
--- a/Class Library/Class Library.csproj
+++ b/Class Library/Class Library.csproj
@@ -114,9 +114,6 @@
-
- 1.4.9.5
-
5.1.0
diff --git a/Class Library/DataAccess.cs b/Class Library/DataAccess.cs
index 712e0b8..b34c381 100644
--- a/Class Library/DataAccess.cs
+++ b/Class Library/DataAccess.cs
@@ -101,7 +101,7 @@ orderby assignment.daysFromNow() descending
return future.Concat(past.Take(limit - futureCount)).ToList();
}
- public static async Task> getCourses(bool forceRemote = false) {
+ public static async Task> getCourses(bool forceRemote = false, string semester = "") {
if (isDemo()) {
var list = new List();
list.Add(new Course {
@@ -116,6 +116,9 @@ public static async Task> getCourses(bool forceRemote = false) {
return list;
}
+ if(semester == "") {
+ semester = (await getSemester()).id;
+ }
if (!forceRemote) {
//try memory
@@ -135,7 +138,7 @@ public static async Task> getCourses(bool forceRemote = false) {
//fetch from remote
- var _courses = await Remote.getRemoteCourseList();
+ var _courses = await Remote.getRemoteCourseList(semester);
courses = _courses;
writeCache(COURSES_FILENAME, JSON.stringify(_courses));
@@ -144,61 +147,122 @@ public static async Task> getCourses(bool forceRemote = false) {
}
public static async Task getTimetable(bool forceRemote = false) {
- if (isDemo()) {
- var table = new Timetable();
-
- var start = DateTime.Now.AddDays(-20);
- while (start.DayOfWeek != DayOfWeek.Monday)
- start = start.AddDays(-1);
-
- for (var i = 0; i < 10; i++) {
- table.Add(new Event {
- nr = "形式语言与自动机",
- dd = "六教 6A301",
- nq = start.AddDays(i * 7 + 2).ToString("yyyy-MM-dd"),
- kssj = "08:00",
- jssj = "09:35"
- });
+ {
+ if (isDemo()) {
+ var table = new Timetable();
+
+ var start = DateTime.Now.AddDays(-20);
+ while (start.DayOfWeek != DayOfWeek.Monday)
+ start = start.AddDays(-1);
+
+ for (var i = 0; i < 10; i++) {
+ table.Add(new Event {
+ nr = "形式语言与自动机",
+ dd = "六教 6A301",
+ nq = start.AddDays(i * 7 + 2).ToString("yyyy-MM-dd"),
+ kssj = "08:00",
+ jssj = "09:35"
+ });
+
+ table.Add(new Event {
+ nr = "高级数据结构",
+ dd = "六教 6A301",
+ nq = start.AddDays(i * 7 + 2).ToString("yyyy-MM-dd"),
+ kssj = "09:50",
+ jssj = "11:25"
+ });
+
+ table.Add(new Event {
+ nr = "操作系统",
+ dd = "六教 6A303",
+ nq = start.AddDays(i * 7 + 3).ToString("yyyy-MM-dd"),
+ kssj = "09:50",
+ jssj = "11:25"
+ });
+
+ table.Add(new Event {
+ nr = "概率论与数理统计",
+ dd = "六教 6C102",
+ nq = start.AddDays(i * 7 + 4).ToString("yyyy-MM-dd"),
+ kssj = "15:20",
+ jssj = "16:55"
+ });
+
+ table.Add(new Event {
+ nr = "概率论与数理统计",
+ dd = "一教 104",
+ nq = start.AddDays(i * 7 + 1).ToString("yyyy-MM-dd"),
+ kssj = "13:30",
+ jssj = "15:05"
+ });
+ }
+ return table;
+ }
+ }
+ {
+ //fetch from remote
+ string[] 大节开始时间 = {
+ "",
+ "8:00",
+ "9:50",
+ "13:30",
+ "15:20",
+ "17:05",
+ "19:20"
+ };
+ int[] 大节开始小节 = { 0, 1, 3, 6, 8, 10, 12 };
+ string[] 小节结束时间 = {
+ "",
+ "8:45",
+ "9:35",
+ "10:35",
+ "11:25",
+ "12:15",
+ "14:15",
+ "15:05",
+ "16:05",
+ "16:55",
+ "17:50",
+ "18:40",
+ "20:05",
+ "20:55",
+ "21:45"
+ };
- table.Add(new Event {
- nr = "高级数据结构",
- dd = "六教 6A301",
- nq = start.AddDays(i * 7 + 2).ToString("yyyy-MM-dd"),
- kssj = "09:50",
- jssj = "11:25"
- });
+ var table = new Timetable();
- table.Add(new Event {
- nr = "操作系统",
- dd = "六教 6A303",
- nq = start.AddDays(i * 7 + 3).ToString("yyyy-MM-dd"),
- kssj = "09:50",
- jssj = "11:25"
- });
+ bool[] bools = { false, true };
+ foreach (bool getNextSemester in bools) {
+
+ var semester = await getSemester(forceRemote, getNextSemester);
+ var start = DateTime.Parse(semester.startDate);
+
+ foreach (var course in await getCourses(forceRemote, semester.id)) {
+ Debug.WriteLine("[getAllDeadlines] Remote " + course.name);
+ var id = course.id;
+ try {
+ var detail = await Remote.getRemoteCourseDetail(course.id);
+ foreach (var segment in detail) {
+ for (int weekOffset = 0; weekOffset < segment.skzc.Length; ++weekOffset) {
+ if (segment.skzc[weekOffset] == '1') {
+ table.Add(new Event {
+ nr = course.name,
+ dd = segment.skdd,
+ nq = start.AddDays(weekOffset * 7 + segment.skxq - 1).ToString("yyyy-MM-dd"),
+ kssj = 大节开始时间[segment.skjc],
+ jssj = 小节结束时间[大节开始小节[segment.skjc] + segment.skxs - 1]
+ });
+ }
+ }
+ }
+ } catch { }
+ }
+ }
- table.Add(new Event {
- nr = "概率论与数理统计",
- dd = "六教 6C102",
- nq = start.AddDays(i * 7 + 4).ToString("yyyy-MM-dd"),
- kssj = "15:20",
- jssj = "16:55"
- });
- table.Add(new Event {
- nr = "概率论与数理统计",
- dd = "一教 104",
- nq = start.AddDays(i * 7 + 1).ToString("yyyy-MM-dd"),
- kssj = "13:30",
- jssj = "15:05"
- });
- }
+ Debug.WriteLine("[getTimetable] Returning remote");
return table;
}
-
- //fetch from remote
- var _remoteTimetable = await Remote.getRemoteTimetable();
- Debug.WriteLine("[getTimetable] Returning remote");
- return _remoteTimetable;
}
public static async Task getSemester(bool forceRemote = false, bool getNextSemester = false) {
@@ -255,6 +319,9 @@ public static async Task getSemester(bool forceRemote = false, bool ge
return __semesters.nextSemester;
}
Debug.WriteLine("[getCalendar] Returning cache");
+ if (getNextSemester) {
+ return semesters.nextSemester;
+ }
return __semesters.currentSemester;
}
}
@@ -276,6 +343,9 @@ public static async Task getSemester(bool forceRemote = false, bool ge
writeCache(SEMESTERS_FILENAME, JSON.stringify(semesters));
Debug.WriteLine("[getCalendar] Returning remote");
+ if (getNextSemester) {
+ return semesters.nextSemester;
+ }
return semesters.currentSemester;
}
@@ -331,16 +401,11 @@ static public async Task> getAllDeadlines(bool forceRemote = fals
foreach (var course in await getCourses(forceRemote)) {
Debug.WriteLine("[getAllDeadlines] Remote " + course.name);
var id = course.id;
- try
- {
+ try {
List __deadlines;
- if (course.isNew)
- __deadlines = await Remote.getRemoteHomeworkListNew(id);
- else
- __deadlines = await Remote.getRemoteHomeworkList(id);
+ __deadlines = await Remote.getRemoteHomeworkList(id);
_deadlines = _deadlines.Concat(__deadlines).ToList();
- }
- catch { }
+ } catch { }
}
diff --git a/Class Library/Record.cs b/Class Library/Record.cs
index 556571d..8e90abf 100644
--- a/Class Library/Record.cs
+++ b/Class Library/Record.cs
@@ -23,8 +23,6 @@ public class Password {
public class Course {
public string id;
public string name;
- public bool isNew; //uses (`learn.cic` or `learn`?) .tsinghua.edu.cn
- public string semester;
override public string ToString() {
return "#" + id + ": " + name;
@@ -36,7 +34,6 @@ public class Deadline {
public string name;
public string ddl;
public string course;
- public string detail;
public bool hasBeenFinished;
public bool hasBeenToasted() {
string toasted = "";
@@ -77,7 +74,7 @@ public void mark_as_toasted() {
}
public double daysFromNow() {
- return (DateTime.Parse(ddl + " 23:59") - DateTime.Now).TotalDays;
+ return (DateTime.Parse(ddl) - DateTime.Now).TotalDays;
}
public string timeLeft() {
@@ -85,11 +82,11 @@ public string timeLeft() {
}
public bool isPast() {
- return DateTime.Parse(ddl + " 23:59") < DateTime.Now;
+ return DateTime.Parse(ddl) < DateTime.Now;
}
public string timeLeftChinese() {
- TimeSpan timeDelta = DateTime.Parse(ddl + " 23:59") - DateTime.Now;
+ TimeSpan timeDelta = DateTime.Parse(ddl) - DateTime.Now;
var daysLeft = timeDelta.TotalDays;
string timeLeft = "";
@@ -108,13 +105,13 @@ public string timeLeftChinese() {
timeLeft = "即将到期!";
} else if (daysLeft > -1) {
var d = (-timeDelta.Hours);
- timeLeft = "已经过去 " + d.ToString() + " 小时";
+ timeLeft = "已过期 " + d.ToString() + " 小时";
} else if (daysLeft > -10) {
var d = (-timeDelta.Days);
- timeLeft = "已经过去 " + d.ToString() + " 天";
+ timeLeft = "已过期 " + d.ToString() + " 天";
} else {
var d = Math.Round(timeDelta.TotalDays / -7);
- timeLeft = "已经过去 " + d.ToString() + " 周";
+ timeLeft = "已过期 " + d.ToString() + " 周";
}
@@ -148,71 +145,92 @@ public string getWeekName() {
// the following classes are generated from JSON by Visual Studio,
// for JSON parser only
- public class CourseAssignmentsRootobject {
- public Resultlist[] resultList { get; set; }
- }
-
- public class Resultlist {
- public Coursehomeworkrecord courseHomeworkRecord { get; set; }
- public Coursehomeworkinfo courseHomeworkInfo { get; set; }
- }
-
- public class Coursehomeworkrecord {
- public string status { get; set; }
- }
- public class Coursehomeworkinfo {
- public int homewkId { get; set; }
- public long endDate { get; set; }
- public string title { get; set; }
- public string detail { get; set; }
- public string courseId { get; set; }
+ public class RemoteSemester {
+ public string xnxq { get; set; }
+ public string xnxqmc { get; set; }
+ public string kssj { get; set; }
+ public string jssj { get; set; }
+ public string id { get; set; }
}
-
public class SemestersRootObject {
- public Currentteachingweek currentTeachingWeek { get; set; }
- public Semester currentSemester { get; set; }
- public string currentDate { get; set; }
- public Semester nextSemester { get; set; }
- }
-
- public class Currentteachingweek {
- public int teachingWeekId { get; set; }
- public string weekName { get; set; }
- public string beginDate { get; set; }
- public string endDate { get; set; }
- public string semesterId { get; set; }
+ public RemoteSemester result { get; set; }
+ public string message { get; set; }
+ public RemoteSemester[] resultList { get; set; }
}
-
public class Timetable : List {
}
public class Event {
public string dd { get; set; }
- public string fl { get; set; }
- public int grrlID { get; set; }
public string jssj { get; set; }
public string kssj { get; set; }
public string nq { get; set; }
public string nr { get; set; }
- public string sfSjtz { get; set; }
- public string skjc { get; set; }
- public string sm { get; set; }
+
+ }
+
+ public class RemoteCourseRootObject {
+ public string currentUser { get; set; }
+ public string message { get; set; }
+ public RemoteCourse[] resultList { get; set; }
}
- public class Lectures {
- public Lecture[] Property1 { get; set; }
+ public class RemoteCourse {
+
+ public string wlkcid { get; set; }
+ public string kcm { get; set; }
+ public string kch { get; set; }
+ public int kxh { get; set; }
+
+ public string jsm { get; set; }
+
+ }
+
+ public class HomeworkDetailRootobject {
+ public string result { get; set; }
+ public HomeworkDetailObject objects { get; set; }
+ }
+
+ public class HomeworkDetailObject {
+ public string iTotalDisplayRecords { get; set; }
+ public HomeworkDetailAadata[] aaData { get; set; }
+ }
+
+ public class HomeworkDetailAadata {
+ public long jzsj { get; set; }
+ public string jzsjStr { get; set; }
+
+ public string bt { get; set; }
+
+ public string wlkcid { get; set; }
+
+ public string zyid { get; set; }
+
}
- public class Lecture {
- public string description { get; set; }
- public string summary { get; set; }
- public string location { get; set; }
- public string dtstart { get; set; }
- public string dtend { get; set; }
- public long uid { get; set; }
+ public class CourseDetail {
+ public string id { get; set; }
+ public string wlkcid { get; set; }
+
+ public string xnxq { get; set; }
+ public string kch { get; set; }
+ public string kxh { get; set; }
+
+ public string skzc { get; set; }
+ public int skxq { get; set; }
+ public int skjc { get; set; }
+ public int skxs { get; set; }
+
+ public string zcms { get; set; }
+
+ public string skdd { get; set; }
+
+ public string jxlh { get; set; }
+ public string jash { get; set; }
+
}
}
\ No newline at end of file
diff --git a/Class Library/Remote.cs b/Class Library/Remote.cs
index 4f41276..cf12d9c 100644
--- a/Class Library/Remote.cs
+++ b/Class Library/Remote.cs
@@ -1,5 +1,4 @@
-using HtmlAgilityPack;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -20,173 +19,56 @@ public static class Remote {
// exposes access to remote objects
- public static async Task getRemoteTimetable() {
+ public static async Task> getRemoteCourseDetail(string courseId) {
Debug.WriteLine("[getRemoteTimetable] start");
await login();
- var ticket = await POST(
- "http://learn.cic.tsinghua.edu.cn:80/gnt",
- "appId=ALL_ZHJW");
+ var page = await GET($"http://learn2018.tsinghua.edu.cn/b/kc/v_wlkc_xk_sjddb/detail?id={courseId}");
+ var parsed = JSON.parse(page);
- //await 十1s(); //cross-domain tickets needs some time to take effect
-
- bool outside_campus_network = false;
- try {
- var zhjw = await GET(
- $"http://zhjw.cic.tsinghua.edu.cn/j_acegi_login.do?url=/&ticket={ticket}");
- } catch (System.Runtime.InteropServices.COMException e) {
- if (e.Message.IndexOf("403") == -1)
- throw e;
- Debug.WriteLine("[getRemoteTimetable] outside campus network");
- //throw new NeedCampusNetworkException();
-
- outside_campus_network = true;
- }
-
-
-
- if (outside_campus_network) {
- //connect via sslvpn
- await logoutSSLVPN();
- await loginSSLVPN();
-
- await login();
-
- ticket = await POST(
- "http://learn.cic.tsinghua.edu.cn:80/gnt",
- "appId=ALL_ZHJW");
-
- await 十1s();
-
- var ticketPage = await GET(
- $"https://sslvpn.tsinghua.edu.cn/,DanaInfo=zhjw.cic.tsinghua.edu.cn+j_acegi_login.do?url=/&ticket={ticket}");
-
- Timetable timetable = new Timetable();
-
- for (int i = -6; i <= 4; i += 2) {
- var roles = new List { "bks", "yjs" };
- foreach (var role in roles)
- {
- try
- {
- string page;
- try
- {
- page = await get_calendar_sslvpn_page(
- DateTime.Now.AddMonths(i).AddDays(1).ToString("yyyyMMdd"),
- DateTime.Now.AddMonths(i + 2).ToString("yyyyMMdd"),
- role
- );
- }
- catch (Exception)
- {
- page = await get_calendar_sslvpn_page(
- DateTime.Now.AddMonths(i).AddDays(1).ToString("yyyyMMdd"),
- DateTime.Now.AddMonths(i + 2).ToString("yyyyMMdd"),
- role
- );
- }
- var set_to_be_appended = parseTimetablePage(page);
- foreach (var _____ in set_to_be_appended)
- {
- timetable.Add(_____);
- }
- }
- catch (Exception) { }
- }
- }
-
- logoutSSLVPN();
-
- Debug.WriteLine("[getRemoteTimetable] returning sslvpn");
- return timetable;
- } else { //TODO: duplicate code
-
- //connect directly
-
- Timetable timetable = new Timetable();
- for (int i = -6; i <= 4; i += 2) {
- var roles = new List { "bks", "yjs" };
- foreach (var role in roles)
- {
- try
- {
- string page;
- try
- {
- page = await get_calendar_page(
- DateTime.Now.AddMonths(i).AddDays(1).ToString("yyyyMMdd"),
- DateTime.Now.AddMonths(i + 2).ToString("yyyyMMdd"),
- role
- );
- }
- catch (Exception)
- {
- page = await get_calendar_page(
- DateTime.Now.AddMonths(i).AddDays(1).ToString("yyyyMMdd"),
- DateTime.Now.AddMonths(i + 2).ToString("yyyyMMdd"),
- role
- );
- }
- var set_to_be_appended = parseTimetablePage(page);
- foreach (var _____ in set_to_be_appended)
- {
- timetable.Add(_____);
- }
- }
- catch (Exception) { }
- }
- }
-
- Debug.WriteLine("[getRemoteTimetable] returning direct");
- return timetable;
- }
- }
- static async Task get_calendar_page(string starting_date, string ending_date, string role) {
- Debug.WriteLine($"[get_calendar_page] {role}, {starting_date}-{ending_date}");
- var stamp = (long)UnixTime().TotalMilliseconds;
- return await GET(
- $"http://zhjw.cic.tsinghua.edu.cn/jxmh.do?m={role}_jxrl_all&p_start_date={starting_date}&p_end_date={ending_date}&jsoncallback=_&_={stamp}");
- }
- static async Task get_calendar_sslvpn_page(string starting_date, string ending_date, string role) {
- Debug.WriteLine($"[get_calendar_sslvpn_page] {role}, {starting_date}-{ending_date}");
- var stamp = (long)UnixTime().TotalMilliseconds;
- return await GET(
- $"https://sslvpn.tsinghua.edu.cn/,DanaInfo=zhjw.cic.tsinghua.edu.cn,CT=js+jxmh.do?m={role}_jxrl_all&p_start_date={starting_date}&p_end_date={ending_date}&jsoncallback=_&_={stamp}");
+ Debug.WriteLine("[getRemoteTimetable] returning direct");
+ return parsed.ToList();
}
+
+
public static async Task> getRemoteHomeworkList(string courseId) {
await login();
- return parseHomeworkListPage(await getHomeworkListPage(courseId));
+ var result = new List { };
+ result = result.Concat(await parseHomeworkListPage(await getHomeworkListPage(courseId, "Wj"))).ToList();
+ return result;
}
- public static async Task> getRemoteHomeworkListNew(string courseId) {
- await login();
- return await parseHomeworkListPageNew(await getHomeworkListPageNew(courseId));
- }
- public static async Task> getRemoteCourseList() {
+ public static async Task> getRemoteCourseList(string semester) {
await login();
- return parseCourseList(await getCourseListPage());
+ return parseCourseList(await getCourseListPage(semester));
}
public static async Task getHostedSemesters() {
return JSON.parse(await GET(hostedCalendarUrl));
}
- public static async Task> getHostedLectures() {
- var raw = await GET(hostedLectureUrl);
- var parsed = JSON.parse>(raw);
- return parsed;
- }
-
public static async Task getRemoteSemesters() {
await login();
- var _remoteCalendar = parseSemestersPage(await getCalendarPage());
+ await 十1s();
+ var _remoteCalendar = parseSemestersPage(await getSemesterPage());
return new Semesters {
- currentSemester = _remoteCalendar.currentSemester,
- nextSemester = _remoteCalendar.nextSemester
+ currentSemester = new Semester {
+ id = _remoteCalendar.result.id,
+ semesterEname = Regex.Replace(Regex.Replace(Regex.Replace(_remoteCalendar.result.id, "-1$", "-Autumn"), "-2$", "-Spring"), "-3$", "-Summer"),
+ semesterName = _remoteCalendar.result.xnxqmc,
+ startDate = _remoteCalendar.result.kssj,
+ endDate = _remoteCalendar.result.jssj
+ },
+ nextSemester = new Semester {
+ id = _remoteCalendar.resultList[0].id,
+ semesterEname = Regex.Replace(Regex.Replace(Regex.Replace(_remoteCalendar.resultList[0].id, "-1$", "-Autumn"), "-2$", "-Spring"), "-3$", "-Summer"),
+ semesterName = _remoteCalendar.resultList[0].xnxqmc,
+ startDate = _remoteCalendar.resultList[0].kssj,
+ endDate = _remoteCalendar.resultList[0].jssj
+ },
};
}
@@ -240,36 +122,25 @@ private static async Task login(bool useLocalSettings = true, string userna
try {
string loginResponse;
- //login to learn.tsinghua.edu.cn
+ //login to learn2018.tsinghua.edu.cn
loginResponse = await POST(
loginUri,
- $"leixin1=student&userid={username}&userpass={password}");
+ $"i_user={username}&i_pass={password}&atOnce=true");
//check if successful
- var alertInfoGroup = Regex.Match(loginResponse, @"window.alert\(""(.+)""\);").Groups;
- if (alertInfoGroup.Count > 1) {
- throw new LoginException(alertInfoGroup[1].Value.Replace("\\r\\n", "\n"));
- }
- if (loginResponse.IndexOf(@"window.location = ""loginteacher_action.jsp"";") == -1) {
- throw new ParsePageException("login_redirect");
- }
+ var ticketGroup = Regex.Match(loginResponse, @"window.location.replace\(""(.+)""\);").Groups;
- //get iframe src
- HtmlDocument htmlDoc = new HtmlDocument();
- htmlDoc.LoadHtml(await GET(courseListUrl));
+ var redirectUrl = ticketGroup[1].Value;
- string iframeSrc;
- try {
- iframeSrc = htmlDoc.DocumentNode.Descendants("iframe")/*MAGIC*/.First().Attributes["src"].Value;
- } catch (Exception) {
- throw new ParsePageException("find_cic_iframe");
+ var redirectStatus = Regex.Match(redirectUrl, @"status=([^&]+)(&|$)").Groups[1].Value;
+ var redirectTicket = Regex.Match(redirectUrl, @"ticket=([^&]+)(&|$)").Groups[1].Value;
+ if (redirectStatus != "SUCCESS") {
+ throw new LoginException("登录失败:" + redirectStatus);
}
+ await GET($"http://learn2018.tsinghua.edu.cn/b/j_spring_security_thauth_roaming_entry?ticket={redirectTicket}");
- //login to learn.cic.tsinghua.edu.cn
- await 十1s();
- await GET(iframeSrc);
} catch (Exception e) {
occupied = false;
Debug.WriteLine("[login] unsuccessful");
@@ -286,73 +157,11 @@ private static async Task login(bool useLocalSettings = true, string userna
return 0;
}
- private static async Task logoutSSLVPN() {
- await GET(logoutSslvpnUrl);
- Debug.WriteLine("[logoutSSLVPN] finish");
- }
-
- private static async Task loginSSLVPN() {
-
- Debug.WriteLine("[loginSSLVPN] start");
-
- //retrieve username and password
- if (DataAccess.credentialAbsent()) {
- throw new LoginException("没有指定用户名和密码");
- }
- var username = DataAccess.getLocalSettings()["username"].ToString();
-
- var vault = new Windows.Security.Credentials.PasswordVault();
- var password = vault.Retrieve("Tsinghua_Learn_Website", username).Password;
-
-
- //login to sslvpn.tsinghua.edu.cn
- var loginResponse = await POST(
- loginSslvpnUri,
- $"tz_offset=480&username={username/*should be numeral ID*/}&password={password}&realm=ldap&btnSubmit=登录");
-
-
- //another sslvpn session exist?
- if (loginResponse.IndexOf("btnContinue") != -1) {
- Debug.WriteLine("[loginSSLVPN] another sslvpn session exist");
-
- HtmlDocument htmlDoc = new HtmlDocument();
- htmlDoc.LoadHtml(loginResponse);
- string formDataStr = htmlDoc.GetElementbyId("DSIDFormDataStr").Attributes["value"].Value;
-
- loginResponse = await POST(
- loginSslvpnUri,
- $"btnContinue=继续会话&FormDataStr={Uri.EscapeDataString(formDataStr)}");
- }
-
- //get xauth token
- var xsauthGroups = Regex.Match(loginResponse, @"name=""xsauth"" value=""([^""]+)""").Groups;
- if (xsauthGroups.Count < 2) {
- throw new ParsePageException("find_xsauth_from_sslvpn");
- }
- var xsauth = xsauthGroups[1];
-
- //second step, invoking xsauth token
- var timestamp = UnixTime().TotalSeconds;
-
- loginResponse = await POST(
- loginSslvpnCheckUri,
- $"xsauth={xsauth}&tz_offset=480&clienttime={timestamp}&url=&activex_enabled=0&java_enabled=0&power_user=0&grab=1&browserproxy=&browsertype=&browserproxysettings=&check=yes");
-
-
-
- Debug.WriteLine("[loginSSLVPN] finish");
- return 0;
- }
private static DateTime lastLogin = DateTime.MinValue;
private static string lastLoginUsername = "";
private static int LOGIN_TIMEOUT_MINUTES = 5;
-
- private static string loginSslvpnUri = "https://sslvpn.tsinghua.edu.cn/dana-na/auth/url_default/login.cgi";
- private static string logoutSslvpnUrl = "https://sslvpn.tsinghua.edu.cn/dana-na/auth/logout.cgi";
- private static string loginSslvpnCheckUri = "https://sslvpn.tsinghua.edu.cn/dana/home/starter0.cgi";
- private static string loginSslvpnCheckUriCheck = "https://sslvpn.tsinghua.edu.cn/dana/home/starter0.cgi?check=yes";
- private static string loginUri = "https://learn.tsinghua.edu.cn/MultiLanguage/lesson/teacher/loginteacher.jsp";
+ private static string loginUri = "https://id.tsinghua.edu.cn/do/off/ui/auth/login/post/bb5df85216504820be7bba2b0ae1535b/0?/login.do";
@@ -361,26 +170,21 @@ private static async Task loginSSLVPN() {
// remote object URLs and wrappers
- private static string courseListUrl = "http://learn.tsinghua.edu.cn/MultiLanguage/lesson/student/MyCourse.jsp?language=cn";
+
private static string hostedCalendarUrl = "https://static.nullspace.cn/thuCalendar.json";
private static string hostedLectureUrl = "http://vultr.nullspace.cn:8000/test.json";
public static string helpUrl = "https://static.nullspace.cn/thuUwpHelp.html";
- private static async Task getHomeworkListPage(string courseId) {
- return await GET($"http://learn.tsinghua.edu.cn/MultiLanguage/lesson/student/hom_wk_brw.jsp?course_id={courseId}");
- }
-
- private static async Task getHomeworkListPageNew(string courseId) {
- var timestamp = UnixTime().TotalMilliseconds;
- string url = $"http://learn.cic.tsinghua.edu.cn/b/myCourse/homework/list4Student/{courseId}/0?_={timestamp}";
- return await GET(url);
+ private static async Task getHomeworkListPage(string courseId, string category) {
+ var payload = $"aoData=[{{\"name\":\"wlkcid\",\"value\":\"{courseId}\"}},{{\"name\":\"iDisplayStart\",\"value\":0}},{{\"name\":\"iDisplayLength\",\"value\":-1}}]";
+ return await POST($"http://learn2018.tsinghua.edu.cn/b/wlxt/kczy/zy/student/zyList" + category, payload);
}
- private static async Task getCourseListPage() {
- return await GET(courseListUrl);
+ private static async Task getCourseListPage(string semester) {
+ return await GET("http://learn2018.tsinghua.edu.cn/b/wlxt/kc/v_wlkc_xs_xkb_kcb_extend/student/loadCourseBySemesterId/" + semester);
}
- private static async Task getCalendarPage() {
- return await GET("http://learn.cic.tsinghua.edu.cn/b/myCourse/courseList/getCurrentTeachingWeek");
+ private static async Task getSemesterPage() {
+ return await GET("http://learn2018.tsinghua.edu.cn/b/kc/zhjw_v_code_xnxq/getCurrentAndNextSemester");
}
@@ -392,70 +196,19 @@ private static async Task getCalendarPage() {
// parse HTML or JSON, and return corresponding Object
- private static List parseHomeworkListPage(string page) {
- try {
- HtmlDocument htmlDoc = new HtmlDocument();
- htmlDoc.LoadHtml(page);
-
- string _name, _due, _course;
-
- _course = htmlDoc.DocumentNode.Descendants("td")/*MAGIC*/.First().InnerText;
- _course = _course.Trim();
- _course = _course.Substring(6/*MAGIC*/);
- _course = WebUtility.HtmlDecode(_course);
-
- HtmlNode[] nodes = htmlDoc.DocumentNode.Descendants("tr")/*MAGIC*/.ToArray();
-
-
- List deadlines = new List();
- Regex re = new Regex("&[^;]+;");
- for (int i = 4/*MAGIC*/; i < nodes.Length - 1/*MAGIC*/; i++) {
- HtmlNode node = nodes[i];
-
- var tds = node.Descendants("td");
-
- var _isFinished = (tds.ElementAt(3/*MAGIC*/).InnerText.Trim() == "已经提交");
-
- _due = tds.ElementAt(2/*MAGIC*/).InnerText;
-
- var link_to_detail = node.Descendants("a")/*MAGIC*/.First();
- _name = link_to_detail.InnerText;
- _name = WebUtility.HtmlDecode(_name);
-
- var _href = link_to_detail.Attributes["href"].Value;
- var _id = Regex.Match(_href, @"[^_]id=(\d+)").Groups[1].Value;
-
- deadlines.Add(new Deadline {
- name = re.Replace(_name, " "),
- ddl = _due,
- course = re.Replace(_course, " "),
- hasBeenFinished = _isFinished,
- id = "@" + _id
- });
- }
- return deadlines;
- } catch (Exception) {
- throw new ParsePageException("AssignmentList");
- }
-
- }
-
- private static async Task> parseHomeworkListPageNew(string page) {
-
- List deadlines = new List();
-
+ private static async Task> parseHomeworkListPage(string page) {
+ var deadlines = new List { };
string _course = "";
- var root = JSON.parse(page);
Regex re = new Regex("&[^;]+;");
- foreach (var item in root.resultList) {
- var _isFinished = (item.courseHomeworkRecord.status != "0" /*MAGIC*/);
- var _dueTimeStamp = item.courseHomeworkInfo.endDate;
- var _dueDate = (new DateTime(1970, 1, 1, 0, 0, 0, 0)).ToLocalTime().AddMilliseconds(_dueTimeStamp).Date;
- string _due = $"{_dueDate.Year}-{_dueDate.Month}-{_dueDate.Day}";
+ var parsed = JSON.parse(page.Replace("\"object\":", "\"objects\":"));
+ foreach (var a in parsed.objects.aaData){
+ var _isFinished = false;
+
+ string _due = a.jzsjStr;
- string _name = item.courseHomeworkInfo.title;
- string _courseId = item.courseHomeworkInfo.courseId;
+ string _name = a.bt;
+ string _courseId = a.wlkcid;
if (_course == "")
_course = _courseId;
@@ -474,52 +227,21 @@ private static async Task> parseHomeworkListPageNew(string page)
ddl = _due,
course = re.Replace(_course, " "),
hasBeenFinished = _isFinished,
- id = "_" + item.courseHomeworkInfo.homewkId
+ id = a.wlkcid + "_" + a.zyid
});
}
return deadlines;
}
private static List parseCourseList(string page) {
- try {
- List courses = new List();
-
- HtmlDocument htmlDoc = new HtmlDocument();
- htmlDoc.LoadHtml(page);
- var tables = htmlDoc.DocumentNode.Descendants("table");
- var links = tables/*MAGIC*/.Take(3).Last()/*MAGIC*/.Descendants("a")/*MAGIC*/.ToArray();
-
- foreach (var link in links) {
- string _name = link.InnerText.Trim();
- string _url = link.Attributes["href"].Value;
- if (_url.Contains("teacher"))
- {
- continue;
- }
- var match = Regex.Match(_name, "(.+?)\\((\\d+)\\)\\((.+?)\\)");
- string _semester = match.Groups[3].Value;
- _name = match.Groups[1].Value;
- bool _isNew = false;
- string _id = "";
-
- if (_url.StartsWith("http://learn.cic.tsinghua.edu.cn/")) {
- _isNew = true;
- _id = Regex.Match(_url, "/([-\\d]+)").Groups[1].Value;
- } else {
- _isNew = false;
- _id = Regex.Match(_url, "course_id=(\\d+)").Groups[1].Value;
- }
- courses.Add(new Course {
- name = _name,
- isNew = _isNew,
- id = _id,
- semester = _semester
- });
- }
- return courses;
- } catch (Exception) {
- throw new ParsePageException("CourseList");
+ var result = new List { };
+ foreach (var c in JSON.parse(page).resultList) {
+ result.Add(new Course {
+ id = c.wlkcid,
+ name = c.kcm,
+ });
}
+ return result;
}
private static SemestersRootObject parseSemestersPage(string page) {
@@ -596,4 +318,4 @@ public static string stringify(object jsonObject) {
}
}
}
-}
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index ae52c1c..99ce854 100644
--- a/README.md
+++ b/README.md
@@ -9,8 +9,8 @@
大二时的练手之作,代码相当杂乱(捂脸)。也就 Class Library 工程里的 Remote 类还算有点复用的价值:
* C# 版本的清华大学网络学堂爬虫
- * 支持 2001 版(learn)、2015 版(learn.cic)
- * 基于 [HtmlAgilityPack](https://www.nuget.org/packages/HtmlAgilityPack/)
+ * ~~支持 2001 版(learn)、2015 版(learn.cic),基于 [HtmlAgilityPack](https://www.nuget.org/packages/HtmlAgilityPack/)~~
+ * 支持 2018 版(learn2018)
## 友情链接
基于本项目的其他项目
diff --git a/Release Notes/version-history.txt b/Release Notes/version-history.txt
index 2492772..3075ac8 100644
--- a/Release Notes/version-history.txt
+++ b/Release Notes/version-history.txt
@@ -1,4 +1,7 @@
-版本 1.2.15
+版本 1.3.0
+- [新增] 升级到网络学堂2018版
+
+版本 1.2.15
- [修复] 2015版网络学堂部分课程作业导致刷新失败
版本 1.2.14
diff --git a/Tsinghua UWP/MainPage.xaml b/Tsinghua UWP/MainPage.xaml
index 200d866..f7dfd85 100644
--- a/Tsinghua UWP/MainPage.xaml
+++ b/Tsinghua UWP/MainPage.xaml
@@ -18,10 +18,6 @@
-
-
-
-
diff --git a/Tsinghua UWP/MainPage.xaml.cs b/Tsinghua UWP/MainPage.xaml.cs
index 239dae4..5a9ad67 100644
--- a/Tsinghua UWP/MainPage.xaml.cs
+++ b/Tsinghua UWP/MainPage.xaml.cs
@@ -34,13 +34,8 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) {
}
private async void update_with_credential() {
-
updateDeadlinesAsyc();
- updateTimetableAsync();
- Appointment.updateCalendar();
- try {
- await Appointment.updateLectures();
- } catch { }
+ // updateTimetableAsync(); // fix: 重复导入课程表
}
private async void update_without_credential() {
@@ -48,10 +43,6 @@ private async void update_without_credential() {
await Notification.update(calendarOnly: true);
await Appointment.updateCalendar();
} catch { }
- try {
- await Appointment.updateLectures();
- } catch { }
-
}
private async Task changeAccountAsync() {
@@ -151,6 +142,7 @@ private void launchHelp() {
}
private void btnRefreshTimetable_Click(object sender, RoutedEventArgs e) {
+ Appointment.updateCalendar();
updateTimetableAsync();
}
diff --git a/Tsinghua UWP/Package.StoreAssociation.xml b/Tsinghua UWP/Package.StoreAssociation.xml
index 6ea061e..c89fc62 100644
--- a/Tsinghua UWP/Package.StoreAssociation.xml
+++ b/Tsinghua UWP/Package.StoreAssociation.xml
@@ -2,6 +2,7 @@
CN=03155EEE-D512-488E-9665-514F20C1D599
Zhaoyang Li
+ MSA
http://www.w3.org/2001/04/xmlenc#sha256
@@ -364,5 +365,21 @@
-
+
+
+ 0.0.0.0
+ X64
+ 1.2.15.0
+
+
+ 0.0.0.0
+ X86
+ 1.2.15.0
+
+
+ 0.0.0.0
+ Arm
+ 1.2.15.0
+
+
\ No newline at end of file
diff --git a/Tsinghua UWP/Package.appxmanifest b/Tsinghua UWP/Package.appxmanifest
index 51a0884..fa791d3 100644
--- a/Tsinghua UWP/Package.appxmanifest
+++ b/Tsinghua UWP/Package.appxmanifest
@@ -1,6 +1,6 @@
-
+
清华磁贴
diff --git a/Tsinghua UWP/Tsinghua UWP.csproj b/Tsinghua UWP/Tsinghua UWP.csproj
index c371d9b..57f69eb 100644
--- a/Tsinghua UWP/Tsinghua UWP.csproj
+++ b/Tsinghua UWP/Tsinghua UWP.csproj
@@ -20,7 +20,7 @@
False
Never
x86|x64|arm
- D4E46E36BD31AA0079F45F415EBDB91D6EFCD60A
+ 29BAD16FD86D09168BA0CCC02F2049F938768959
True
win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot
False