mirror of
https://github.com/XFox111/GUTSchedule.git
synced 2026-04-22 06:58:01 +03:00
Cleanup and optimization of the parser (not finished)
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public class CabinetExportParameters : ExportParameters
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public class CabinetSubject
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Cabinet { get; set; }
|
||||
public string Order { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public string Opponent { get; set; }
|
||||
public bool ProfessorSchedule { get; set; }
|
||||
|
||||
public CabinetSubject(string name, string type, string cabinet, string opponent, int year, int month, int day, string schedule, bool profSchedule)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
Cabinet = cabinet;
|
||||
Opponent = opponent;
|
||||
ProfessorSchedule = profSchedule;
|
||||
|
||||
string[] time = schedule.Split('-');
|
||||
|
||||
StartTime = new DateTime(year, month, day, int.Parse(time[0].Split('.')[0]), int.Parse(time[0].Split('.')[1]), 0);
|
||||
EndTime = new DateTime(year, month, day, int.Parse(time[1].Split('.')[0]), int.Parse(time[1].Split('.')[1]), 0);
|
||||
switch (time[0])
|
||||
{
|
||||
case "09.00": Order = "1"; break;
|
||||
case "10.45": Order = "2"; break;
|
||||
case "13.00": Order = "3"; break;
|
||||
case "14.45": Order = "4"; break;
|
||||
case "16.30": Order = "5"; break;
|
||||
case "18.15": Order = "6"; break;
|
||||
case "20.00": Order = "7"; break;
|
||||
case "10.30": Order = "2"; break; //Расписание для пар по физ-ре
|
||||
case "12.00": Order = "3"; break;
|
||||
case "13.30": Order = "4"; break;
|
||||
case "15.00": Order = "5"; break;
|
||||
case "18.00": Order = "7"; break;
|
||||
default: Order = ""; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using GUTSchedule.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GUTSchedule
|
||||
{
|
||||
public static class Data
|
||||
{
|
||||
public static List<(string Id, string Name)> Faculties { get; set; }
|
||||
public static List<(string Id, string Name)> Groups { get; set; }
|
||||
public static int FirstWeekDay { get; set; }
|
||||
public static DateTime StartDate { get; set; } = DateTime.Today;
|
||||
public static DateTime EndDate { get; set; } = DateTime.Today.AddDays(7);
|
||||
|
||||
/// <summary>
|
||||
/// Export parameters
|
||||
/// </summary>
|
||||
public static DataSet DataSet { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public class DataSet
|
||||
{
|
||||
public string Calendar { get; set; }
|
||||
public string Faculty { get; set; }
|
||||
public int Course { get; set; }
|
||||
public string Group { get; set; }
|
||||
public int Reminder { get; set; }
|
||||
public bool AddGroupToTitle { get; set; }
|
||||
public HttpClient HttpClient { get; set; }
|
||||
public bool? IsProfessor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public class DefaultExportParameters : ExportParameters
|
||||
{
|
||||
public string FacultyId { get; set; }
|
||||
public string GroupId { get; set; }
|
||||
public string Course { get; set; }
|
||||
public bool Session { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public abstract class ExportParameters
|
||||
{
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public class Occupation
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Cabinet { get; set; }
|
||||
public string Order { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public string Opponent { get; set; }
|
||||
|
||||
public string Group { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GUTSchedule.Models
|
||||
{
|
||||
public class Subject
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Professor { get; set; }
|
||||
public string[] Cabinets { get; set; }
|
||||
public string Order { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public string Group { get; set; }
|
||||
|
||||
public static List<Subject> GetSubject(string name, string type, string professor, string place, int order, string[] weeks, int weekday, string group)
|
||||
{
|
||||
List<Subject> subjects = new List<Subject>();
|
||||
string[] cabinets = place.Replace("ауд.: ", "").Replace("; Б22", "").Split(';');
|
||||
string pair = order < 10 ? order.ToString() : $"Ф{order - 81}";
|
||||
|
||||
foreach (string week in weeks)
|
||||
subjects.Add(new Subject(name, type, professor, cabinets, pair, int.Parse(week), weekday, group));
|
||||
|
||||
return subjects;
|
||||
}
|
||||
|
||||
public Subject(string name, string type, string prof, string[] cabs, string order, int week, int weekday, string group)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
Professor = prof;
|
||||
Cabinets = cabs;
|
||||
Order = order;
|
||||
Group = group;
|
||||
|
||||
StartTime = Extensions.GetDateFromWeeks(week, weekday);
|
||||
string rawTime;
|
||||
switch (order)
|
||||
{
|
||||
case "1": rawTime = "9:00"; break;
|
||||
case "2": rawTime = "10:45"; break;
|
||||
case "3": rawTime = "13:00"; break;
|
||||
case "4": rawTime = "14:45"; break;
|
||||
case "5": rawTime = "16:30"; break;
|
||||
case "6": rawTime = "18:15"; break;
|
||||
case "7": rawTime = "20:00"; break;
|
||||
case "Ф1": rawTime = "9:00"; break; //Расписание для пар по физ-ре
|
||||
case "Ф2": rawTime = "10:30"; break;
|
||||
case "Ф3": rawTime = "12:00"; break;
|
||||
case "Ф4": rawTime = "13:30"; break;
|
||||
case "Ф5": rawTime = "15:00"; break;
|
||||
case "Ф6": rawTime = "16:30"; break;
|
||||
case "Ф7": rawTime = "18:00"; break;
|
||||
default: rawTime = "9:00"; break;
|
||||
}
|
||||
StartTime = StartTime.Add(TimeSpan.Parse(rawTime));
|
||||
EndTime = StartTime + TimeSpan.FromMinutes(order.Contains("Ф") ? 90 : 95);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,108 +11,119 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace GUTSchedule
|
||||
{
|
||||
public enum ScheduleType
|
||||
{
|
||||
Default = 1,
|
||||
Session = 2
|
||||
}
|
||||
|
||||
public static class Parser
|
||||
{
|
||||
public static async Task<List<Subject>> LoadSchedule()
|
||||
public static async Task VaildateAuthorization(string email, string password)
|
||||
{
|
||||
List<Subject> schedule = new List<Subject>();
|
||||
if (string.IsNullOrWhiteSpace(email))
|
||||
throw new ArgumentNullException(nameof(email));
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
throw new ArgumentNullException(nameof(password));
|
||||
|
||||
HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "group_el", "0" },
|
||||
{ "kurs", Data.DataSet.Course.ToString() },
|
||||
{ "type_z", "1" },
|
||||
{ "faculty", Data.DataSet.Faculty },
|
||||
{ "group", Data.DataSet.Group },
|
||||
{ "ok", "Показать" },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
await client.GetAsync("https://cabs.itut.ru/cabinet/");
|
||||
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/lib/autentificationok.php");
|
||||
request.SetContent(
|
||||
("users", email),
|
||||
("parole", password));
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseContent = await response.GetString();
|
||||
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(await response.Content.ReadAsStringAsync());
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpRequestException($"{response.StatusCode} ({response.ReasonPhrase}): {responseContent}");
|
||||
|
||||
string groupName = Data.Groups.First(i => i.Id == Data.DataSet.Group).Name;
|
||||
|
||||
IHtmlCollection<IElement> pairs = doc.QuerySelectorAll(".pair");
|
||||
foreach (IElement item in pairs)
|
||||
if (!responseContent.StartsWith("1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string name, type, professor, place;
|
||||
int order, weekday;
|
||||
string[] weeks;
|
||||
Dictionary<string, string> responseQuery = new Dictionary<string, string>();
|
||||
foreach (string i in responseContent.Split('&'))
|
||||
responseQuery.Add(i.Split('=')[0], i.Split('=')[1]);
|
||||
|
||||
name = item.QuerySelector(".subect strong")?.TextContent ?? "Неизвестный предмет (см. Расписание)";
|
||||
type = item.QuerySelector(".type").TextContent.Replace("(", "").Replace(")", "");
|
||||
professor = item.QuerySelector(".teacher")?.GetAttribute("title").Replace(";", "") ?? "";
|
||||
place = item.QuerySelector(".aud")?.TextContent ?? "СПбГУТ";
|
||||
order = int.Parse(item.GetAttribute("pair")) - 1;
|
||||
weeks = item.QuerySelector(".weeks").TextContent.Replace("(", "").Replace("н)", "").Replace(" ", "").Split(',');
|
||||
weekday = int.Parse(item.GetAttribute("weekday"));
|
||||
throw new System.Security.VerificationException(responseQuery["error"].Replace("|", "; "));
|
||||
}
|
||||
}
|
||||
|
||||
schedule.AddRange(Subject.GetSubject(name, type, professor, place, order, weeks, weekday, groupName));
|
||||
public static async Task<List<Occupation>> GetSchedule(ExportParameters exportParameters)
|
||||
{
|
||||
List<Occupation> schedule = new List<Occupation>();
|
||||
|
||||
if (exportParameters is CabinetExportParameters)
|
||||
{
|
||||
|
||||
}
|
||||
else if (exportParameters is DefaultExportParameters arg)
|
||||
{
|
||||
if (arg.Session)
|
||||
schedule.AddRange(await GetSessionSchedule());
|
||||
else
|
||||
{
|
||||
int offsetDay = int.Parse(await new HttpClient().GetStringAsync("https://xfox111.net/schedule_offset.txt"));
|
||||
schedule.AddRange(await GetRegularSchedule(offsetDay, arg.FacultyId, arg.Course, arg.GroupId));
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("Invaild argument instance", nameof(exportParameters));
|
||||
|
||||
// Merge duplicating entries
|
||||
schedule.OrderByDescending(i => i.StartTime);
|
||||
for (int k = 1; k < schedule.Count; k++)
|
||||
if (schedule[k - 1].StartTime == schedule[k].StartTime &&
|
||||
schedule[k - 1].Name == schedule[k].Name &&
|
||||
schedule[k - 1].Type == schedule[k].Type)
|
||||
{
|
||||
schedule[k - 1].Opponent += "\n" + schedule[k].Opponent;
|
||||
schedule[k - 1].Cabinet += "; " + schedule[k].Cabinet;
|
||||
schedule.RemoveAt(k--);
|
||||
}
|
||||
|
||||
return schedule.FindAll(i => i.StartTime.Date >= exportParameters.StartDate && i.StartTime.Date <= exportParameters.EndDate);
|
||||
}
|
||||
|
||||
public static async Task<List<(string id, string name)>> GetFaculties(ScheduleType scheduleType) =>
|
||||
await GetList(
|
||||
("choice", "1"),
|
||||
("kurs", "0"),
|
||||
("type_z", ((int)scheduleType).ToString()),
|
||||
("schet", GetCurrentSemester()));
|
||||
|
||||
public static async Task<List<(string id, string name)>> GetGroups(ScheduleType scheduleType, string facultyId, string course = "0") =>
|
||||
await GetList(
|
||||
("choice", "1"),
|
||||
("kurs", course),
|
||||
("type_z", ((int)scheduleType).ToString()),
|
||||
("schet", GetCurrentSemester()),
|
||||
("faculty", facultyId));
|
||||
|
||||
private static async Task<List<(string id, string name)>> GetList(params (string key, string value)[] parameters)
|
||||
{
|
||||
List<(string id, string name)> list = new List<(string, string)>();
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php");
|
||||
request.SetContent(parameters);
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
if (string.IsNullOrWhiteSpace(responseBody))
|
||||
return list;
|
||||
|
||||
foreach (string s in responseBody.Remove(responseBody.Length - 1).Split(';'))
|
||||
list.Add((s.Split(',')[0], s.Split(',')[1]));
|
||||
}
|
||||
|
||||
return schedule;
|
||||
return list;
|
||||
}
|
||||
|
||||
public static async Task LoadFaculties()
|
||||
{
|
||||
Data.Faculties = new List<(string, string)>();
|
||||
HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "choice", "1" },
|
||||
{ "kurs", "0" },
|
||||
{ "type_z", "1" },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
if (string.IsNullOrWhiteSpace(responseBody))
|
||||
throw new NullReferenceException("Расписание на текущий семестр еще не объявлено");
|
||||
|
||||
foreach (string s in responseBody.Split(';'))
|
||||
try { Data.Faculties.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static async Task LoadGroups(string facultyId, int course)
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "choice", "1" },
|
||||
{ "kurs", course.ToString() },
|
||||
{ "type_z", "1" },
|
||||
{ "faculty", facultyId },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
Data.Groups = new List<(string, string)>();
|
||||
foreach (string s in responseBody.Split(';'))
|
||||
try { Data.Groups.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
static string GetCurrentSemester()
|
||||
private static string GetCurrentSemester()
|
||||
{
|
||||
DateTime now = DateTime.Today;
|
||||
|
||||
@@ -122,7 +133,98 @@ namespace GUTSchedule
|
||||
return $"205.{now.Year - 2001}{now.Year - 2000}/2";
|
||||
}
|
||||
|
||||
public static async Task<List<CabinetSubject>> GetCabinetSchedule(HttpClient client, DateTime date, bool checkProfSchedule)
|
||||
private static DateTime[] GetDatesFromWeeks(int offsetDay, int weekday, string[] weeks)
|
||||
{
|
||||
List<DateTime> dates = new List<DateTime>();
|
||||
foreach(string rawWeek in weeks)
|
||||
{
|
||||
int week = int.Parse(rawWeek);
|
||||
DateTime date = new DateTime(DateTime.Today.Year, DateTime.Today.Month >= 8 ? 9 : 2, offsetDay);
|
||||
|
||||
date = date.AddDays(--week * 7);
|
||||
date = date.AddDays(--weekday);
|
||||
|
||||
dates.Add(date);
|
||||
}
|
||||
|
||||
return dates.ToArray();
|
||||
}
|
||||
|
||||
private static async Task<List<Occupation>> GetRegularSchedule(int offsetDay, string facultyId, string course, string groupId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(facultyId))
|
||||
throw new ArgumentNullException(nameof(facultyId));
|
||||
if (string.IsNullOrWhiteSpace(course))
|
||||
throw new ArgumentNullException(nameof(course));
|
||||
if (string.IsNullOrWhiteSpace(groupId))
|
||||
throw new ArgumentNullException(nameof(groupId));
|
||||
|
||||
List<Occupation> schedule = new List<Occupation>();
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new");
|
||||
request.SetContent(
|
||||
("group_el", "0"),
|
||||
("kurs", course),
|
||||
("type_z", "1"),
|
||||
("faculty", facultyId),
|
||||
("group", groupId),
|
||||
("ok", "Показать"),
|
||||
("schet", GetCurrentSemester()));
|
||||
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseContent = await response.Content.ReadAsStringAsync();
|
||||
if (string.IsNullOrWhiteSpace(responseContent))
|
||||
return schedule;
|
||||
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(responseContent);
|
||||
|
||||
string groupName = doc.QuerySelector("#group").Children.FirstOrDefault(i => i.HasAttribute("selected")).TextContent;
|
||||
|
||||
IHtmlCollection<IElement> pairs = doc.QuerySelectorAll(".pair");
|
||||
foreach (IElement item in pairs)
|
||||
{
|
||||
DateTime[] dates = GetDatesFromWeeks(
|
||||
offsetDay,
|
||||
int.Parse(item.GetAttribute("weekday")),
|
||||
item.QuerySelector(".weeks").TextContent.Replace("(", "").Replace("н)", "").Replace(" ", "").Split(','));
|
||||
|
||||
foreach(DateTime date in dates)
|
||||
{
|
||||
schedule.Add(new Occupation
|
||||
{
|
||||
Name = item.QuerySelector(".subect").TextContent,
|
||||
Type = item.QuerySelector(".type").TextContent,
|
||||
Group = groupName
|
||||
});
|
||||
}
|
||||
string name, type, professor, place;
|
||||
int order, weekday;
|
||||
string[] weeks;
|
||||
|
||||
name = item.QuerySelector(".subect")?.TextContent ?? "Неизвестный предмет (см. Расписание)";
|
||||
type = item.QuerySelector(".type").TextContent.Replace("(", "").Replace(")", "");
|
||||
professor = item.QuerySelector(".teacher")?.GetAttribute("title").Replace(";", "") ?? "";
|
||||
place = item.QuerySelector(".aud")?.TextContent ?? "СПбГУТ";
|
||||
order = int.Parse(item.GetAttribute("pair")) - 1;
|
||||
weeks = item.QuerySelector(".weeks").TextContent.Replace("(", "").Replace("н)", "").Replace(" ", "").Split(',');
|
||||
weekday = int.Parse(item.GetAttribute("weekday"));
|
||||
|
||||
schedule.AddRange(Occupation.GetSubject(name, type, professor, place, order, weeks, weekday, groupName));
|
||||
}
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
|
||||
private static async Task<List<Occupation>> GetSessionSchedule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static async Task<List<CabinetSubject>> GetCabinetSchedule(HttpClient client, DateTime date, bool checkProfSchedule)
|
||||
{
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"https://cabs.itut.ru/cabinet/project/cabinet/forms/{(checkProfSchedule ? "pr_" : "")}raspisanie_kalendar.php");
|
||||
request.SetContent(
|
||||
|
||||
Reference in New Issue
Block a user