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 TypeClassDescriptionclass
class
private class
class
ATask
that can be executed in a differentThread
to log in to Friedolin using the student's credentials specified in theConfiguration
previously 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 ofasi
must be updated with the currenturlSecretParameter
.private HttpClient
The HTTP client to use for sending requests to Friedolin.private @NonNull Configuration
Various 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 HTTPClient
is 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.Login
private String
A 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.Builder
addHeaders
(HttpRequest.Builder builder) Adds the default headers to the givenHttpRequest.Builder
, namely:Accept
Accept-Encoding
Accept-Language
Cache-Control
Content-Type
DNT
Origin
Sec-Fetch-Dest
Sec-Fetch-Mode
Sec-Fetch-Site
Sec-Fetch-User
Sec-GPC
Upgrade-Insecure-Requests
User-Agent
Determines whether and how theclient
can access the internet.private boolean
downloadFile
(@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.boolean
fetchGrades
(@NonNull String... degrees) Fetches the student's grades from the University of Jena's Friedolin system, using the credentials specified in theConfiguration
previously set viaFriedolinClient.setConfiguration(Configuration)
(or the constructor).boolean
Deprecated.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.boolean
Deprecated.void
finish()
Exits the headless browser.private @NonNull HttpResponse
<@NonNull String> Sends aGET
request toFriedolyn.REQUEST_URL
with the given headers.private @NonNull HttpResponse
<@NonNull String> get
(@NonNull Map<@NonNull String, @NonNull String> urlParameters, @NonNull Map<@NonNull String, @NonNull String> headers) Sends aGET
request toFriedolyn.REQUEST_URL
with the given parameters and headers.@NonNull Configuration
@NonNull Client.FetchClearname
@NonNull Client.FetchEmailAddress
@NonNull Client.Login
private boolean
Makes an initialGET
request 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 aPOST
request toFriedolyn.REQUEST_URL
with 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.void
setConfiguration
(@NonNull Configuration configuration) Updates the currentconfiguration
with a deep copy of the given one (not the actual reference of it, for security reasons).void
setConfigurationReference
(@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 boolean
updateCookies
(@NonNull URI uri, @NonNull HttpHeaders headers) Makes theclient
remember 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
ATask
that can be run in a differentThread
to 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 ofasi
must 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.
asi
must 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 ofasi
must 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 ofasi
must 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 ofasi
must 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
NonNull
annotation should be removed, because it does not understand that the (only) constructor callssetConfiguration(Configuration)
to initialise this field. The use ofNonNull
is 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:
getConfiguration
in 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 currentconfiguration
with a deep copy of the given one (not the actual reference of it, for security reasons).- Specified by:
setConfiguration
in 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:
setConfigurationReference
in classFriedolinClient
- Parameters:
configuration
- The new configuration to use.- See Also:
-
initialise
private boolean initialise()Makes an initialGET
request to Friedolin to retrieve the initial cookies and headers needed for logging in.- Returns:
true
if the request was successful,false
otherwise
-
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:
finish
in classFriedolinClient
-
getLoginTask
- Specified by:
getLoginTask
in classFriedolinClient
- Returns:
- A
Task
that can be executed in a differentThread
to log in to Friedolin.
-
fetchGrades
Fetches the student's grades from the University of Jena's Friedolin system, using the credentials specified in theConfiguration
previously set viaFriedolinClient.setConfiguration(Configuration)
(or the constructor).- Specified by:
fetchGrades
in classFriedolinClient
- Parameters:
degrees
- The academic degrees to fetch the grades for. If none are specified, all degrees present ininvalid reference
Configuration#getAcademicDegrees()
- Returns:
true
if the grades were fetched successfully,false
otherwise.- Throws:
IllegalArgumentException
- If any of the given degrees is not present in the configuration.
-
getFetchClearnameTask
- Specified by:
getFetchClearnameTask
in classFriedolinClient
- Returns:
- A
Task
that can be executed in a differentThread
to fetch the student's real name (e.g.Edward Snowden
) from the University of Jena's Friedolin system.
-
getFetchEmailAddressTask
- Specified by:
getFetchEmailAddressTask
in classFriedolinClient
- Returns:
- A
Task
that can be executed in a differentThread
to fetch the student's email address (e.g.edward.snowden@uni-jena.de
).
-
checkInternetConnectivity
Determines whether and how theclient
can access the internet.- Specified by:
checkInternetConnectivity
in 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.net
of 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:
true
if the study progress was successfully fetched,false
otherwise
-
fetchMyData
Deprecated.Tests whether internal pages can be fetched at all by trying to get the student's personal data.- Returns:
true
if the personal data was successfully fetched,false
otherwise
-
get
@NonNull private @NonNull HttpResponse<@NonNull String> get(@NonNull @NonNull Map<@NonNull String, @NonNull String> headers) throws IOException, InterruptedException, IllegalArgumentException, SecurityExceptionSends aGET
request toFriedolyn.REQUEST_URL
with 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 aGET
request toFriedolyn.REQUEST_URL
with the given parameters and headers.- Parameters:
urlParameters
- The query to append to the URL. If theMap
includes 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 aPOST
request toFriedolyn.REQUEST_URL
with the given parameters and headers.- Parameters:
urlParameters
- The query to append to the URL. If theMap
includes 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 aGET
or aPOST
request.urlParameters
- The query to append to the URL. If theMap
includes 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.GET
requests.- 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 theMap
includes 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:
true
if the file was successfully downloaded,false
otherwise- Throws:
IllegalArgumentException
- If the file could not be fetched and saved.IllegalStateException
- If theclient
isnull
.
-
updateCookies
Makes theclient
remember 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 theHttpResponse
that contained the cookies.- Returns:
true
if the cookies were successfully saved,false
otherwise
-
addHeaders
Adds the default headers to the givenHttpRequest.Builder
, namely:Accept
Accept-Encoding
Accept-Language
Cache-Control
Content-Type
DNT
Origin
Sec-Fetch-Dest
Sec-Fetch-Mode
Sec-Fetch-Site
Sec-Fetch-User
Sec-GPC
Upgrade-Insecure-Requests
User-Agent
- Parameters:
builder
- TheHttpRequest.Builder
to add the headers to.- Returns:
- The same
HttpRequest.Builder
with the headers added.
-