-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStJohnsHttpClient.java
239 lines (205 loc) · 8.43 KB
/
StJohnsHttpClient.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
package org.hydev.veracross.sdk;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.hydev.veracross.sdk.exceptions.VeracrossException;
import org.hydev.veracross.sdk.model.StJohnsCourseDescription;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* HTTP Client for the veracross sdk specific to SJP.
* <p>
* Class created by the HyDEV Team on 2019-08-19!
*
* @author HyDEV Team (https://github.com/HyDevelop)
* @author Hykilpikonna (https://github.com/hykilpikonna)
* @author Vanilla (https://github.com/VergeDX)
* @since 2019-08-19 13:45
*/
public class StJohnsHttpClient extends GeneralHttpClient
{
private static final Pattern SSO_USERNAME_PATTERN = Pattern.compile("(?<=name=\"username\" value=\").*(?=\">)");
private static final Pattern SSO_TOKEN_PATTERN = Pattern.compile("(?<=name=\"token\" value=\").*(?=\">)");
private String username;
/**
* Get the session's authenticity token
*
* @return CSRF token
*/
public String getCsrf() throws IOException
{
// Exmaple response: <input name="authenticity_token" type="hidden" value="oLeYfaLYmQDScdhx9fR5jpgvyjBXDCC36NTvfIjkBkgrsyCxA+KO71Du9n1MvJqNbjRK1R+HCl4OlmGlrpqRSg==">
String response = getBody("https://www.stjohnsprep.org/fs/sessions/user/csrf-token");
// Example CSRF Token: oLeYfaLYmQDScdhx9fR5jpgvyjBXDCC36NTvfIjkBkgrsyCxA+KO71Du9n1MvJqNbjRK1R+HCl4OlmGlrpqRSg==
return response.substring(response.indexOf("value=\"") + 7, response.indexOf("\">"));
}
/**
* Login and save the session
*/
public void login(String username, String password) throws IOException, VeracrossException
{
// Keep the username
this.username = username;
// Post request
CloseableHttpResponse response = postForm("https://www.stjohnsprep.org/fs/auth/finalsite/callback", null,
"username", username,
"password", password,
"protected_page", "false",
"authenticity_token", getCsrf());
// Get response
int status = response.getStatusLine().getStatusCode();
String responseText = getBody(response);
// Close it
response.close();
// Unknown http problem
if (status != 200 && status != 301 && status != 302)
{
throw new VeracrossException("Login Failed: HTTP Connection Problem, status code: " + status);
}
// Invalid password
if (responseText.contains("<div class=\"fsLoginMessage\">Invalid username or password. Please try again.</div><br>"))
{
throw new VeracrossException("Login Failed: Invalid username or password.");
}
}
/**
* Get the veracross single sign on token.
*
* @return SSO Token string
*/
public String getVeracrossSSOToken() throws VeracrossException
{
// Create request
HttpGet get = new HttpGet("https://www.stjohnsprep.org/fs/sso/?type=Veracross-SSO");
try
{
// Send it
CloseableHttpResponse response = httpClient.execute(get);
// Get text
String responseText = EntityUtils.toString(response.getEntity(), "UTF-8");
// Match text
Matcher matcher = SSO_TOKEN_PATTERN.matcher(responseText);
if (!matcher.find())
{
// There's not much to do on runtime.
throw new RuntimeException("SSO Login Failed: Unsupported response: " + responseText);
}
// Return result
return matcher.group();
}
catch (IOException e)
{
// There is not much to do.
throw new VeracrossException("SSO Login Failed: Failed to obtain token", e);
}
}
/**
* Login to Veracross via the single sign on interface.
*
* @return Veracross http client
*/
public VeracrossHttpClient veracrossLoginSSO() throws IOException, VeracrossException
{
// Create veracross client
VeracrossHttpClient client = new VeracrossHttpClient();
// Obtain token and login with it
client.loginSJP(username, getVeracrossSSOToken());
return client;
}
/**
* Get course descriptions
* Eg. https://www.stjohnsprep.org/page.cfm?p=9248
*
* @return Descriptions of all courses
*/
public List<StJohnsCourseDescription> getCourseDescriptions()
{
// Collect data for those urls
final String baseUrl = "https://www.stjohnsprep.org/page.cfm?p=";
final int[] urlCodes = {9246, 9247, 9248, 9249, 9250, 9251, 9252, 9253, 9254};
// Declare results
List<StJohnsCourseDescription> result = new ArrayList<>();
// Loop through them
for (int urlCode : urlCodes)
{
// Combine to form final url
String url = baseUrl + urlCode;
try
{
// Parse html
Document doc = Jsoup.parse(getBody(url));
// Get courses
Elements elements = doc.select("div.contentElementDesc");
// Loop through them
for (Element course : elements)
{
// Get title
Element titleElement = course.selectFirst("h5");
String title = titleElement != null ? titleElement.text() : course.selectFirst("p").text();
// Get other stuff from title
String[] split = title.split(" - ");
if (split.length == 1) split = title.split("-");
if (split.length == 1) split = title.split(" – "); // En dash
if (split.length == 1) split = title.split("–");
if (split.length == 1 && split[0].contains(" Honors"))
{
split = title.split(" Honors");
split[1] = "Honors" + split[1];
}
if (split.length == 1 && split[0].contains("AP"))
{
split = title.split(" \\[");
if (split.length == 1) split = new String[]{split[0], ""};
split[1] = "AP [" + split[1];
}
if (split.length == 1)
{
split = title.split(" \\[");
if (split.length == 1) split = new String[]{split[0], ""};
split[1] = "Unknown [" + split[1];
}
// Continue splitting
String name = split[0];
split = split[1].split(" \\[");
String level = split[0];
String credit = split.length == 1 ? "Unknown" : split[1].split(" ")[0];
// Combine paragraphs to get description
StringBuilder description = new StringBuilder();
String prerequisites = "None";
Elements paragraphs = course.select("p");
// Loop through paragraphs
for (Element paragraph : paragraphs)
{
// Get text
String text = paragraph.text();
// See if text is prerequisites
if (text.startsWith("Prerequisite") || text.startsWith("Prerequisites"))
{
prerequisites = text.replaceFirst("Prerequisite: ", "").replaceFirst("Prerequisites: ", "");
}
else
{
description.append(text).append("\n");
}
}
// Add to result
result.add(new StJohnsCourseDescription(title, name, level, credit,
description.toString(), prerequisites));
}
}
catch (IOException e)
{
// Error in one page doesn't mean every page would fail.
e.printStackTrace();
}
}
return result;
}
}