implemented requests

This commit is contained in:
Timerix22 2023-09-02 18:08:26 +06:00
commit ba2ca206bd
19 changed files with 332 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
bin/
obj/

View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/modules.xml
/projectSettingsUpdater.xml
/.idea.PlatonusSchedule.iml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="User" />
</component>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,5 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
</profile>
</component>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<option name="fileGroupingEnabled" value="true" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,10 @@
namespace Platonus.API.DataModels;
class LoginResponse
{
/// session_id
public string? sid { get; set; }
public string? auth_token { get; set; }
/// should be "success"
public string? login_status { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace Platonus.API.DataModels;
public class ScheduleRequest
{
public int statusID { get; set; } = 1;
public int studentTypeID { get; set; } = 1;
public int week { get; set; } = 1;
}

View File

@ -0,0 +1,47 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace Platonus.API;
public class LoggindHttpHandler : DelegatingHandler
{
public LoggindHttpHandler(HttpMessageHandler innerHandler) : base(innerHandler)
{ }
void LogHttpRequest(HttpRequestMessage req)
{
Console.WriteLine($"REQUEST {req.Method} to {req.RequestUri}: " +
req.Content?.ReadAsStringAsync().GetAwaiter().GetResult());
}
void LogHttpResponse(HttpResponseMessage res)
{
Console.WriteLine($"RESPONSE {res.StatusCode} ({(int)res.StatusCode}) from {res.RequestMessage?.RequestUri}: " +
res.Content.ReadAsStringAsync().GetAwaiter().GetResult());
if (res.Headers.TryGetValues("Set-Cookie", out var cookieHeaders))
foreach (var cookieHeader in cookieHeaders)
{
Console.WriteLine($" Set-Cookie: {cookieHeader}");
}
}
#if !NETSTANDARD2_0
protected override HttpResponseMessage Send(HttpRequestMessage req, CancellationToken cancellationToken)
{
LogHttpRequest(req);
var res = base.Send(req, cancellationToken);
LogHttpResponse(res);
return res;
}
#endif
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken cancellationToken)
{
LogHttpRequest(req);
var res = await base.SendAsync(req, cancellationToken);
LogHttpResponse(res);
return res;
}
}

View File

@ -0,0 +1,20 @@
namespace Platonus.API;
public struct LoginCredentials
{
/// <summary>
/// student_id@iitu.edu.kz
/// </summary>
public readonly string Login;
public readonly string Password;
public readonly PlatonusLanguage Language;
public LoginCredentials(string login, string password, PlatonusLanguage language)
{
Login = login;
Password = password;
Language = language;
}
}

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0;net7.0</TargetFrameworks>
<LangVersion>11</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Platonus.API</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Net.Http.Json" Version="7.0.1" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,103 @@
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Platonus.API.DataModels;
namespace Platonus.API;
public class PlatonusClient
{
private const string base_url = "https://platonus.iitu.edu.kz/";
public bool DebugHttpMessages;
private LoginResponse? _loginResponse;
private PlatonusLanguage? _language;
private HttpClient _http;
private CookieContainer _cookies;
public PlatonusClient()
{
#if DEBUG
// TODO disable http messages logging
DebugHttpMessages = true;
#endif
_cookies = new CookieContainer();
var httpClientHandler = new HttpClientHandler
{
CookieContainer = _cookies
};
_http = new HttpClient(new LoggindHttpHandler(httpClientHandler))
{
BaseAddress = new Uri(base_url)
};
}
public async Task LoginAsync(LoginCredentials userCredentials)
{
string json = $$"""
{
"login": "{{userCredentials.Login}}",
"password": "{{userCredentials.Password}}",
"authForDeductedStudentsAndGraduates": "false"
}
""";
var reqContent = new StringContent(json);
reqContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
_language = userCredentials.Language;
reqContent.Headers.Add("language", _language.Number.ToString());
try
{
// send POST request
var res = await _http.PostAsync("rest/api/login", reqContent);
// parse json
if (res.Content.Headers.ContentLength < 1)
throw new Exception("responce doesn't have any content");
_loginResponse = await res.Content.ReadFromJsonAsync<LoginResponse>()
?? throw new Exception("invalid login request rezult");
if(_loginResponse.login_status != "success")
throw new Exception("invalid login request rezult");
// set session id and user token headers in HttpClient
_http.DefaultRequestHeaders.Add("sid", _loginResponse.sid);
_http.DefaultRequestHeaders.Add("token", _loginResponse.auth_token);
}
catch (HttpRequestException re)
{
HandleRequestException(re);
}
}
public async Task GetScheduleAsync()
{
if (_language is null)
throw new Exception("language is null, you need to login");
if (_loginResponse is null)
throw new Exception("session id is null, you need to login");
try
{
var req = JsonContent.Create<ScheduleRequest>(new ScheduleRequest());
var res = await _http.PostAsync(
$"rest/schedule/userSchedule/student/initial/{_language.LiteralCode}",
req);
// var rezult = await res.Content.ReadFromJsonAsync<ScheduleResponseData>();
}
catch (HttpRequestException re)
{
HandleRequestException(re);
}
}
private void HandleRequestException(HttpRequestException re)
{
// TODO http exception handling
throw re;
}
}

View File

@ -0,0 +1,17 @@
namespace Platonus.API;
public class PlatonusLanguage
{
public readonly int Number;
public readonly string LiteralCode;
private PlatonusLanguage(int num, string literalCode)
{
Number = num;
LiteralCode = literalCode;
}
public static PlatonusLanguage English = new(0, "en");
public static PlatonusLanguage Russian = new(1, "ru");
public static PlatonusLanguage Kazakh = new(2, "kz");
}

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>10</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Platonus.API\Platonus.API.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,20 @@
using System;
using Platonus.API;
var p = new PlatonusClient();
var loginCredentials = new LoginCredentials(
ReadString("login"),
ReadString("password"),
PlatonusLanguage.English);
await p.LoginAsync(loginCredentials);
await p.GetScheduleAsync();
return;
string ReadString(string question)
{
Console.Write($"{question}: ");
string? answ = Console.ReadLine();
if (string.IsNullOrEmpty(answ))
throw new NullReferenceException();
return answ;
}

22
PlatonusSchedule.sln Normal file
View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Platonus.API", "Platonus.API\Platonus.API.csproj", "{3650802E-D79E-47FC-ADED-2D9D6AF80340}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlatonusSchedule.CLI", "PlatonusSchedule.CLI\PlatonusSchedule.CLI.csproj", "{B445963D-AB65-4138-912D-58A0A954A736}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3650802E-D79E-47FC-ADED-2D9D6AF80340}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3650802E-D79E-47FC-ADED-2D9D6AF80340}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3650802E-D79E-47FC-ADED-2D9D6AF80340}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3650802E-D79E-47FC-ADED-2D9D6AF80340}.Release|Any CPU.Build.0 = Release|Any CPU
{B445963D-AB65-4138-912D-58A0A954A736}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B445963D-AB65-4138-912D-58A0A954A736}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B445963D-AB65-4138-912D-58A0A954A736}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B445963D-AB65-4138-912D-58A0A954A736}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal