Change vTokenSchemeMapping to vHeaders with configurable header name
This commit is contained in:
parent
bc52de44f9
commit
b8ff96f5fd
8 changed files with 89 additions and 41 deletions
|
@ -18,7 +18,7 @@ ext {
|
|||
moshi = "1.13.0"
|
||||
}
|
||||
|
||||
version = "2.6.9"
|
||||
version = "2.6.10-SNAPSHOT"
|
||||
group = "io.github.wulkanowy"
|
||||
|
||||
nexusPublishing {
|
||||
|
|
|
@ -630,6 +630,27 @@ internal val ApiEndpointsVTokenMap = mapOf(
|
|||
"Usuniete" to "6fb7f517-7287-41c3-8d30-64e654f647a7",
|
||||
"UsunieteSkrzynka" to "937cd3ba-6fa9-4e44-bb99-e4fd282803c2",
|
||||
),
|
||||
"uonetplus-uczenplus" to mapOf(
|
||||
"Context" to "cbdc1e7c-612f-4b7d-911d-c76701a0bd41",
|
||||
"Frekwencja" to "04921511-8b5f-44fc-8d2c-d9c5157393d1",
|
||||
"Usprawiedliwienia" to "0e579c35-e3e0-466c-ae2c-82b2b972097f",
|
||||
"FrekwencjaStatystyki" to "39dccbf3-8a04-41b1-a48d-8c056dff702c",
|
||||
"ZarejestrowaneUrzadzenia" to "06b04925-c003-4a53-8f9e-b720e368862a",
|
||||
"Zebrania" to "968f86f2-92a0-4f6e-b22c-4791e3362554",
|
||||
"RealizacjaZajec" to "3e1c3fb2-1b8a-4579-b7d8-ea2cfa263d42",
|
||||
"SprawdzianyZadaniaDomowe" to "bf7d0726-7979-4aee-89e2-9b74bbe0820d",
|
||||
"SprawdzianSzczegoly" to "3dcff009-c0ad-4b7f-95eb-18be7e3b9019",
|
||||
"ZadanieDomoweSzczegoly" to "2d8b6288-1f13-4ca7-bb6f-334de9a663d0",
|
||||
"PlanZajec" to "acd3f4c1-f366-41a4-b2a1-c3543d173ec7",
|
||||
"DniWolne" to "f28b5242-c33a-4ef3-8c3d-e8fb4d39f801",
|
||||
"Uwagi" to "1a0d8d8b-de01-4fe7-ae28-8fed2d68e9b5",
|
||||
"Nauczyciele" to "ce89218b-4609-4e10-92aa-217521e5d99a",
|
||||
"Informacje" to "984449a8-907b-4488-9f90-8f0c6e56c03c",
|
||||
"DaneUcznia" to "64348eca-82d1-442a-acc3-4886ca5daa33",
|
||||
"UczenZdjecie" to "4ed033b1-f8f4-4ca1-b277-60be0f80ab0f",
|
||||
"OkresyKlasyfikacyjne" to "6ff9273a-fb69-417d-aca9-d60ecceaad26",
|
||||
"Oceny" to "86f8dd7b-e144-42d9-a389-0648503a479d",
|
||||
),
|
||||
),
|
||||
"24.04.0008.58830" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
|
@ -644,24 +665,38 @@ internal val ApiEndpointsVTokenMap = mapOf(
|
|||
),
|
||||
)
|
||||
|
||||
internal val ApiEndpointsVTokenSchemeMap = mapOf(
|
||||
internal val ApiEndpointsVHeaders = mapOf(
|
||||
"24.04.0003.58698" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to "{UUID}-{name}-{appCustomerDb}-{appVersion}",
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
"V-Token" to "{UUID}-{name}-{appCustomerDb}-{appVersion}",
|
||||
),
|
||||
),
|
||||
"24.04.0004.58722" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to "{UUID}-{appCustomerDb}-{appVersion}",
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
"V-Token" to "{UUID}-{appCustomerDb}-{appVersion}",
|
||||
),
|
||||
),
|
||||
"24.04.0005.58736" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
"V-Token" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
),
|
||||
),
|
||||
"24.04.0006.58753" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
"V-Token" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
),
|
||||
),
|
||||
"24.04.0007.58773" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
"uonetplus-uczenplus" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
"V-Token" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
),
|
||||
"uonetplus-uczenplus" to mapOf(
|
||||
"V-Token" to "{UUID}-{appCustomerDb}-{appVersion}-{apiKey}",
|
||||
),
|
||||
),
|
||||
"24.04.0008.58830" to mapOf(
|
||||
"uonetplus-wiadomosciplus" to "{UUID}-{appCustomerDb}-{appCustomerDbSig}-{appVersion}-{apiKey}",
|
||||
"uonetplus-wiadomosciplus" to mapOf(
|
||||
"V-Apitoken" to "{UUID}-{appCustomerDb}-{appCustomerDbSig}-{appVersion}-{apiKey}",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -224,10 +224,10 @@ class Scrapper {
|
|||
vTokenMap = value
|
||||
}
|
||||
|
||||
var vTokenSchemeMapping: Map<String, Map<String, String>>
|
||||
get() = vTokenSchemeMap
|
||||
var vHeaders: Map<String, Map<String, Map<String, String>>>
|
||||
get() = vHeadersMap
|
||||
set(value) {
|
||||
vTokenSchemeMap = value
|
||||
vHeadersMap = value
|
||||
}
|
||||
|
||||
var vParamsEvaluation: suspend () -> EvaluateHandler
|
||||
|
@ -239,7 +239,7 @@ class Scrapper {
|
|||
internal companion object {
|
||||
var endpointsMap: Map<String, Map<String, Map<String, String>>> = ApiEndpointsMap
|
||||
var vTokenMap: Map<String, Map<String, Map<String, String>>> = ApiEndpointsVTokenMap
|
||||
var vTokenSchemeMap: Map<String, Map<String, String>> = ApiEndpointsVTokenSchemeMap
|
||||
var vHeadersMap: Map<String, Map<String, Map<String, String>>> = ApiEndpointsVHeaders
|
||||
var vParamsRun: suspend () -> EvaluateHandler = { object : EvaluateHandler {} }
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import kotlinx.serialization.json.jsonObject
|
|||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.slf4j.LoggerFactory
|
||||
|
@ -307,13 +306,22 @@ internal suspend fun getModuleHeadersFromDocument(document: Document): ModuleHea
|
|||
)
|
||||
}
|
||||
|
||||
internal fun Request.Builder.attachVToken(moduleHost: String, url: HttpUrl, headers: ModuleHeaders?): Request.Builder {
|
||||
val vToken = url.getMatchedVToken(moduleHost, headers) ?: return this
|
||||
addHeader("V-Apitoken", vToken)
|
||||
return this
|
||||
internal fun getVHeaders(moduleHost: String, url: HttpUrl, headers: ModuleHeaders?): Map<String, String> {
|
||||
val vHeaders = Scrapper.vHeadersMap[headers?.appVersion] ?: ApiEndpointsVHeaders[headers?.appVersion]
|
||||
|
||||
return vHeaders?.get(moduleHost).orEmpty().mapNotNull { (key, scheme) ->
|
||||
val headerValue = url.getMatchedVHeader(
|
||||
moduleHost = moduleHost,
|
||||
domainSchema = scheme,
|
||||
headers = headers,
|
||||
)
|
||||
if (headerValue != null) {
|
||||
key to headerValue
|
||||
} else null
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
internal fun HttpUrl.getMatchedVToken(moduleHost: String, headers: ModuleHeaders?): String? {
|
||||
private fun HttpUrl.getMatchedVHeader(moduleHost: String, domainSchema: String?, headers: ModuleHeaders?): String? {
|
||||
val pathSegmentIndex = getPathIndexByModuleHost(moduleHost)
|
||||
val pathKey = pathSegments.getOrNull(pathSegmentIndex)
|
||||
val mappedUuid = (Scrapper.vTokenMap[headers?.appVersion] ?: ApiEndpointsVTokenMap[headers?.appVersion])
|
||||
|
@ -321,17 +329,19 @@ internal fun HttpUrl.getMatchedVToken(moduleHost: String, headers: ModuleHeaders
|
|||
?.get(pathKey)
|
||||
?: return null
|
||||
|
||||
return getVToken(mappedUuid, headers, moduleHost)
|
||||
return getVToken(
|
||||
uuid = mappedUuid,
|
||||
headers = headers,
|
||||
domainSchema = domainSchema,
|
||||
)
|
||||
}
|
||||
|
||||
private val vTokenSchemeKeysRegex = "\\{([^{}]+)\\}".toRegex()
|
||||
|
||||
private fun getVToken(uuid: String, headers: ModuleHeaders?, moduleHost: String): String? {
|
||||
private fun getVToken(uuid: String, headers: ModuleHeaders?, domainSchema: String?): String? {
|
||||
if (uuid.isBlank()) return null
|
||||
|
||||
val schemeToSubstitute = (Scrapper.vTokenSchemeMap[headers?.appVersion] ?: ApiEndpointsVTokenSchemeMap[headers?.appVersion])
|
||||
?.get(moduleHost)
|
||||
?: "{UUID}-{appCustomerDb}-{appCustomerDbSig}-{appVersion}-{apiKey}"
|
||||
val schemeToSubstitute = domainSchema ?: "{UUID}-{appCustomerDb}-{appCustomerDbSig}-{appVersion}-{apiKey}"
|
||||
|
||||
val vTokenEncoded = runCatching {
|
||||
vTokenSchemeKeysRegex.replace(schemeToSubstitute) {
|
||||
|
|
|
@ -9,10 +9,10 @@ import io.github.wulkanowy.sdk.scrapper.Scrapper.LoginType.ADFSLight
|
|||
import io.github.wulkanowy.sdk.scrapper.Scrapper.LoginType.ADFSLightCufs
|
||||
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.exception.VulcanServerError
|
||||
import io.github.wulkanowy.sdk.scrapper.getModuleHeadersFromDocument
|
||||
import io.github.wulkanowy.sdk.scrapper.getVHeaders
|
||||
import io.github.wulkanowy.sdk.scrapper.isAnyMappingAvailable
|
||||
import io.github.wulkanowy.sdk.scrapper.login.LoginModuleResult
|
||||
import io.github.wulkanowy.sdk.scrapper.login.LoginResult
|
||||
|
@ -176,7 +176,14 @@ internal class AutoLoginInterceptor(
|
|||
addHeader("X-V-RequestVerificationToken", it.token)
|
||||
addHeader("X-V-AppGuid", it.appGuid)
|
||||
addHeader("X-V-AppVersion", it.appVersion)
|
||||
attachVToken(moduleHost, url, headers)
|
||||
|
||||
getVHeaders(
|
||||
moduleHost = moduleHost,
|
||||
url = url,
|
||||
headers = headers,
|
||||
).forEach { (key, headerValue) ->
|
||||
addHeader(key, headerValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.url(mappedUrl)
|
||||
|
|
|
@ -3,10 +3,10 @@ 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.getVHeaders
|
||||
import io.github.wulkanowy.sdk.scrapper.interceptor.StudentModuleHost
|
||||
import io.github.wulkanowy.sdk.scrapper.interceptor.StudentPlusModuleHost
|
||||
import io.github.wulkanowy.sdk.scrapper.interceptor.handleErrors
|
||||
|
@ -41,7 +41,6 @@ import org.jsoup.nodes.Element
|
|||
import org.jsoup.parser.Parser
|
||||
import org.jsoup.select.Elements
|
||||
import org.slf4j.LoggerFactory
|
||||
import pl.droidsonroids.jspoon.Jspoon
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
|
||||
@Suppress("UnnecessaryOptInAnnotation")
|
||||
|
@ -63,10 +62,6 @@ internal class RegisterRepository(
|
|||
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||
}
|
||||
|
||||
private val certificateAdapter by lazy {
|
||||
Jspoon.create().adapter(CertificateResponse::class.java)
|
||||
}
|
||||
|
||||
suspend fun getUserSubjects(): RegisterUser {
|
||||
val symbolLoginType = getLoginType(startSymbol.getNormalizedSymbol())
|
||||
val certificateResponse = getCert(symbolLoginType)
|
||||
|
@ -350,21 +345,21 @@ internal class RegisterRepository(
|
|||
val moduleHeaders = getModuleHeadersFromDocument(homepage)
|
||||
val baseStudentPlus = url.generate(UrlGenerator.Site.STUDENT_PLUS)
|
||||
val contextUrl = (baseStudentPlus + "api/Context").toHttpUrl()
|
||||
val contextVToken = contextUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
|
||||
val contextVHeaders = getVHeaders(StudentPlusModuleHost, contextUrl, moduleHeaders)
|
||||
val mappedContextUrl = contextUrl.mapModuleUrl(StudentPlusModuleHost, moduleHeaders.appVersion)
|
||||
|
||||
val semestersUrl = (baseStudentPlus + "api/OkresyKlasyfikacyjne").toHttpUrl()
|
||||
val semestersVToken = semestersUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
|
||||
val semesterVHeaders = getVHeaders(StudentPlusModuleHost, semestersUrl, moduleHeaders)
|
||||
val mappedSemestersUrl = semestersUrl.mapModuleUrl(StudentPlusModuleHost, moduleHeaders.appVersion)
|
||||
|
||||
return studentPlus
|
||||
.getContextByUrl(vToken = contextVToken, url = mappedContextUrl.toString()).students
|
||||
.getContextByUrl(vHeaders = contextVHeaders, url = mappedContextUrl.toString()).students
|
||||
.map { contextStudent ->
|
||||
val semesters = runCatching {
|
||||
when {
|
||||
contextStudent.isAuthorizationRequired -> emptyList()
|
||||
else -> studentPlus.getSemestersByUrl(
|
||||
vToken = semestersVToken,
|
||||
vHeaders = semesterVHeaders,
|
||||
url = mappedSemestersUrl.toString(),
|
||||
key = contextStudent.key,
|
||||
diaryId = contextStudent.registerId,
|
||||
|
|
|
@ -26,6 +26,7 @@ import retrofit2.Response
|
|||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.HeaderMap
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Url
|
||||
|
@ -36,13 +37,13 @@ internal interface StudentPlusService {
|
|||
|
||||
@GET
|
||||
suspend fun getContextByUrl(
|
||||
@Header("V-Apitoken") vToken: String?,
|
||||
@HeaderMap vHeaders: Map<String, String>,
|
||||
@Url url: String,
|
||||
): ContextResponse
|
||||
|
||||
@GET
|
||||
suspend fun getSemestersByUrl(
|
||||
@Header("V-Apitoken") vToken: String?,
|
||||
@HeaderMap vHeaders: Map<String, String>,
|
||||
@Url url: String,
|
||||
@Query("key") key: String,
|
||||
@Query("idDziennik") diaryId: Int,
|
||||
|
|
|
@ -248,10 +248,10 @@ class Sdk {
|
|||
scrapper.vTokenMapping = value
|
||||
}
|
||||
|
||||
var vTokenSchemeMapping
|
||||
get() = scrapper.vTokenSchemeMapping
|
||||
var vHeaders
|
||||
get() = scrapper.vHeaders
|
||||
set(value) {
|
||||
scrapper.vTokenSchemeMapping = value
|
||||
scrapper.vHeaders = value
|
||||
}
|
||||
|
||||
var vParamsEvaluation: suspend () -> EvaluateHandler
|
||||
|
|
Loading…
Reference in a new issue