mirror of
https://github.com/XFox111/GUTSchedule.git
synced 2026-04-22 06:58:01 +03:00
[1.0.7] Added schedule export for profs
Now export preferences are kept
This commit is contained in:
@@ -31,14 +31,29 @@ namespace GUT.Schedule
|
||||
{
|
||||
try
|
||||
{
|
||||
status.Text = "Загрузка расписания";
|
||||
List<Subject> schedule = await Parser.LoadSchedule();
|
||||
if(Data.DataSet.HttpClient != null)
|
||||
{
|
||||
status.Text = "Загрузка расписания с картофельных серверов Бонча";
|
||||
List<ProfessorSubject> schedule = new List<ProfessorSubject>();
|
||||
|
||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||
for (DateTime d = Data.StartDate; int.Parse($"{d.Year}{d.Month:00}") <= int.Parse($"{Data.EndDate.Year}{Data.EndDate.Month:00}"); d = d.AddMonths(1))
|
||||
schedule.AddRange(await Parser.GetProfessorSchedule(Data.DataSet.HttpClient, d));
|
||||
|
||||
status.Text = "Экспортирование в календарь";
|
||||
Calendar.Export(schedule);
|
||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||
|
||||
status.Text = "Экспортирование в календарь";
|
||||
Calendar.Export(schedule);
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Text = "Загрузка расписания";
|
||||
List<Subject> schedule = await Parser.LoadSchedule();
|
||||
|
||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||
|
||||
status.Text = "Экспортирование в календарь";
|
||||
Calendar.Export(schedule);
|
||||
}
|
||||
|
||||
status.Text = "Готово";
|
||||
await Task.Delay(1000);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Support.V4.Text;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Text.Method;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using AngleSharp.Html.Dom;
|
||||
using AngleSharp.Html.Parser;
|
||||
using GUT.Schedule.Models;
|
||||
|
||||
namespace GUT.Schedule
|
||||
@@ -18,35 +22,64 @@ namespace GUT.Schedule
|
||||
{
|
||||
Button start, end, export;
|
||||
Button forDay, forWeek, forMonth, forSemester;
|
||||
Spinner faculty, course, group, reminder, calendar;
|
||||
Spinner faculty, course, group, reminder, calendar, user;
|
||||
CheckBox groupTitle;
|
||||
TextView error;
|
||||
LinearLayout studentParams, profParams;
|
||||
EditText email, password;
|
||||
|
||||
ISharedPreferences prefs;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.activity_main);
|
||||
|
||||
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
||||
|
||||
AssignVariables();
|
||||
|
||||
faculty.SetList(this, Data.Faculties.Select(i => i.Name));
|
||||
int s = Data.Faculties.FindIndex(i => i.Id == prefs.GetString("Faculty", "-123"));
|
||||
faculty.SetSelection(s == -1 ? 0 : s);
|
||||
|
||||
course.SetList(this, "1234".ToCharArray());
|
||||
course.SetSelection(prefs.GetInt("Course", 0)); // IDK why but this shit triggers events anyway (even if they are set in the next line. It seem to be that there's some asynchronous shit somewhere there)
|
||||
// P.S. Fuck Android
|
||||
|
||||
AddEvents();
|
||||
|
||||
// Settings spinners' dropdown lists content
|
||||
faculty.SetList(this, Data.Faculties.Select(i => i.Name));
|
||||
course.SetList(this, "1234".ToCharArray());
|
||||
reminder.SetList(this, new string[]
|
||||
user.SetList(this, new[]
|
||||
{
|
||||
"Студент",
|
||||
"Преподаватель"
|
||||
});
|
||||
user.SetSelection(prefs.GetInt("User", 0));
|
||||
|
||||
reminder.SetList(this, new[]
|
||||
{
|
||||
"Нет",
|
||||
"Во время начала",
|
||||
"За 5 мин",
|
||||
"За 10 мин"
|
||||
});
|
||||
reminder.SetSelection(prefs.GetInt("Reminder", 0));
|
||||
|
||||
calendar.SetList(this, Calendar.Calendars.Select(i => i.Name));
|
||||
s = Calendar.Calendars.FindIndex(i => i.Id == prefs.GetString("Calendar", "-123"));
|
||||
calendar.SetSelection(s == -1 ? 0 : s);
|
||||
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
start.Text = Data.StartDate.ToShortDateString();
|
||||
|
||||
groupTitle.Checked = prefs.GetBoolean("AddGroupToHeader", false);
|
||||
|
||||
email.Text = prefs.GetString("email", "");
|
||||
password.Text = prefs.GetString("password", "");
|
||||
}
|
||||
|
||||
private void Export_Click(object sender, EventArgs e)
|
||||
private async void Export_Click(object sender, EventArgs e)
|
||||
{
|
||||
error.Visibility = ViewStates.Gone;
|
||||
|
||||
@@ -57,15 +90,82 @@ namespace GUT.Schedule
|
||||
return;
|
||||
}
|
||||
|
||||
HttpClient client = null;
|
||||
if(user.SelectedItemPosition == 1)
|
||||
{
|
||||
Toast.MakeText(ApplicationContext, "Авторизация...", ToastLength.Short).Show();
|
||||
if (string.IsNullOrWhiteSpace(email.Text) || string.IsNullOrWhiteSpace(password.Text))
|
||||
{
|
||||
error.Text = "Ошибка: Введите корректные учетные данные";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
export.Enabled = false;
|
||||
client = new HttpClient();
|
||||
|
||||
await client.GetAsync("https://cabs.itut.ru/cabinet/");
|
||||
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/lib/autentificationok.php");
|
||||
request.SetContent(
|
||||
("users", email.Text),
|
||||
("parole", password.Text));
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseContent = await response.GetString();
|
||||
export.Enabled = true;
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
error.Text = $"Ошибка авторизации: {response.StatusCode}: {responseContent}";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!responseContent.StartsWith("1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
error.Text = $"Ошибка авторизации: Неверный e-mail и/или пароль ({string.Join("; ", responseContent.Replace("error=", "", StringComparison.OrdinalIgnoreCase).Split('|'))})";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
export.Enabled = false;
|
||||
HttpResponseMessage verificationResponse = await client.GetAsync("https://cabs.itut.ru/cabinet/?login=yes");
|
||||
export.Enabled = true;
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(await verificationResponse.GetString());
|
||||
if (!doc.QuerySelectorAll("nobr").Any(i => i.TextContent.Contains("Ведомости")))
|
||||
{
|
||||
error.Text = "Ошибка авторизации: Необходимо авторизоваться с аккаунтом преподавателя";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
Data.Groups = null;
|
||||
|
||||
// According to this SO thread: https://stackoverflow.com/questions/1925486/android-storing-username-and-password
|
||||
// I consider Preferences as safe enough method for storing credentials
|
||||
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutBoolean("email", groupTitle.Checked).Apply();
|
||||
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutBoolean("password", groupTitle.Checked).Apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Data.Groups.Count < 1)
|
||||
{
|
||||
error.Text = "Ошибка: Не выбрана группа";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Forming export parameters
|
||||
Data.DataSet = new DataSet
|
||||
{
|
||||
Faculty = Data.Faculties[faculty.SelectedItemPosition].Id,
|
||||
Group = Data.Groups[group.SelectedItemPosition].Id,
|
||||
Group = Data.Groups?[group.SelectedItemPosition].Id,
|
||||
Course = course.SelectedItemPosition + 1,
|
||||
AddGroupToTitle = groupTitle.Checked,
|
||||
Calendar = Calendar.Calendars[calendar.SelectedItemPosition].Id,
|
||||
Reminder = (reminder.SelectedItemPosition - 1) * 5
|
||||
Reminder = (reminder.SelectedItemPosition - 1) * 5,
|
||||
HttpClient = client
|
||||
};
|
||||
|
||||
StartActivity(new Intent(this, typeof(ExportActivity)));
|
||||
@@ -83,13 +183,16 @@ namespace GUT.Schedule
|
||||
start.Text = Data.StartDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void UpdateGroupsList(object sender, AdapterView.ItemSelectedEventArgs e)
|
||||
private async void UpdateGroupsList()
|
||||
{
|
||||
if (course.SelectedItem == null)
|
||||
return;
|
||||
|
||||
await Parser.LoadGroups(Data.Faculties[faculty.SelectedItemPosition].Id, course.SelectedItemPosition + 1);
|
||||
group.SetList(this, Data.Groups.Select(i => i.Name));
|
||||
|
||||
int s = Data.Groups?.FindIndex(i => i.Id == prefs.GetString("Group", "-123")) ?? 0;
|
||||
group.SetSelection(s == -1 ? 0 : s);
|
||||
}
|
||||
|
||||
private void SetDate(int days)
|
||||
@@ -115,15 +218,57 @@ namespace GUT.Schedule
|
||||
group = FindViewById<Spinner>(Resource.Id.group);
|
||||
reminder = FindViewById<Spinner>(Resource.Id.reminder);
|
||||
calendar = FindViewById<Spinner>(Resource.Id.calendar);
|
||||
user = FindViewById<Spinner>(Resource.Id.user);
|
||||
|
||||
error = FindViewById<TextView>(Resource.Id.error);
|
||||
groupTitle = FindViewById<CheckBox>(Resource.Id.groupTitle);
|
||||
|
||||
studentParams = FindViewById<LinearLayout>(Resource.Id.studentParams);
|
||||
profParams = FindViewById<LinearLayout>(Resource.Id.professorParams);
|
||||
|
||||
email = FindViewById<EditText>(Resource.Id.email);
|
||||
password = FindViewById<EditText>(Resource.Id.password);
|
||||
}
|
||||
|
||||
private void AddEvents()
|
||||
{
|
||||
faculty.ItemSelected += UpdateGroupsList;
|
||||
course.ItemSelected += UpdateGroupsList;
|
||||
faculty.ItemSelected += (s, e) =>
|
||||
{
|
||||
prefs.Edit().PutString("Faculty", Data.Faculties[e.Position].Id).Apply();
|
||||
UpdateGroupsList();
|
||||
};
|
||||
course.ItemSelected += (s, e) =>
|
||||
{
|
||||
prefs.Edit().PutInt("Course", e.Position).Apply();
|
||||
UpdateGroupsList();
|
||||
};
|
||||
user.ItemSelected += (s, e) =>
|
||||
{
|
||||
prefs.Edit().PutInt("User", e.Position).Apply();
|
||||
switch (e.Position)
|
||||
{
|
||||
case 0:
|
||||
studentParams.Visibility = ViewStates.Visible;
|
||||
groupTitle.Visibility = ViewStates.Visible;
|
||||
profParams.Visibility = ViewStates.Gone;
|
||||
break;
|
||||
case 1:
|
||||
studentParams.Visibility = ViewStates.Gone;
|
||||
groupTitle.Visibility = ViewStates.Gone;
|
||||
profParams.Visibility = ViewStates.Visible;
|
||||
break;
|
||||
}
|
||||
};
|
||||
calendar.ItemSelected += (s, e) =>
|
||||
prefs.Edit().PutString("Calendar", Calendar.Calendars[e.Position].Id).Apply();
|
||||
reminder.ItemSelected += (s, e) =>
|
||||
prefs.Edit().PutInt("Reminder", e.Position).Apply();
|
||||
group.ItemSelected += (s, e) =>
|
||||
prefs.Edit().PutString("Group", Data.Groups[e.Position].Id).Apply();
|
||||
|
||||
groupTitle.Click += (s, e) =>
|
||||
prefs.Edit().PutBoolean("AddGroupToHeader", groupTitle.Checked).Apply();
|
||||
|
||||
|
||||
forDay.Click += (s, e) => SetDate(0);
|
||||
forWeek.Click += (s, e) => SetDate(6);
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace GUT.Schedule
|
||||
|
||||
foreach (Subject item in schedule)
|
||||
{
|
||||
Android.Content.ContentValues eventValues = new Android.Content.ContentValues();
|
||||
ContentValues eventValues = new ContentValues();
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace GUT.Schedule
|
||||
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, Extensions.ToUnixTime(item.EndTime));
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
||||
@@ -76,7 +76,51 @@ namespace GUT.Schedule
|
||||
// Settings reminder
|
||||
if(data.Reminder != -5)
|
||||
{
|
||||
Android.Content.ContentValues reminderValues = new Android.Content.ContentValues();
|
||||
ContentValues reminderValues = new ContentValues();
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
||||
|
||||
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Export(IEnumerable<ProfessorSubject> schedule)
|
||||
{
|
||||
DataSet data = Data.DataSet;
|
||||
|
||||
foreach (ProfessorSubject item in schedule)
|
||||
{
|
||||
ContentValues eventValues = new ContentValues();
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}. {1} ({2})",
|
||||
item.Order,
|
||||
item.Name,
|
||||
item.Type));
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Groups);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, item.Cabinet);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
||||
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
||||
|
||||
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
||||
|
||||
// Settings reminder
|
||||
if(data.Reminder != -5)
|
||||
{
|
||||
ContentValues reminderValues = new ContentValues();
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Android.Content;
|
||||
using Android.Widget;
|
||||
|
||||
@@ -45,5 +48,24 @@ namespace GUT.Schedule
|
||||
/// <returns><see cref="long"/> which is represented by total milliseconds count passed since 1970</returns>
|
||||
public static long ToUnixTime(this DateTime dt) =>
|
||||
(long)dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
||||
|
||||
public static void SetContent(this HttpRequestMessage request, params (string key, string value)[] values)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
Dictionary<string, string> body = new Dictionary<string, string>();
|
||||
foreach ((string key, string value) in values)
|
||||
body.Add(key, value);
|
||||
request.Content = new FormUrlEncodedContent(body);
|
||||
}
|
||||
public static async Task<string> GetString(this HttpResponseMessage response)
|
||||
{
|
||||
if (response == null)
|
||||
throw new ArgumentNullException(nameof(response));
|
||||
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
return Encoding.GetEncoding("Windows-1251").GetString(await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,7 @@
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="Activities\MainActivity.cs" />
|
||||
<Compile Include="Models\DataSet.cs" />
|
||||
<Compile Include="Models\ProfessorSubject.cs" />
|
||||
<Compile Include="Parser.cs" />
|
||||
<Compile Include="Resources\Resource.designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace GUT.Schedule.Models
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GUT.Schedule.Models
|
||||
{
|
||||
public class DataSet
|
||||
{
|
||||
@@ -8,5 +10,6 @@
|
||||
public string Group { get; set; }
|
||||
public int Reminder { get; set; }
|
||||
public bool AddGroupToTitle { get; set; }
|
||||
public HttpClient HttpClient { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
|
||||
namespace GUT.Schedule.Models
|
||||
{
|
||||
public class ProfessorSubject
|
||||
{
|
||||
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 Groups { get; set; }
|
||||
|
||||
public ProfessorSubject(string name, string type, string cabinet, string groups, int year, int month, int day, string schedule)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
Cabinet = cabinet;
|
||||
Groups = groups;
|
||||
|
||||
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);
|
||||
Order = time[0] switch
|
||||
{
|
||||
"09.00" => "1",
|
||||
"10.45" => "2",
|
||||
"13.00" => "3",
|
||||
"14.45" => "4",
|
||||
"16.30" => "5",
|
||||
"18.15" => "6",
|
||||
"20.00" => "7",
|
||||
"10.30" => "2", //Расписание для пар по физ-ре
|
||||
"12.00" => "3",
|
||||
"13.30" => "4",
|
||||
"15.00" => "5",
|
||||
"18.00" => "7",
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,6 @@ namespace GUT.Schedule
|
||||
|
||||
public static async Task LoadGroups(string facultyId, int course)
|
||||
{
|
||||
Data.Groups = new List<(string, string)>();
|
||||
using HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
@@ -107,6 +106,7 @@ namespace GUT.Schedule
|
||||
|
||||
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 { }
|
||||
@@ -122,5 +122,39 @@ namespace GUT.Schedule
|
||||
return $"205.{now.Year - 2001}{now.Year - 2000}/2";
|
||||
}
|
||||
|
||||
public static async Task<List<ProfessorSubject>> GetProfessorSchedule(HttpClient client, DateTime date)
|
||||
{
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/project/cabinet/forms/pr_raspisanie_kalendar.php");
|
||||
request.SetContent(
|
||||
("month", date.Month.ToString()),
|
||||
("year", date.Year.ToString()),
|
||||
("type_z", "0"));
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
string responseContent = await response.GetString().ConfigureAwait(false);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpRequestException(responseContent);
|
||||
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(responseContent);
|
||||
List<ProfessorSubject> schedule = new List<ProfessorSubject>();
|
||||
foreach(var i in doc.QuerySelectorAll("td").Where(i => i.GetAttribute("style") == "text-align: center; vertical-align: top"))
|
||||
for (int k = 0; k < i.QuerySelectorAll("i").Length; k++)
|
||||
{
|
||||
ProfessorSubject item = new ProfessorSubject(
|
||||
name: i.QuerySelectorAll("b")[k * 2 + 1].TextContent,
|
||||
type: i.QuerySelectorAll("i")[k].TextContent,
|
||||
cabinet: i.ChildNodes[k * 13 + 12].TextContent,
|
||||
groups: i.ChildNodes[k * 13 + 7].TextContent,
|
||||
year: date.Year,
|
||||
month: date.Month,
|
||||
day: int.Parse(i.QuerySelectorAll("b")[0].TextContent),
|
||||
schedule: i.QuerySelectorAll("b")[k * 2 + 2].TextContent
|
||||
);
|
||||
schedule.Add(item);
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="106" android:versionName="1.0.6" package="com.xfox111.gut.schedule" android:installLocation="auto">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="107" android:versionName="1.0.7" package="com.xfox111.gut.schedule" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28" />
|
||||
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="ГУТ.Расписание" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBar"></application>
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||
|
||||
+119
-107
@@ -3590,253 +3590,265 @@ namespace GUT.Schedule
|
||||
public const int parent_matrix = 2131230844;
|
||||
|
||||
// aapt resource value: 0x7F08007D
|
||||
public const int pin = 2131230845;
|
||||
public const int password = 2131230845;
|
||||
|
||||
// aapt resource value: 0x7F08007E
|
||||
public const int progress_circular = 2131230846;
|
||||
public const int pin = 2131230846;
|
||||
|
||||
// aapt resource value: 0x7F08007F
|
||||
public const int progress_horizontal = 2131230847;
|
||||
public const int professorParams = 2131230847;
|
||||
|
||||
// aapt resource value: 0x7F080080
|
||||
public const int radio = 2131230848;
|
||||
public const int progress_circular = 2131230848;
|
||||
|
||||
// aapt resource value: 0x7F080081
|
||||
public const int reminder = 2131230849;
|
||||
public const int progress_horizontal = 2131230849;
|
||||
|
||||
// aapt resource value: 0x7F080082
|
||||
public const int right = 2131230850;
|
||||
public const int radio = 2131230850;
|
||||
|
||||
// aapt resource value: 0x7F080083
|
||||
public const int right_icon = 2131230851;
|
||||
public const int reminder = 2131230851;
|
||||
|
||||
// aapt resource value: 0x7F080084
|
||||
public const int right_side = 2131230852;
|
||||
public const int right = 2131230852;
|
||||
|
||||
// aapt resource value: 0x7F080085
|
||||
public const int save_image_matrix = 2131230853;
|
||||
public const int right_icon = 2131230853;
|
||||
|
||||
// aapt resource value: 0x7F080086
|
||||
public const int save_non_transition_alpha = 2131230854;
|
||||
public const int right_side = 2131230854;
|
||||
|
||||
// aapt resource value: 0x7F080087
|
||||
public const int save_scale_type = 2131230855;
|
||||
public const int save_image_matrix = 2131230855;
|
||||
|
||||
// aapt resource value: 0x7F080088
|
||||
public const int screen = 2131230856;
|
||||
public const int save_non_transition_alpha = 2131230856;
|
||||
|
||||
// aapt resource value: 0x7F080089
|
||||
public const int scroll = 2131230857;
|
||||
|
||||
// aapt resource value: 0x7F08008D
|
||||
public const int scrollable = 2131230861;
|
||||
public const int save_scale_type = 2131230857;
|
||||
|
||||
// aapt resource value: 0x7F08008A
|
||||
public const int scrollIndicatorDown = 2131230858;
|
||||
public const int screen = 2131230858;
|
||||
|
||||
// aapt resource value: 0x7F08008B
|
||||
public const int scrollIndicatorUp = 2131230859;
|
||||
|
||||
// aapt resource value: 0x7F08008C
|
||||
public const int scrollView = 2131230860;
|
||||
|
||||
// aapt resource value: 0x7F08008E
|
||||
public const int search_badge = 2131230862;
|
||||
public const int scroll = 2131230859;
|
||||
|
||||
// aapt resource value: 0x7F08008F
|
||||
public const int search_bar = 2131230863;
|
||||
public const int scrollable = 2131230863;
|
||||
|
||||
// aapt resource value: 0x7F08008C
|
||||
public const int scrollIndicatorDown = 2131230860;
|
||||
|
||||
// aapt resource value: 0x7F08008D
|
||||
public const int scrollIndicatorUp = 2131230861;
|
||||
|
||||
// aapt resource value: 0x7F08008E
|
||||
public const int scrollView = 2131230862;
|
||||
|
||||
// aapt resource value: 0x7F080090
|
||||
public const int search_button = 2131230864;
|
||||
public const int search_badge = 2131230864;
|
||||
|
||||
// aapt resource value: 0x7F080091
|
||||
public const int search_close_btn = 2131230865;
|
||||
public const int search_bar = 2131230865;
|
||||
|
||||
// aapt resource value: 0x7F080092
|
||||
public const int search_edit_frame = 2131230866;
|
||||
public const int search_button = 2131230866;
|
||||
|
||||
// aapt resource value: 0x7F080093
|
||||
public const int search_go_btn = 2131230867;
|
||||
public const int search_close_btn = 2131230867;
|
||||
|
||||
// aapt resource value: 0x7F080094
|
||||
public const int search_mag_icon = 2131230868;
|
||||
public const int search_edit_frame = 2131230868;
|
||||
|
||||
// aapt resource value: 0x7F080095
|
||||
public const int search_plate = 2131230869;
|
||||
public const int search_go_btn = 2131230869;
|
||||
|
||||
// aapt resource value: 0x7F080096
|
||||
public const int search_src_text = 2131230870;
|
||||
public const int search_mag_icon = 2131230870;
|
||||
|
||||
// aapt resource value: 0x7F080097
|
||||
public const int search_voice_btn = 2131230871;
|
||||
|
||||
// aapt resource value: 0x7F080099
|
||||
public const int selected = 2131230873;
|
||||
public const int search_plate = 2131230871;
|
||||
|
||||
// aapt resource value: 0x7F080098
|
||||
public const int select_dialog_listview = 2131230872;
|
||||
public const int search_src_text = 2131230872;
|
||||
|
||||
// aapt resource value: 0x7F080099
|
||||
public const int search_voice_btn = 2131230873;
|
||||
|
||||
// aapt resource value: 0x7F08009B
|
||||
public const int selected = 2131230875;
|
||||
|
||||
// aapt resource value: 0x7F08009A
|
||||
public const int select_dialog_listview = 2131230874;
|
||||
|
||||
// aapt resource value: 0x7F080004
|
||||
public const int SHIFT = 2131230724;
|
||||
|
||||
// aapt resource value: 0x7F08009A
|
||||
public const int shortcut = 2131230874;
|
||||
|
||||
// aapt resource value: 0x7F08009B
|
||||
public const int showCustom = 2131230875;
|
||||
|
||||
// aapt resource value: 0x7F08009C
|
||||
public const int showHome = 2131230876;
|
||||
public const int shortcut = 2131230876;
|
||||
|
||||
// aapt resource value: 0x7F08009D
|
||||
public const int showTitle = 2131230877;
|
||||
public const int showCustom = 2131230877;
|
||||
|
||||
// aapt resource value: 0x7F08009E
|
||||
public const int smallLabel = 2131230878;
|
||||
public const int showHome = 2131230878;
|
||||
|
||||
// aapt resource value: 0x7F08009F
|
||||
public const int snackbar_action = 2131230879;
|
||||
public const int showTitle = 2131230879;
|
||||
|
||||
// aapt resource value: 0x7F0800A0
|
||||
public const int snackbar_text = 2131230880;
|
||||
public const int smallLabel = 2131230880;
|
||||
|
||||
// aapt resource value: 0x7F0800A1
|
||||
public const int snap = 2131230881;
|
||||
public const int snackbar_action = 2131230881;
|
||||
|
||||
// aapt resource value: 0x7F0800A2
|
||||
public const int snapMargins = 2131230882;
|
||||
public const int snackbar_text = 2131230882;
|
||||
|
||||
// aapt resource value: 0x7F0800A3
|
||||
public const int spacer = 2131230883;
|
||||
public const int snap = 2131230883;
|
||||
|
||||
// aapt resource value: 0x7F0800A4
|
||||
public const int split_action_bar = 2131230884;
|
||||
public const int snapMargins = 2131230884;
|
||||
|
||||
// aapt resource value: 0x7F0800A5
|
||||
public const int src_atop = 2131230885;
|
||||
public const int spacer = 2131230885;
|
||||
|
||||
// aapt resource value: 0x7F0800A6
|
||||
public const int src_in = 2131230886;
|
||||
public const int split_action_bar = 2131230886;
|
||||
|
||||
// aapt resource value: 0x7F0800A7
|
||||
public const int src_over = 2131230887;
|
||||
public const int src_atop = 2131230887;
|
||||
|
||||
// aapt resource value: 0x7F0800A8
|
||||
public const int start = 2131230888;
|
||||
public const int src_in = 2131230888;
|
||||
|
||||
// aapt resource value: 0x7F0800A9
|
||||
public const int status = 2131230889;
|
||||
public const int src_over = 2131230889;
|
||||
|
||||
// aapt resource value: 0x7F0800AA
|
||||
public const int stretch = 2131230890;
|
||||
public const int start = 2131230890;
|
||||
|
||||
// aapt resource value: 0x7F0800AB
|
||||
public const int submenuarrow = 2131230891;
|
||||
public const int status = 2131230891;
|
||||
|
||||
// aapt resource value: 0x7F0800AC
|
||||
public const int submit_area = 2131230892;
|
||||
public const int stretch = 2131230892;
|
||||
|
||||
// aapt resource value: 0x7F0800AD
|
||||
public const int studentParams = 2131230893;
|
||||
|
||||
// aapt resource value: 0x7F0800AE
|
||||
public const int submenuarrow = 2131230894;
|
||||
|
||||
// aapt resource value: 0x7F0800AF
|
||||
public const int submit_area = 2131230895;
|
||||
|
||||
// aapt resource value: 0x7F080005
|
||||
public const int SYM = 2131230725;
|
||||
|
||||
// aapt resource value: 0x7F0800AD
|
||||
public const int tabMode = 2131230893;
|
||||
|
||||
// aapt resource value: 0x7F0800AE
|
||||
public const int tag_transition_group = 2131230894;
|
||||
|
||||
// aapt resource value: 0x7F0800AF
|
||||
public const int tag_unhandled_key_event_manager = 2131230895;
|
||||
|
||||
// aapt resource value: 0x7F0800B0
|
||||
public const int tag_unhandled_key_listeners = 2131230896;
|
||||
public const int tabMode = 2131230896;
|
||||
|
||||
// aapt resource value: 0x7F0800B1
|
||||
public const int text = 2131230897;
|
||||
public const int tag_transition_group = 2131230897;
|
||||
|
||||
// aapt resource value: 0x7F0800B2
|
||||
public const int text2 = 2131230898;
|
||||
|
||||
// aapt resource value: 0x7F0800B7
|
||||
public const int textinput_counter = 2131230903;
|
||||
|
||||
// aapt resource value: 0x7F0800B8
|
||||
public const int textinput_error = 2131230904;
|
||||
|
||||
// aapt resource value: 0x7F0800B9
|
||||
public const int textinput_helper_text = 2131230905;
|
||||
public const int tag_unhandled_key_event_manager = 2131230898;
|
||||
|
||||
// aapt resource value: 0x7F0800B3
|
||||
public const int textSpacerNoButtons = 2131230899;
|
||||
public const int tag_unhandled_key_listeners = 2131230899;
|
||||
|
||||
// aapt resource value: 0x7F0800B4
|
||||
public const int textSpacerNoTitle = 2131230900;
|
||||
public const int text = 2131230900;
|
||||
|
||||
// aapt resource value: 0x7F0800B5
|
||||
public const int textStart = 2131230901;
|
||||
|
||||
// aapt resource value: 0x7F0800B6
|
||||
public const int text_input_password_toggle = 2131230902;
|
||||
public const int text2 = 2131230901;
|
||||
|
||||
// aapt resource value: 0x7F0800BA
|
||||
public const int time = 2131230906;
|
||||
public const int textinput_counter = 2131230906;
|
||||
|
||||
// aapt resource value: 0x7F0800BB
|
||||
public const int title = 2131230907;
|
||||
public const int textinput_error = 2131230907;
|
||||
|
||||
// aapt resource value: 0x7F0800BC
|
||||
public const int titleDividerNoCustom = 2131230908;
|
||||
public const int textinput_helper_text = 2131230908;
|
||||
|
||||
// aapt resource value: 0x7F0800B6
|
||||
public const int textSpacerNoButtons = 2131230902;
|
||||
|
||||
// aapt resource value: 0x7F0800B7
|
||||
public const int textSpacerNoTitle = 2131230903;
|
||||
|
||||
// aapt resource value: 0x7F0800B8
|
||||
public const int textStart = 2131230904;
|
||||
|
||||
// aapt resource value: 0x7F0800B9
|
||||
public const int text_input_password_toggle = 2131230905;
|
||||
|
||||
// aapt resource value: 0x7F0800BD
|
||||
public const int title_template = 2131230909;
|
||||
public const int time = 2131230909;
|
||||
|
||||
// aapt resource value: 0x7F0800BE
|
||||
public const int top = 2131230910;
|
||||
public const int title = 2131230910;
|
||||
|
||||
// aapt resource value: 0x7F0800BF
|
||||
public const int topPanel = 2131230911;
|
||||
public const int titleDividerNoCustom = 2131230911;
|
||||
|
||||
// aapt resource value: 0x7F0800C0
|
||||
public const int touch_outside = 2131230912;
|
||||
public const int title_template = 2131230912;
|
||||
|
||||
// aapt resource value: 0x7F0800C1
|
||||
public const int transition_current_scene = 2131230913;
|
||||
public const int top = 2131230913;
|
||||
|
||||
// aapt resource value: 0x7F0800C2
|
||||
public const int transition_layout_save = 2131230914;
|
||||
public const int topPanel = 2131230914;
|
||||
|
||||
// aapt resource value: 0x7F0800C3
|
||||
public const int transition_position = 2131230915;
|
||||
public const int touch_outside = 2131230915;
|
||||
|
||||
// aapt resource value: 0x7F0800C4
|
||||
public const int transition_scene_layoutid_cache = 2131230916;
|
||||
public const int transition_current_scene = 2131230916;
|
||||
|
||||
// aapt resource value: 0x7F0800C5
|
||||
public const int transition_transform = 2131230917;
|
||||
public const int transition_layout_save = 2131230917;
|
||||
|
||||
// aapt resource value: 0x7F0800C6
|
||||
public const int uniform = 2131230918;
|
||||
public const int transition_position = 2131230918;
|
||||
|
||||
// aapt resource value: 0x7F0800C7
|
||||
public const int unlabeled = 2131230919;
|
||||
public const int transition_scene_layoutid_cache = 2131230919;
|
||||
|
||||
// aapt resource value: 0x7F0800C8
|
||||
public const int up = 2131230920;
|
||||
public const int transition_transform = 2131230920;
|
||||
|
||||
// aapt resource value: 0x7F0800C9
|
||||
public const int useLogo = 2131230921;
|
||||
public const int uniform = 2131230921;
|
||||
|
||||
// aapt resource value: 0x7F0800CA
|
||||
public const int view_offset_helper = 2131230922;
|
||||
public const int unlabeled = 2131230922;
|
||||
|
||||
// aapt resource value: 0x7F0800CB
|
||||
public const int visible = 2131230923;
|
||||
public const int up = 2131230923;
|
||||
|
||||
// aapt resource value: 0x7F0800CC
|
||||
public const int withText = 2131230924;
|
||||
public const int useLogo = 2131230924;
|
||||
|
||||
// aapt resource value: 0x7F0800CD
|
||||
public const int wrap_content = 2131230925;
|
||||
public const int user = 2131230925;
|
||||
|
||||
// aapt resource value: 0x7F0800CE
|
||||
public const int view_offset_helper = 2131230926;
|
||||
|
||||
// aapt resource value: 0x7F0800CF
|
||||
public const int visible = 2131230927;
|
||||
|
||||
// aapt resource value: 0x7F0800D0
|
||||
public const int withText = 2131230928;
|
||||
|
||||
// aapt resource value: 0x7F0800D1
|
||||
public const int wrap_content = 2131230929;
|
||||
|
||||
static Id()
|
||||
{
|
||||
|
||||
@@ -19,35 +19,78 @@
|
||||
android:textStyle="bold"
|
||||
android:textSize="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Факультет"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/faculty"
|
||||
android:id="@+id/user"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:id="@+id/studentParams"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Курс"/>
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/course"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Факультет"/>
|
||||
|
||||
<TextView
|
||||
<Spinner
|
||||
android:id="@+id/faculty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Курс"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/course"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Группа"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/professorParams"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Группа"/>
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="E-mail"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/email"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textWebEmailAddress"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Пароль"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textWebPassword"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
|
||||
Reference in New Issue
Block a user