java.lang.Object
page.codeberg.friedolyn.client.FriedolinClient
page.codeberg.friedolyn.client.Client
A resource-efficient client to automatically interact with the University of Jena's Friedolin system.
Does not use a browser, but instead sends HTTP requests directly to the server.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionclassclassprivate classclassATaskthat can be executed in a differentThreadto log in to Friedolin using the student's credentials specified in theConfigurationpreviously set viaFriedolinClient.setConfiguration(Configuration)(or the constructor).Nested classes/interfaces inherited from class page.codeberg.friedolyn.client.FriedolinClient
FriedolinClient.HTTP_REQUEST_TYPE, FriedolinClient.InternetConnectivityStatus -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters to send with the requests to accept the obligation of use and fetch the grades table. The value ofasimust be updated with the currenturlSecretParameter.private HttpClientThe HTTP client to use for sending requests to Friedolin.private @NonNull ConfigurationVarious options that modify Friedolyn's behaviour.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters to send with the request to retrieve the list of all courses (Studiengänge) the student is enrolled in before the grades can be fetched.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters to send with the request to retrieve the student's e-mail address.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters for the referrer to use when retrieving the student's e-mail address.static final @NonNull LinkedHashMap<ExamsPDF, @NonNull LinkedHashMap<@NonNull String, @NonNull String>> The parameters to send with the request to retrieve the differentgrade tables as PDFs.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters to send with the request to retrieve the obligation-of-use page.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters for the referrer to use when retrieving the obligation-of-use page.Whether this HTTPClientis currently logged in at the University of Jena's Friedolin system.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The parameters to send with the login request to Friedolin.static final @NonNull LinkedHashMap<@NonNull String, @NonNull String> The referrer to use when sending the login request to Friedolin.private @NonNull Client.Loginprivate StringA secret that is included in all internal Friedolin URLs and is newly generated for each session.Fields inherited from class page.codeberg.friedolyn.client.FriedolinClient
SESSION_LIFETIME -
Constructor Summary
ConstructorsConstructorDescriptionClient(@NonNull Configuration configuration) Creates a new client that can be used immediately without further configuration or initialisation. -
Method Summary
Modifier and TypeMethodDescriptionprivate @NonNull HttpResponse<@NonNull String> Before students can access their grades, they have to accept the "Obligation of Use", i.e.private HttpRequest.BuilderaddHeaders(HttpRequest.Builder builder) Adds the default headers to the givenHttpRequest.Builder, namely:AcceptAccept-EncodingAccept-LanguageCache-ControlContent-TypeDNTOriginSec-Fetch-DestSec-Fetch-ModeSec-Fetch-SiteSec-Fetch-UserSec-GPCUpgrade-Insecure-RequestsUser-AgentDetermines whether and how theclientcan access the internet.private booleandownloadFile(@NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull Map<@NonNull String, @NonNull String> headers, @NonNull File downloadTarget) Retrieves some file from the Friedolin server and saves it in the specified location.booleanfetchGrades(@NonNull String... degrees) Fetches the student's grades from the University of Jena's Friedolin system, using the credentials specified in theConfigurationpreviously set viaFriedolinClient.setConfiguration(Configuration)(or the constructor).booleanDeprecated.private @NonNull HttpResponse<@NonNull String> Retrieves the obligation-of-use page from Friedolin, which needs to be accepted before the grade table can be accessed.booleanDeprecated.voidfinish()Exits the headless browser.private @NonNull HttpResponse<@NonNull String> Sends aGETrequest toFriedolyn.REQUEST_URLwith the given headers.private @NonNull HttpResponse<@NonNull String> get(@NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull Map<@NonNull String, @NonNull String> headers) Sends aGETrequest toFriedolyn.REQUEST_URLwith the given parameters and headers.@NonNull Configuration@NonNull Client.FetchClearname@NonNull Client.FetchEmailAddress@NonNull Client.Loginprivate booleanMakes an initialGETrequest to Friedolin to retrieve the initial cookies and headers needed for logging in.private @NonNull HttpResponse<@NonNull String> post(@NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull Map<@NonNull String, @NonNull String> headers, @NonNull Map<@NonNull String, @NonNull String> body) Sends aPOSTrequest toFriedolyn.REQUEST_URLwith the given parameters and headers.private @NonNull HttpResponse<@NonNull String> request(FriedolinClient.HTTP_REQUEST_TYPE type, @NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull Map<@NonNull String, @NonNull String> headers, @NonNull Map<@NonNull String, @NonNull String> body) Makes an HTTP request to the Friedolin server.voidsetConfiguration(@NonNull Configuration configuration) Updates the currentconfigurationwith a deep copy of the given one (not the actual reference of it, for security reasons).voidsetConfigurationReference(@NonNull Configuration configuration) Updates the preferences that determine the behaviour of this client with the exact reference of the givenConfiguration(instead of just a deep copy).private booleanupdateCookies(@NonNull URI uri, @NonNull HttpHeaders headers) Makes theclientremember the cookies received from the server in the given headers.Methods inherited from class page.codeberg.friedolyn.client.FriedolinClient
buildURL, decodeQuery, encodeParameters, fetchEmailAddress, fetchStudentClearname, getIsLoggedIn, login, saveResponse, stripAnchor
-
Field Details
-
loginTask
ATaskthat can be run in a differentThreadto log in to Friedolin. The execution may take a while, so it is recommended to use this task instead of the blockingFriedolinClient.login()method. -
LOGIN_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> LOGIN_PARAMETERSThe parameters to send with the login request to Friedolin. -
LOGIN_REFERRER
The referrer to use when sending the login request to Friedolin. -
GET_OBLIGATION_OF_USE_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> GET_OBLIGATION_OF_USE_PARAMETERSThe parameters to send with the request to retrieve the obligation-of-use page. The value ofasimust be updated with the currenturlSecretParameter. -
GET_OBLIGATION_OF_USE_REFERRER_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> GET_OBLIGATION_OF_USE_REFERRER_PARAMETERSThe parameters for the referrer to use when retrieving the obligation-of-use page. -
ACCEPT_OBLIGATION_OF_USE_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> ACCEPT_OBLIGATION_OF_USE_PARAMETERSThe parameters to send with the requests to- accept the obligation of use and
- fetch the grades table.
asimust be updated with the currenturlSecretParameter. -
GET_COURSE_LIST_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> GET_COURSE_LIST_PARAMETERSThe parameters to send with the request to retrieve the list of all courses (Studiengänge) the student is enrolled in before the grades can be fetched. The value ofasimust be updated with the currenturlSecretParameter. -
GET_GRADES_TABLE_REFERRER_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> GET_GRADES_TABLE_REFERRER_PARAMETERS -
GET_EMAIL_ADDRESS_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> GET_EMAIL_ADDRESS_PARAMETERSThe parameters to send with the request to retrieve the student's e-mail address. The value ofasimust be updated with the currenturlSecretParameter. -
GET_EMAIL_ADDRESS_REFERRER_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<@NonNull String,@NonNull String> GET_EMAIL_ADDRESS_REFERRER_PARAMETERSThe parameters for the referrer to use when retrieving the student's e-mail address. -
GET_EXAMS_PDF_PARAMETERS
@NonNull public static final @NonNull LinkedHashMap<ExamsPDF,@NonNull LinkedHashMap<@NonNull String, GET_EXAMS_PDF_PARAMETERS@NonNull String>> The parameters to send with the request to retrieve the differentgrade tables as PDFs. For each PDF, the value ofasimust be updated with the currenturlSecretParameter. -
urlSecretParameter
A secret that is included in all internal Friedolin URLs and is newly generated for each session. Without this secret, it is not possible to access the user's data. -
configuration
Various options that modify Friedolyn's behaviour.- Implementation Note:
- IntelliJ shows a warning that the
NonNullannotation should be removed, because it does not understand that the (only) constructor callssetConfiguration(Configuration)to initialise this field. The use ofNonNullis therefore entirely justified, and the warning can be safely ignored.
-
isLoggedIn
-
client
The HTTP client to use for sending requests to Friedolin.
-
-
Constructor Details
-
Client
Creates a new client that can be used immediately without further configuration or initialisation.- Parameters:
configuration- The preferences that determine the behaviour of this client. The exact reference of this object is stored, so that changes to it are reflected in this client. If this is not desired, callnew Client(configuration.copy())instead ofnew Client(configuration).
-
-
Method Details
-
getConfiguration
- Specified by:
getConfigurationin classFriedolinClient- Returns:
- A deep copy of the preferences that determine the behaviour of this client (not the actual reference, for security reasons).
-
setConfiguration
Updates the currentconfigurationwith a deep copy of the given one (not the actual reference of it, for security reasons).- Specified by:
setConfigurationin classFriedolinClient- Parameters:
configuration- The new configuration to use.- See Also:
-
setConfigurationReference
Updates the preferences that determine the behaviour of this client with the exact reference of the givenConfiguration(instead of just a deep copy).- Specified by:
setConfigurationReferencein classFriedolinClient- Parameters:
configuration- The new configuration to use.- See Also:
-
initialise
private boolean initialise()Makes an initialGETrequest to Friedolin to retrieve the initial cookies and headers needed for logging in.- Returns:
trueif the request was successful,falseotherwise
-
finish
public void finish()Exits the headless browser. This method should be called when the headless browser is no longer needed but the application is still running, in order not to waste resources longer than necessary. Yes, Java has a garbage collector, but there may be situations where the parent of this object is still in use but does not need the headless browser anymore.- Specified by:
finishin classFriedolinClient
-
getLoginTask
- Specified by:
getLoginTaskin classFriedolinClient- Returns:
- A
Taskthat can be executed in a differentThreadto log in to Friedolin.
-
fetchGrades
Fetches the student's grades from the University of Jena's Friedolin system, using the credentials specified in theConfigurationpreviously set viaFriedolinClient.setConfiguration(Configuration)(or the constructor).- Specified by:
fetchGradesin classFriedolinClient- Parameters:
degrees- The academic degrees to fetch the grades for. If none are specified, all degrees present inwill be fetched.invalid reference
Configuration#getAcademicDegrees()- Returns:
trueif the grades were fetched successfully,falseotherwise.- Throws:
IllegalArgumentException- If any of the given degrees is not present in the configuration.
-
getFetchClearnameTask
- Specified by:
getFetchClearnameTaskin classFriedolinClient- Returns:
- A
Taskthat can be executed in a differentThreadto fetch the student's real name (e.g.Edward Snowden) from the University of Jena's Friedolin system.
-
getFetchEmailAddressTask
- Specified by:
getFetchEmailAddressTaskin classFriedolinClient- Returns:
- A
Taskthat can be executed in a differentThreadto fetch the student's email address (e.g.edward.snowden@uni-jena.de).
-
checkInternetConnectivity
Determines whether and how theclientcan access the internet.- Specified by:
checkInternetConnectivityin classFriedolinClient- Returns:
- The status of the internet connectivity.
- See Also:
- Implementation Note:
- In order to rule out DNS issues, we
first try to ping 199.7.83.42
(i.e.
l.root-servers.netof ICANN). Then, we connect to codeberg.org to take DNS into consideration.
-
acceptObligationOfUse
@NonNull private @NonNull HttpResponse<@NonNull String> acceptObligationOfUse() throws IllegalStateException, IOException, InterruptedException, IllegalArgumentException, SecurityExceptionBefore students can access their grades, they have to accept the "Obligation of Use", i.e. Friedolin's terms of service. This method accepts the obligation of use, by "clicking" the "Accept" checkbox.- Returns:
- The response from the server to the request, which is a list of all courses (Studiengänge) the student is enrolled in.
- Throws:
IllegalStateException- Ifinitialise()has not been called yet.IOException- Seepost(Map, Map, Map).InterruptedException- Seepost(Map, Map, Map).IllegalArgumentException- Seepost(Map, Map, Map).SecurityException- Seepost(Map, Map, Map).
-
fetchObligationOfUse
@NonNull private @NonNull HttpResponse<@NonNull String> fetchObligationOfUse() throws IOException, InterruptedException, IllegalArgumentException, SecurityExceptionRetrieves the obligation-of-use page from Friedolin, which needs to be accepted before the grade table can be accessed. The obligation of use is basically Friedolin's terms of service, which state that the student is obliged to check Friedolin every two weeks for new grades.- Returns:
- The response from the server to the request, which is the obligation-of-use page.
- Throws:
IOException- Seeget(Map, Map).InterruptedException- Seeget(Map, Map).IllegalArgumentException- Seeget(Map, Map).SecurityException- Seeget(Map, Map).
-
fetchStudyProgress
Deprecated.Tests whether internal pages can be fetched at all by trying to get the student's study progress.- Returns:
trueif the study progress was successfully fetched,falseotherwise
-
fetchMyData
Deprecated.Tests whether internal pages can be fetched at all by trying to get the student's personal data.- Returns:
trueif the personal data was successfully fetched,falseotherwise
-
get
@NonNull private @NonNull HttpResponse<@NonNull String> get(@NonNull @NonNull Map<@NonNull String, @NonNull String> headers) throws IOException, InterruptedException, IllegalArgumentException, SecurityExceptionSends aGETrequest toFriedolyn.REQUEST_URLwith the given headers.- Parameters:
headers- Custom headers additionally to the default headers. (SeeaddHeaders(HttpRequest.Builder))- Returns:
- The response from the server to the request.
- Throws:
IOException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).InterruptedException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).IllegalArgumentException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).SecurityException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).
-
get
@NonNull private @NonNull HttpResponse<@NonNull String> get(@NonNull @NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull @NonNull Map<@NonNull String, throws IllegalStateException, IOException, InterruptedException, IllegalArgumentException, SecurityException@NonNull String> headers) Sends aGETrequest toFriedolyn.REQUEST_URLwith the given parameters and headers.- Parameters:
urlParameters- The query to append to the URL. If theMapincludes a key namedasi, its value will be replaced with the currenturlSecretParameter.headers- Custom headers additionally to the default headers. (seeaddHeaders(HttpRequest.Builder))- Returns:
- The response from the server to the request.
- Throws:
IllegalStateException- Ifinitialise()has not been called yet.IOException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).InterruptedException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).IllegalArgumentException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).SecurityException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).
-
post
@NonNull private @NonNull HttpResponse<@NonNull String> post(@NonNull @NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull @NonNull Map<@NonNull String, throws IllegalStateException, IOException, InterruptedException, IllegalArgumentException, SecurityException@NonNull String> headers, @NonNull @NonNull Map<@NonNull String, @NonNull String> body) Sends aPOSTrequest toFriedolyn.REQUEST_URLwith the given parameters and headers.- Parameters:
urlParameters- The query to append to the URL. If theMapincludes a key namedasi, its value will be replaced with the currenturlSecretParameter.headers- Custom headers additionally to the default headers. (seeaddHeaders(HttpRequest.Builder))body- The body of the request, i.e. form data.- Returns:
- The response from the server to the request.
- Throws:
IllegalStateException- Ifinitialise()has not been called yet.IOException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).InterruptedException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).IllegalArgumentException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).SecurityException- Seerequest(FriedolinClient.HTTP_REQUEST_TYPE, Map, Map, Map).
-
request
@NonNull private @NonNull HttpResponse<@NonNull String> request(@NonNull FriedolinClient.HTTP_REQUEST_TYPE type, @NonNull @NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull @NonNull Map<@NonNull String, throws IOException, InterruptedException, IllegalArgumentException, SecurityException, IllegalStateException@NonNull String> headers, @NonNull @NonNull Map<@NonNull String, @NonNull String> body) Makes an HTTP request to the Friedolin server.- Parameters:
type- Whether it's aGETor aPOSTrequest.urlParameters- The query to append to the URL. If theMapincludes a key namedasi, its value will be replaced with the currenturlSecretParameter.headers- Custom headers additionally to the default headers. (seeaddHeaders(HttpRequest.Builder))body- The body of the request, i.e. form data. Is ignored forFriedolinClient.HTTP_REQUEST_TYPE.GETrequests.- Returns:
- The response from the server to the request.
- Throws:
IllegalStateException- Ifinitialise()has not been called yet.IOException- SeeHttpClient.send(HttpRequest, HttpResponse.BodyHandler).InterruptedException- SeeHttpClient.send(HttpRequest, HttpResponse.BodyHandler).IllegalArgumentException- SeeHttpClient.send(HttpRequest, HttpResponse.BodyHandler).SecurityException- SeeHttpClient.send(HttpRequest, HttpResponse.BodyHandler).
-
downloadFile
private boolean downloadFile(@NonNull @NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull @NonNull Map<@NonNull String, throws IllegalArgumentException, IllegalStateException@NonNull String> headers, @NonNull @NonNull File downloadTarget) Retrieves some file from the Friedolin server and saves it in the specified location.- Parameters:
urlParameters- The query to append to theFriedolyn.REQUEST_URL. If theMapincludes a key namedasi, its value will be replaced with the currenturlSecretParameter.headers- Custom headers additionally to the default headers. (seeaddHeaders(HttpRequest.Builder))downloadTarget- The path where the file should be saved, including the file name. The file must not exist, but the directory must exist.- Returns:
trueif the file was successfully downloaded,falseotherwise- Throws:
IllegalArgumentException- If the file could not be fetched and saved.IllegalStateException- If theclientisnull.
-
updateCookies
Makes theclientremember the cookies received from the server in the given headers.- Parameters:
uri- The URI of the server that sent the cookies.headers- The headers of theHttpResponsethat contained the cookies.- Returns:
trueif the cookies were successfully saved,falseotherwise
-
addHeaders
Adds the default headers to the givenHttpRequest.Builder, namely:AcceptAccept-EncodingAccept-LanguageCache-ControlContent-TypeDNTOriginSec-Fetch-DestSec-Fetch-ModeSec-Fetch-SiteSec-Fetch-UserSec-GPCUpgrade-Insecure-RequestsUser-Agent
- Parameters:
builder- TheHttpRequest.Builderto add the headers to.- Returns:
- The same
HttpRequest.Builderwith the headers added.
-