Skip to content

Commit a57a03f

Browse files
committed
initial commit
0 parents  commit a57a03f

File tree

18 files changed

+676
-0
lines changed

18 files changed

+676
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
bin/
2+
obj/
3+
/packages/
4+
riderModule.iml
5+
/_ReSharper.Caches/
6+
.idea/
7+
/SaveMyMyimaths.sln.DotSettings.user

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# SaveMyMyimaths
2+
3+
A tool used to help myself with boring and annoying Myimaths tasks. Feel free to use it.
4+
5+
**IMPORTANT: It is STRONGLY discouraged to use under un-emergent situations. There are traces of using this tool that
6+
administrators can find out.**
7+
8+
## How-to
9+
10+
### For Windows x64 users:
11+
12+
- Download and extract “win_x64.zip” in directory “Releases”;
13+
- Run “SaveMyMyimaths.exe”.
14+
15+
### For Mac M-series users:
16+
17+
- Download [.NET SDK 8](https://dotnet.microsoft.com/en-us/download) if you haven’t done so;
18+
- Download and extract “osx_arm64.zip” in directory “Releases”;
19+
- Open up Terminal in the extracted directory;
20+
- Run “dotnet ./SaveMyMyimaths.dll”
21+
22+
### For Mac Intel-series users:
23+
24+
- Download [.NET SDK 8](https://dotnet.microsoft.com/en-us/download) if you haven’t done so;
25+
- Download and extract “osx_x64.zip” in directory “Releases”;
26+
- Open up Terminal in the extracted directory;
27+
- Run “dotnet ./SaveMyMyimaths.dll”
28+
29+
### For other systems:
30+
31+
Go and build it yourself😡

Release/osx_arm64.zip

30.8 MB
Binary file not shown.

Release/osx_x64.zip

32.4 MB
Binary file not shown.

Release/win_x64.zip

29.9 MB
Binary file not shown.

SaveMyMyimaths.sln

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaveMyMyimaths", "SaveMyMyimaths\SaveMyMyimaths.csproj", "{8DA9D153-0901-4D3D-9084-185C5A9C586C}"
4+
EndProject
5+
Global
6+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7+
Debug|Any CPU = Debug|Any CPU
8+
Release|Any CPU = Release|Any CPU
9+
EndGlobalSection
10+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
11+
{8DA9D153-0901-4D3D-9084-185C5A9C586C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12+
{8DA9D153-0901-4D3D-9084-185C5A9C586C}.Debug|Any CPU.Build.0 = Debug|Any CPU
13+
{8DA9D153-0901-4D3D-9084-185C5A9C586C}.Release|Any CPU.ActiveCfg = Release|Any CPU
14+
{8DA9D153-0901-4D3D-9084-185C5A9C586C}.Release|Any CPU.Build.0 = Release|Any CPU
15+
EndGlobalSection
16+
EndGlobal
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System.Text;
2+
using System.Web;
3+
using HtmlAgilityPack;
4+
using SaveMyMyimaths.Records;
5+
6+
namespace SaveMyMyimaths;
7+
8+
public class CrackHandler
9+
{
10+
private static readonly int TaskAmount = 5;
11+
12+
public static async Task DoTaskAsync(int index)
13+
{
14+
var markParameters = await LoadTaskAsync(index);
15+
16+
var client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
17+
var request = new HttpRequestMessage(HttpMethod.Post, "https://app.myimaths.com/api/legacy/save/mark");
18+
Utilities.Utilities.AddHeaders(ref request);
19+
20+
request.Content = new StringContent(Utilities.Utilities.ToQueryString(new Dictionary<string, string?>
21+
{
22+
{ "taskID", markParameters.TaskId.ToString() },
23+
{ "realID", markParameters.RealId.ToString() },
24+
{ "q1score", markParameters.Q1Score.ToString() },
25+
{ "q2score", markParameters.Q2Score.ToString() },
26+
{ "q3score", null },
27+
{ "q4score", null },
28+
{ "sCode", markParameters.GetSCode().ToString() },
29+
{ "studentID", markParameters.StudentId.ToString() },
30+
{ "authToken", markParameters.AuthToken },
31+
{ "time_spent", new Random().Next(600_000, 1_260_000).ToString() }
32+
}), Encoding.UTF8, "application/x-www-form-urlencoded");
33+
34+
Registry.Registry.GetProgress("1").Update("Uploading marks...");
35+
var response = await client.SendAsync(request);
36+
37+
Registry.Registry.GetProgress("1").Update("Finished.");
38+
}
39+
40+
private static async Task<MarkParameterRecord> LoadTaskAsync(int index)
41+
{
42+
var markParameters = await GetMarkParameterRecordAsync(index);
43+
44+
var client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
45+
46+
var request = (HttpContent)new StringContent(Utilities.Utilities.ToQueryString(new Dictionary<string, string?>
47+
{
48+
{ "taskID", markParameters.TaskId.ToString() },
49+
{ "realID", markParameters.RealId.ToString() },
50+
{ "authCode", null }
51+
}),
52+
Encoding.UTF8, "application/x-www-form-urlencoded");
53+
54+
Registry.Registry.GetProgress("1").Update("Authenticating...");
55+
var response = await client.PostAsync("https://app.myimaths.com/api/legacy/auth", request);
56+
Utilities.Utilities.UpdateCookie(response);
57+
58+
string content = await response.Content.ReadAsStringAsync();
59+
markParameters = markParameters with { AuthToken = HttpUtility.ParseQueryString(content)["authToken"] };
60+
61+
client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
62+
request = new StringContent(Utilities.Utilities.ToQueryString(new Dictionary<string, string?>
63+
{
64+
{ "taskID", markParameters.TaskId.ToString() },
65+
{ "realID", markParameters.RealId.ToString() }
66+
}));
67+
68+
Registry.Registry.GetProgress("1").Update("Updating Cookie...");
69+
Utilities.Utilities.UpdateCookie(await client.PostAsync("https://app.myimaths.com/api/legacy/launch", request));
70+
71+
return markParameters;
72+
}
73+
74+
private static async Task<MarkParameterRecord> GetMarkParameterRecordAsync(int index)
75+
{
76+
var client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
77+
Registry.Registry.NewProgress("1", "Requesting task info...", TaskAmount);
78+
var response =
79+
await client.GetAsync($"https://app.myimaths.com{Registry.Registry.TaskInfoRecordsList[index].Href}");
80+
Utilities.Utilities.UpdateCookie(response);
81+
82+
var doc = new HtmlDocument();
83+
doc.LoadHtml(await response.Content.ReadAsStringAsync());
84+
85+
string? src =
86+
doc.DocumentNode.SelectSingleNode("//embed/@src").GetAttributeValue("src", string.Empty);
87+
88+
Registry.Registry.GetProgress("1").Update("Parsing task info...");
89+
return await MarkParameterRecord.ParseFromPlayerAsync(src);
90+
}
91+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.Text;
2+
using System.Web;
3+
using HtmlAgilityPack;
4+
using SaveMyMyimaths.Records;
5+
6+
namespace SaveMyMyimaths;
7+
8+
public static class LoginHandler
9+
{
10+
private static string _csrf = "";
11+
private static readonly int TaskAmount = 6;
12+
private static AccountInfoRecord _accountInfo = null!;
13+
14+
public static async Task Login(AccountInfoRecord account)
15+
{
16+
_accountInfo = account;
17+
18+
await SchoolLoginAsync(account.SchoolUsername, account.SchoolPassword);
19+
await PortalLoginAsync(account.PortalUsername, account.PortalPassword);
20+
}
21+
22+
private static async Task SchoolLoginAsync(string username, string password)
23+
{
24+
var client = new HttpClient();
25+
var request = new HttpRequestMessage(HttpMethod.Post, "https://login.myimaths.com/login");
26+
27+
Utilities.Utilities.AddHeaders(ref request);
28+
request.Headers.Add("Referer", "https://login.myimaths.com/login");
29+
request.Headers.Add("Origin", "https://login.myimaths.com");
30+
31+
Registry.Registry.NewProgress("0", "Fetching CSRF token", TaskAmount);
32+
_csrf = await FetchCsrfAsync("https://login.myimaths.com/login", false);
33+
34+
string requestString =
35+
"utf8=%E2%9C%93&authenticity_token=" + HttpUtility.UrlEncode(_csrf, Encoding.UTF8) +
36+
"&_form_generated_at=" +
37+
HttpUtility.UrlEncode(DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz"), Encoding.UTF8) +
38+
"&account%5Buser_name%5D=" + HttpUtility.UrlEncode(username, Encoding.UTF8) +
39+
"&account%5Bpassword%5D=" + HttpUtility.UrlEncode(password, Encoding.UTF8) + "&commit=Log+in";
40+
41+
request.Content = new StringContent(requestString, Encoding.UTF8, "application/x-www-form-urlencoded");
42+
43+
Registry.Registry.GetProgress("0").Update("Logging in to Myimaths...");
44+
var response = await client.SendAsync(request);
45+
Utilities.Utilities.UpdateCookie(response);
46+
47+
Registry.Registry.GetProgress("0").Update("Updating Cookie...");
48+
client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
49+
response = await client.GetAsync("https://app.myimaths.com/myportal/library/39?login_modal=true");
50+
Utilities.Utilities.UpdateCookie(response);
51+
}
52+
53+
54+
private static async Task<string> FetchCsrfAsync(string uri, bool isCookieNeeded)
55+
{
56+
var doc = new HtmlDocument();
57+
var client = isCookieNeeded
58+
? new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container })
59+
: new HttpClient();
60+
61+
var response = await client.GetAsync(uri);
62+
string responseContent = await response.Content.ReadAsStringAsync();
63+
doc.LoadHtml(responseContent);
64+
65+
return doc.DocumentNode.SelectSingleNode("//meta[@name='csrf-token']")
66+
.GetAttributeValue("content", string.Empty);
67+
}
68+
69+
private static async Task PortalLoginAsync(string portalUsername, string portalPassword)
70+
{
71+
var client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
72+
var request = new HttpRequestMessage(HttpMethod.Post, "https://app.myimaths.com/myportal/student/authenticate");
73+
74+
Utilities.Utilities.AddHeaders(ref request);
75+
request.Headers.Add("Referer", "https://app.myimaths.com/myportal/library/39?login_modal=true");
76+
request.Headers.Add("Origin", "https://app.myimaths.com");
77+
78+
Registry.Registry.GetProgress("0").Update("Fetching CSRF token...");
79+
_csrf = await FetchCsrfAsync("https://app.myimaths.com/myportal/library/39", true);
80+
81+
string requestString =
82+
"utf8=%E2%9C%93&authenticity_token=" + HttpUtility.UrlEncode(_csrf, Encoding.UTF8) +
83+
"&student%5Buser_name%5D=" + HttpUtility.UrlEncode(portalUsername, Encoding.UTF8) +
84+
"&student%5Bpassword%5D=" + HttpUtility.UrlEncode(portalPassword, Encoding.UTF8) + "&commit=Log+in";
85+
request.Content = new StringContent(requestString, Encoding.UTF8, "application/x-www-form-urlencoded");
86+
87+
Registry.Registry.GetProgress("0").Update("Logging in to the student portal...");
88+
var response = await client.SendAsync(request);
89+
Utilities.Utilities.UpdateCookie(response);
90+
}
91+
92+
public static async Task FindAllTaskAsync()
93+
{
94+
var client = new HttpClient(new HttpClientHandler { CookieContainer = Registry.Registry.Container });
95+
96+
Registry.Registry.GetProgress("0").Update("Fetching unfinished tasks...");
97+
var response = await client.GetAsync("https://app.myimaths.com/myportal/student/my_homework");
98+
Utilities.Utilities.UpdateCookie(response);
99+
100+
Registry.Registry.GetProgress("0").Update("Finished.");
101+
102+
string responseContent = await response.Content.ReadAsStringAsync();
103+
104+
var doc = new HtmlDocument();
105+
doc.LoadHtml(responseContent);
106+
107+
var hrefs = doc.DocumentNode.SelectNodes("//a[@class='primary btn btn-m']");
108+
var infos = doc.DocumentNode.SelectNodes("//h2[@class='accordion-header']/button");
109+
110+
string? studentName = doc.DocumentNode
111+
.SelectSingleNode("//div[@class='student-name d-flex align-items-center']/div[not(@*)]")
112+
.InnerText;
113+
Registry.Registry.Accounts.TryAdd(studentName, _accountInfo);
114+
Registry.Registry.DumpAccountInfoToFile();
115+
116+
if (hrefs == null) return;
117+
//I know this is extremely not elegant, but man, I know nothing about algorithms and please forgive me.
118+
for (int i = 0; i < hrefs.Count; i++)
119+
{
120+
string? href = hrefs[i].GetAttributeValue("href", string.Empty);
121+
string name = infos[i].InnerText.Trim().Split("\n\n\n\n")[0];
122+
string dueDayInfo = infos[i].InnerText.Trim().Split("\n\n\n\n")[1];
123+
124+
Registry.Registry.TaskInfoRecordsList.Add(new TaskInfoRecord(href, name, dueDayInfo));
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)