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.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import retrofit2.Response
|
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 {
|
internal fun getScriptFlag(name: String, content: String, fallback: Boolean = false): Boolean {
|
||||||
return "$name: (false|true)".toRegex().find(content).let { result ->
|
return "$name: (false|true)".toRegex().find(content).let { result ->
|
||||||
if (null !== result) result.groupValues[1].toBoolean() else fallback
|
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()
|
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)
|
val matches = vParamsRegex.findAll(htmlContent)
|
||||||
return ModuleHeaders(
|
return ModuleHeaders(
|
||||||
token = getScriptParam("antiForgeryToken", htmlContent),
|
token = getScriptParam("antiForgeryToken", htmlContent),
|
||||||
|
@ -252,6 +270,7 @@ internal fun getModuleHeadersFromDocument(htmlContent: String): ModuleHeaders {
|
||||||
appVersion = getScriptParam("version", htmlContent).ifBlank {
|
appVersion = getScriptParam("version", htmlContent).ifBlank {
|
||||||
getScriptParam("appVersion", htmlContent)
|
getScriptParam("appVersion", htmlContent)
|
||||||
},
|
},
|
||||||
|
apiKey = getApiKey(document),
|
||||||
email = getScriptParam("name", htmlContent),
|
email = getScriptParam("name", htmlContent),
|
||||||
symbol = getScriptParam("appCustomerDb", htmlContent),
|
symbol = getScriptParam("appCustomerDb", htmlContent),
|
||||||
vParams = matches.toList().associate { match ->
|
vParams = matches.toList().associate { match ->
|
||||||
|
@ -289,12 +308,14 @@ private fun getVToken(uuid: String, headers: ModuleHeaders?, moduleHost: String)
|
||||||
val scheme = Scrapper.vTokenSchemeMap[headers?.appVersion]
|
val scheme = Scrapper.vTokenSchemeMap[headers?.appVersion]
|
||||||
?.get(moduleHost)
|
?.get(moduleHost)
|
||||||
?: "{UUID}-{appCustomerDb}-{appVersion}"
|
?: "{UUID}-{appCustomerDb}-{appVersion}"
|
||||||
val schemeToSubstitute = scheme.replace("{UUID}", uuid)
|
val schemeToSubstitute = scheme
|
||||||
|
.replace("{UUID}", uuid)
|
||||||
|
|
||||||
val vTokenEncoded = runCatching {
|
val vTokenEncoded = runCatching {
|
||||||
vTokenSchemeKeysRegex.replace(schemeToSubstitute) {
|
vTokenSchemeKeysRegex.replace(schemeToSubstitute) {
|
||||||
val key = it.groupValues[1]
|
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 {
|
}.onFailure {
|
||||||
logger.error("Error preparing vtoken!", it)
|
logger.error("Error preparing vtoken!", it)
|
||||||
|
|
|
@ -142,8 +142,7 @@ internal class AutoLoginInterceptor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveModuleHeaders(doc: Document, url: HttpUrl) {
|
private fun saveModuleHeaders(doc: Document, url: HttpUrl) {
|
||||||
val htmlContent = doc.select("script").html()
|
val moduleHeaders = getModuleHeadersFromDocument(doc)
|
||||||
val moduleHeaders = getModuleHeadersFromDocument(htmlContent)
|
|
||||||
|
|
||||||
if (moduleHeaders.token.isBlank()) {
|
if (moduleHeaders.token.isBlank()) {
|
||||||
logger.info("There is no token found on $url")
|
logger.info("There is no token found on $url")
|
||||||
|
|
|
@ -4,6 +4,7 @@ internal data class ModuleHeaders(
|
||||||
val token: String,
|
val token: String,
|
||||||
val appGuid: String,
|
val appGuid: String,
|
||||||
val appVersion: String,
|
val appVersion: String,
|
||||||
|
val apiKey: String,
|
||||||
val symbol: String? = null,
|
val symbol: String? = null,
|
||||||
val email: String? = null,
|
val email: String? = null,
|
||||||
val vParams: Map<String?, String?> = emptyMap(),
|
val vParams: Map<String?, String?> = emptyMap(),
|
||||||
|
|
|
@ -343,7 +343,7 @@ internal class RegisterRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getEduOneDiaries(baseStudentPlus: String, homepage: String): List<RegisterStudent> {
|
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 contextUrl = (baseStudentPlus + "api/Context").toHttpUrl()
|
||||||
val contextVToken = contextUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
|
val contextVToken = contextUrl.getMatchedVToken(StudentPlusModuleHost, moduleHeaders)
|
||||||
|
|
Loading…
Reference in a new issue