feat: apiKey parsing (#205)
Co-authored-by: Mikołaj Pich <m.pich@outlook.com>
This commit is contained in:
parent
de2a887188
commit
660e075cce
4 changed files with 27 additions and 6 deletions
|
@ -12,6 +12,7 @@ import okhttp3.HttpUrl
|
|||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.slf4j.LoggerFactory
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Response
|
||||
|
@ -75,6 +76,22 @@ internal fun getScriptParam(name: String, content: String, fallback: String = ""
|
|||
}
|
||||
}
|
||||
|
||||
internal fun getApiKey(document: Document, fallback: String = ""): String {
|
||||
val script = document.getElementsByTag("script").toList()
|
||||
.map { element -> element.html() }
|
||||
.filter { text -> text.length < 500 }
|
||||
.filter { text -> text.contains("VParam") && text.contains("apiKey") }
|
||||
.firstOrNull()
|
||||
|
||||
if (script == null) {
|
||||
return fallback
|
||||
}
|
||||
|
||||
return "(\\d{5,8})".toRegex().find(script).let { result ->
|
||||
if (null !== result) result.groupValues[1] else fallback
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getScriptFlag(name: String, content: String, fallback: Boolean = false): Boolean {
|
||||
return "$name: (false|true)".toRegex().find(content).let { result ->
|
||||
if (null !== result) result.groupValues[1].toBoolean() else fallback
|
||||
|
@ -244,7 +261,8 @@ internal fun getPathIndexByModuleHost(moduleHost: String): Int = when (moduleHos
|
|||
|
||||
private val vParamsRegex = "([a-zA-Z]+)\\s*:\\s*'([^']*)'".toRegex()
|
||||
|
||||
internal fun getModuleHeadersFromDocument(htmlContent: String): ModuleHeaders {
|
||||
internal fun getModuleHeadersFromDocument(document: Document): ModuleHeaders {
|
||||
val htmlContent = document.select("script").html()
|
||||
val matches = vParamsRegex.findAll(htmlContent)
|
||||
return ModuleHeaders(
|
||||
token = getScriptParam("antiForgeryToken", htmlContent),
|
||||
|
@ -252,6 +270,7 @@ internal fun getModuleHeadersFromDocument(htmlContent: String): ModuleHeaders {
|
|||
appVersion = getScriptParam("version", htmlContent).ifBlank {
|
||||
getScriptParam("appVersion", htmlContent)
|
||||
},
|
||||
apiKey = getApiKey(document),
|
||||
email = getScriptParam("name", htmlContent),
|
||||
symbol = getScriptParam("appCustomerDb", htmlContent),
|
||||
vParams = matches.toList().associate { match ->
|
||||
|
@ -289,12 +308,14 @@ private fun getVToken(uuid: String, headers: ModuleHeaders?, moduleHost: String)
|
|||
val scheme = Scrapper.vTokenSchemeMap[headers?.appVersion]
|
||||
?.get(moduleHost)
|
||||
?: "{UUID}-{appCustomerDb}-{appVersion}"
|
||||
val schemeToSubstitute = scheme.replace("{UUID}", uuid)
|
||||
val schemeToSubstitute = scheme
|
||||
.replace("{UUID}", uuid)
|
||||
|
||||
val vTokenEncoded = runCatching {
|
||||
vTokenSchemeKeysRegex.replace(schemeToSubstitute) {
|
||||
val key = it.groupValues[1]
|
||||
headers?.vParams.orEmpty()[key] ?: key
|
||||
val fallback = if (key == "apiKey") headers?.apiKey.orEmpty() else key
|
||||
headers?.vParams.orEmpty()[key] ?: fallback
|
||||
}
|
||||
}.onFailure {
|
||||
logger.error("Error preparing vtoken!", it)
|
||||
|
|
|
@ -142,8 +142,7 @@ internal class AutoLoginInterceptor(
|
|||
}
|
||||
|
||||
private fun saveModuleHeaders(doc: Document, url: HttpUrl) {
|
||||
val htmlContent = doc.select("script").html()
|
||||
val moduleHeaders = getModuleHeadersFromDocument(htmlContent)
|
||||
val moduleHeaders = getModuleHeadersFromDocument(doc)
|
||||
|
||||
if (moduleHeaders.token.isBlank()) {
|
||||
logger.info("There is no token found on $url")
|
||||
|
|
|
@ -4,6 +4,7 @@ internal data class ModuleHeaders(
|
|||
val token: String,
|
||||
val appGuid: String,
|
||||
val appVersion: String,
|
||||
val apiKey: String,
|
||||
val symbol: String? = null,
|
||||
val email: String? = null,
|
||||
val vParams: Map<String?, String?> = emptyMap(),
|
||||
|
|
|
@ -343,7 +343,7 @@ internal class RegisterRepository(
|
|||
}
|
||||
|
||||
private suspend fun getEduOneDiaries(baseStudentPlus: String, homepage: String): List<RegisterStudent> {
|
||||
val moduleHeaders = getModuleHeadersFromDocument(homepage)
|
||||
val moduleHeaders = getModuleHeadersFromDocument(Jsoup.parse(homepage))
|
||||
|
||||
val contextUrl = (baseStudentPlus + "api/Context").toHttpUrl()
|
||||
val contextVToken = contextUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
|
||||
|
|
Loading…
Reference in a new issue