Add missing V-Token headers to eduOne requests during registration

This commit is contained in:
Mikołaj Pich 2024-05-12 13:48:19 +02:00
parent f50690a95a
commit c1e40d8538
No known key found for this signature in database
5 changed files with 46 additions and 24 deletions

View file

@ -128,7 +128,7 @@ internal val ApiEndpointsMap = mapOf(
"ZgloszoneNieobecnosci" to "5c63a985-2149-4e7b-a30f-3692b16b69e3",
),
"uonetplus-uczenplus" to mapOf(
"Context" to "Context",
"Context" to "308f5f36-16cb-45c8-8a43-1e038de2b30a",
"AutoryzacjaPesel" to "AutoryzacjaPesel",
"Frekwencja" to "Frekwencja",
"Usprawiedliwienia" to "Usprawiedliwienia",
@ -147,7 +147,7 @@ internal val ApiEndpointsMap = mapOf(
"Informacje" to "Informacje",
"DaneUcznia" to "DaneUcznia",
"UczenZdjecie" to "UczenZdjecie",
"OkresyKlasyfikacyjne" to "OkresyKlasyfikacyjne",
"OkresyKlasyfikacyjne" to "c4ef1a36-b928-428f-8a9e-184ea0185c2f",
"Oceny" to "Oceny",
),
"uonetplus-wiadomosciplus" to mapOf(
@ -169,6 +169,10 @@ internal val ApiEndpointsMap = mapOf(
internal val ApiEndpointsVTokenMap = mapOf(
"24.04.0003.58698" to mapOf(
"uonetplus-uczenplus" to mapOf(
"Context" to "e89f6a8e-bc6b-403b-a23d-2a807512d3bd",
"OkresyKlasyfikacyjne" to "1ff9466c-2ebb-4649-9563-b005aab2a92a",
),
"uonetplus-wiadomosciplus" to mapOf(
"Skrzynki" to "7d4b1844-d114-40e3-a565-696564703b38",
"Odebrane" to "a94f324b-0ab8-43eb-830e-814d4a0b4aca",

View file

@ -227,17 +227,33 @@ internal fun getPathIndexByModuleHost(moduleHost: String): Int = when (moduleHos
else -> -1
}
internal fun getModuleHeadersFromDocument(htmlContent: String): ModuleHeaders {
return ModuleHeaders(
token = getScriptParam("antiForgeryToken", htmlContent),
appGuid = getScriptParam("appGuid", htmlContent),
appVersion = getScriptParam("version", htmlContent).ifBlank {
getScriptParam("appVersion", htmlContent)
},
email = getScriptParam("name", htmlContent),
symbol = getScriptParam("appCustomerDb", htmlContent),
)
}
internal fun Request.Builder.attachVToken(moduleHost: String, url: HttpUrl, headers: ModuleHeaders?): Request.Builder {
val vToken = url.getMatchedVToken(moduleHost, headers) ?: return this
addHeader("V-Token", vToken)
return this
}
internal fun HttpUrl.getMatchedVToken(moduleHost: String, headers: ModuleHeaders?): String? {
val pathSegmentIndex = getPathIndexByModuleHost(moduleHost)
val pathKey = url.pathSegments.getOrNull(pathSegmentIndex)
val pathKey = pathSegments.getOrNull(pathSegmentIndex)
val mappedUuid = Scrapper.vTokenMap[headers?.appVersion]
?.get(moduleHost)
?.get(pathKey)
?: return this
?: return null
val vToken = getVToken(mappedUuid, headers) ?: return this
addHeader("V-Token", vToken)
return this
return getVToken(mappedUuid, headers)
}
private fun getVToken(uuid: String, headers: ModuleHeaders?): String? {

View file

@ -11,7 +11,7 @@ import io.github.wulkanowy.sdk.scrapper.Scrapper.LoginType.ADFSLightScoped
import io.github.wulkanowy.sdk.scrapper.Scrapper.LoginType.STANDARD
import io.github.wulkanowy.sdk.scrapper.attachVToken
import io.github.wulkanowy.sdk.scrapper.exception.VulcanClientError
import io.github.wulkanowy.sdk.scrapper.getScriptParam
import io.github.wulkanowy.sdk.scrapper.getModuleHeadersFromDocument
import io.github.wulkanowy.sdk.scrapper.login.LoginResult
import io.github.wulkanowy.sdk.scrapper.login.ModuleHeaders
import io.github.wulkanowy.sdk.scrapper.login.NotLoggedInException
@ -140,15 +140,7 @@ internal class AutoLoginInterceptor(
private fun saveModuleHeaders(doc: Document, url: HttpUrl) {
val htmlContent = doc.select("script").html()
val moduleHeaders = ModuleHeaders(
token = getScriptParam("antiForgeryToken", htmlContent),
appGuid = getScriptParam("appGuid", htmlContent),
appVersion = getScriptParam("version", htmlContent).ifBlank {
getScriptParam("appVersion", htmlContent)
},
email = getScriptParam("name", htmlContent),
symbol = getScriptParam("appCustomerDb", htmlContent),
)
val moduleHeaders = getModuleHeadersFromDocument(htmlContent)
if (moduleHeaders.token.isBlank()) {
logger.info("There is no token found on $url")

View file

@ -3,6 +3,8 @@ package io.github.wulkanowy.sdk.scrapper.repository
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.exception.ScrapperException
import io.github.wulkanowy.sdk.scrapper.exception.StudentGraduateException
import io.github.wulkanowy.sdk.scrapper.getMatchedVToken
import io.github.wulkanowy.sdk.scrapper.getModuleHeadersFromDocument
import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
import io.github.wulkanowy.sdk.scrapper.getScriptParam
import io.github.wulkanowy.sdk.scrapper.interceptor.StudentModuleHost
@ -341,23 +343,26 @@ internal class RegisterRepository(
}
private suspend fun getEduOneDiaries(baseStudentPlus: String, homepage: String): List<RegisterStudent> {
val appVersion = getScriptParam("version", homepage).ifBlank {
getScriptParam("appVersion", homepage)
}
val moduleHeaders = getModuleHeadersFromDocument(homepage)
val contextUrl = (baseStudentPlus + "api/Context")
.toHttpUrl()
.mapModuleUrls(StudentPlusModuleHost, appVersion)
.mapModuleUrls(StudentPlusModuleHost, moduleHeaders.appVersion)
val contextVToken = contextUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
val semestersUrl = (baseStudentPlus + "api/OkresyKlasyfikacyjne")
.toHttpUrl()
.mapModuleUrls(StudentModuleHost, appVersion)
.mapModuleUrls(StudentPlusModuleHost, moduleHeaders.appVersion)
val semestersVToken = semestersUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
return studentPlus
.getContextByUrl(url = contextUrl.toString()).students
.getContextByUrl(vToken = contextVToken, url = contextUrl.toString()).students
.map { contextStudent ->
val semesters = runCatching {
when {
contextStudent.isAuthorizationRequired -> emptyList()
else -> studentPlus.getSemestersByUrl(
vToken = semestersVToken,
url = semestersUrl.toString(),
key = contextStudent.key,
diaryId = contextStudent.registerId,

View file

@ -25,6 +25,7 @@ import io.github.wulkanowy.sdk.scrapper.timetable.TimetablePlusHeader
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Query
import retrofit2.http.Url
@ -34,10 +35,14 @@ internal interface StudentPlusService {
// for register
@GET
suspend fun getContextByUrl(@Url url: String): ContextResponse
suspend fun getContextByUrl(
@Header("V-Token") vToken: String?,
@Url url: String,
): ContextResponse
@GET
suspend fun getSemestersByUrl(
@Header("V-Token") vToken: String?,
@Url url: String,
@Query("key") key: String,
@Query("idDziennik") diaryId: Int,