private static void SetGrades(string HTMLdom, User user) { if (user.Subjects.Count > 0) { CQ dom = HTMLdom; CQ HTMLtable = dom[".dettable tbody"].RenderSelection(); List<string> lines = new List<string>(); int i = 0; while (true) { try { lines.Add(HTMLtable.Select("tr")[i].InnerHTML); i++; } catch { break; } } string currentSubj = ""; foreach (string line in lines) { CQ CQline = line; string strmark = CQline["td:nth-child(2)"].Text().Replace(" ", ""); double dblmark; string type = WebUtility.HtmlDecode(CQline[".dettyp"].Text().Replace(" ", "")); if (type == "C") type = "10"; int weight = int.Parse(type, CultureInfo.InvariantCulture); string[] strdate = (CQline[".detdatum"].Text().Replace(" ", "")).Split('.'); DateTime date = new DateTime((int.Parse(strdate[2], CultureInfo.InvariantCulture) + 2000), int.Parse(strdate[1], CultureInfo.InvariantCulture), int.Parse(strdate[0], CultureInfo.InvariantCulture)); string label = WebUtility.HtmlDecode(CQline[".detcaption"].Text()); string detail = WebUtility.HtmlDecode(CQline[".detpozn2"].Text().Replace("(", "").Replace(")", "")); if (strmark.ToUpper(CultureInfo.InvariantCulture).Contains("N")) { dblmark = 0.0; } else if (strmark.Contains("-")) { dblmark = double.Parse((strmark.Replace("-", ".5")), CultureInfo.InvariantCulture); } else { dblmark = double.Parse(strmark.Replace(" ", ""), CultureInfo.InvariantCulture); } if (!string.IsNullOrEmpty((CQline[".detpredm"].Text()))) { currentSubj = CQline[".detpredm"].Text(); } var query = from q in user.Subjects where (q.Info.LongName == currentSubj) select q; Grade grade = new Grade { Time = date, Detail = detail, Name = label, Value = dblmark, Weight = weight }; if (query.Any()) { Subject parent = query.First(); parent.Grades.Add(grade); } } } }
/// <summary> /// loads data from a specific existing session /// </summary> /// <param name="sessionId">ASP.NET_SessionId of a logged connection</param> /// <returns>user loaded from website</returns> public User Load(string sessionId) { if (string.IsNullOrWhiteSpace(sessionId)) throw new ArgumentException("sessionId cannot be empty!"); if (isDisposed) throw new ObjectDisposedException("API"); User user = new User(); _client.CookieContainer.GetCookies(new Uri(GradesUrl)).Add(new Cookie("ASP.NET_SessionId", sessionId)); string welcome=_client.GETRequest(CombineUrl("uvod.aspx")); CQ welcomeHtml = welcome;//todo:reset back string nameLabel = Helper.Decode( Helper.RemoveStartingWhitespaces( Helper.RemoveEndingWhitespaces( Helper.RemoveLineBreaks(welcomeHtml[".logjmeno"][0].InnerText) ) ) ); #region name formating string name; if (nameLabel.Contains(','))//remove the class name { name = nameLabel.Split(',')[0]; } else name = nameLabel; if (name.Contains(' '))//switch name and surename to friendlier form (Smith John > John Smith) { user.Name = name.Split(' ')[1] + " " + name.Split(' ')[0]; } else user.Name = name; #endregion //scrapping sequence string scheduleUrl = CombineUrl(welcomeHtml["#panelmenu > div > div:nth-child(4) > div > ul > li:nth-child(1) > a"][0]["href"]); string gradesUrl = CombineUrl(welcomeHtml["#panelmenu > div > div:nth-child(6) > div > ul > li:nth-child(1) > a"][0]["href"]); #region shedule scrapping NameValueCollection scheduleData = Client.GetFieldsFromHtml(_client.DownloadString(scheduleUrl)); scheduleData.Set("hlavnimenuSI", "3i0"); scheduleData.Set("ctl00$cphmain$radiorozvrh", "stálý rozvrh"); scheduleData.Set("ctl00$cphmain$Flyrozvrh$checkucitel", "on"); scheduleData.Set("ctl00$cphmain$Flyrozvrh$checkskupina", "on"); scheduleData.Set("ctl00$cphmain$Flyrozvrh$Checkmistnost", "on"); string scheduleHtml = _client.POSTRequest(scheduleUrl, scheduleData);//this is weekly schedule HTML user.Subjects = ParseSubjects(scheduleHtml); #endregion #region subjects' counts string countsHtml = _client.GETRequest(CombineUrl("prehled.aspx?s=9")); SetSubjectsCount(countsHtml, user.Subjects); #endregion #region grades NameValueCollection gradesData = Client.GetFieldsFromHtml(_client.GETRequest(gradesUrl)); gradesData.Set("ctl00$cphmain$Checkdetail", "on"); gradesData.Set("ctl00$cphmain$Flyout2$Checktypy", "on"); gradesData.Set("ctl00$cphmain$Flyout2$Checkdatumy", "on"); gradesData.Set("ctl00$cphmain$Flyout2$Checkprumery", "on"); gradesData.Set("ctl00$cphmain$Flyout2$checkpoznamky", "on"); gradesData.Set("hlavnimenuSI", "2i0"); string gradesHtml = _client.POSTRequest(gradesUrl, gradesData); SetGrades(gradesHtml, user); #endregion #region absences //list for storing mondays of each week we know that contains absences List<DateTime> weeklyAbsences = new List<DateTime>(); /* idea of monthly checks: it's not necessary to check every week in semester, when most of them should be empty. We'll save the weeks, which weren't empty and look up the absences note: this is slower for ppl with a lots of absences, but it's their problem, right? */ #region mothly checks //do not touch, optimisation is probably impossible! very fragile! #region getting the right values for monthly checks NameValueCollection absenceData = Client.GetFieldsFromHtml(_client.GETRequest(CombineUrl("prehled.aspx?s=3"))); absenceData.Set("ctl00$cphmain$listdobaoml", "zadané období"); absenceData.Set("ctl00$cphmain$listjakoml", "seznam"); absenceData = Client.GetFieldsFromHtml( _client.POSTRequest(CombineUrl("prehled.aspx?s=3"), absenceData)); absenceData.Set("ctl00$cphmain$listabsencedo", "daný měsíc"); absenceData.Set("ctl00$cphmain$listdobaoml", "zadané období"); absenceData.Set("ctl00$cphmain$listjakoml", "seznam"); #endregion //go through every month in semester and find weeks with absences foreach (DateTime monthDate in _absenceMonths) { string unixTime = Helper.ToUnixtime(monthDate).ToString() + "000"; absenceData.Set("cphmain_listabsenceod_Raw", unixTime); CQ monthlyAbsenceHtml = _client.POSTRequest(CombineUrl("prehled.aspx?s=3"), absenceData); CQ rows = monthlyAbsenceHtml[".omlseztab > tbody> tr.omlsezbody"]; string table = monthlyAbsenceHtml.RenderSelection(); for (int r = 0; r < rows.Length; r++)//go through each row of table. table represents month's days { CQ cells = ((CQ)rows[r].InnerHTML)["td"];//row cells for (int i = 0; i < cells.Length; i++) { if (i == 0)//first cell with date, we know the date from "r" and "date" continue; else if (i == 1)//shortened day of week, e.g. "po", "út"... continue; string cell = cells[i].InnerText; if (string.IsNullOrWhiteSpace(cell)) continue;//no absence for this cell //now we know there's an absence DateTime mondayOfCheckedWeek = Helper.ToMonday(new DateTime(monthDate.Year, monthDate.Month, r + 1)); bool contains = weeklyAbsences.Contains(mondayOfCheckedWeek); if (!contains) weeklyAbsences.Add(mondayOfCheckedWeek);//we'll check this week later break; } } } #endregion #region weekly checks //look up every week we know that contains absences and save 'em NameValueCollection weeklyAbsenceData = Client.GetFieldsFromHtml(_client.GETRequest(CombineUrl("prehled.aspx?s=3"))); weeklyAbsenceData.Set("ctl00$cphmain$Flyoutoml$Checkomlpredmety", "on"); weeklyAbsenceData.Set("ctl00$cphmain$listdobaoml", "zadané období"); weeklyAbsenceData.Set("ctl00$cphmain$listjakoml", "tabulka"); weeklyAbsenceData = Client.GetFieldsFromHtml( _client.POSTRequest(CombineUrl("prehled.aspx?s=3"), weeklyAbsenceData)); weeklyAbsenceData.Set("ctl00$cphmain$listabsencedo", "daný týden"); weeklyAbsenceData.Set("ctl00$cphmain$Flyoutoml$Checkomlpredmety", "on"); weeklyAbsenceData.Set("ctl00$cphmain$listdobaoml", "zadané období"); weeklyAbsenceData.Set("ctl00$cphmain$listjakoml", "tabulka"); foreach (DateTime weekDate in weeklyAbsences) { string unix = Helper.ToUnixtime(weekDate).ToString() + "000"; weeklyAbsenceData.Set("cphmain_listabsenceod_Raw", unix); CQ weeklyAbsencesHtml = _client.POSTRequest(CombineUrl("prehled.aspx?s=3"), weeklyAbsenceData); //select even rows with subject's name inside CQ s_rows = weeklyAbsencesHtml["#trozvrh > table > tbody > tr:nth-child(even)"]; //select odd rows with images to find out the absence's type CQ i_rows = weeklyAbsencesHtml["#trozvrh > table > tbody > tr:nth-child(odd)"]; for (int row = 0; row < 5; row++) { for (int col = 0; col < 15; col++) { //the cell with possible name of subject IDomObject s_cell=Cq(s_rows[row + 1])["td"][col]; //name of subject for abs, long string subjName = s_cell.HasAttribute("title") ? s_cell["title"] : null; if (!string.IsNullOrWhiteSpace(subjName))//there's an absence { //the source of image IDomObject i_cell = Cq(i_rows[row + 1])["td"][col+1]; IDomObject img = Cq(i_cell)["img"][0]; string imgSrc = img["src"]; Absence.EType absType;//type of current absence if (imgSrc.Contains("wAbOk.gif")) absType = Absence.EType.Execused; else if (imgSrc.Contains("wAbsent.gif")) absType = Absence.EType.YetUnexecused; else if (imgSrc.Contains("wAbMiss.gif")) absType = Absence.EType.Unexecused; else if (imgSrc.Contains("wAbSoon.gif")) absType = Absence.EType.Early; else if (imgSrc.Contains("wAbLate.gif")) absType = Absence.EType.Late; else absType = Absence.EType.Uncountable; ShedulePosition pos = new ShedulePosition(row, col); Absence newAbsence = new Absence { Type = absType, Time = ShedulePosition.ToDateTime(pos, weekDate) }; var query = from q in user.Subjects where q.Info.LongName == subjName select q.Absences; if (query.Any()) { query.First().Add(newAbsence); } else Debug.WriteLine("no matching subject found for '" + subjName + "'"); } } } } weeklyAbsenceData.Set("cphmain_listabsenceod_Raw", ""); #endregion #endregion return user; }