Update dependencies, update ktlint rules
This commit is contained in:
parent
29af590dd8
commit
f0c7093521
22 changed files with 151 additions and 91 deletions
|
@ -9,7 +9,17 @@ indent_size=4
|
|||
indent_size=2
|
||||
|
||||
[*.{kt,kts}]
|
||||
disabled_rules=import-ordering,no-wildcard-imports
|
||||
max_line_length=177
|
||||
ij_kotlin_allow_trailing_comma_on_call_site=true
|
||||
ij_kotlin_allow_trailing_comma=true
|
||||
|
||||
ktlint_standard_no-empty-first-line-in-class-body=disabled
|
||||
ktlint_standard_function-signature=disabled
|
||||
ktlint_standard_string-template-indent=disabled
|
||||
ktlint_standard_string-template-indent-expression-wrapping=disabled
|
||||
ktlint_standard_multiline-expression-wrapping=disabled
|
||||
ktlint_standard_max-line-length=disabled
|
||||
ktlint_standard_no-blank-line-in-list=disabled
|
||||
ktlint_standard_parameter-list-wrapping=disabled
|
||||
ktlint_standard_discouraged-comment-location=disabled
|
||||
ktlint_standard_if-else-wrapping=disabled
|
||||
|
|
|
@ -2,7 +2,7 @@ plugins {
|
|||
alias(libs.plugins.kotlin) apply false
|
||||
alias(libs.plugins.ksp) apply false
|
||||
alias(libs.plugins.serialization)
|
||||
id "org.jlleitschuh.gradle.ktlint" version "11.6.1"
|
||||
id "org.jlleitschuh.gradle.ktlint" version "12.0.2"
|
||||
id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
|
||||
id 'ru.vyarus.mkdocs' version '3.0.0'
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ ext {
|
|||
GIT_URL = 'https://github.com/wulkanowy/sdk.git'
|
||||
|
||||
jspoon = "1.3.2"
|
||||
jsoup = "1.16.2"
|
||||
jsoup = "1.17.1"
|
||||
slf4j = "2.0.9"
|
||||
moshi = "1.13.0"
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ subprojects {
|
|||
apply plugin: 'jacoco'
|
||||
|
||||
ktlint {
|
||||
additionalEditorconfigFile = file(".editorconfig")
|
||||
// additionalEditorconfigFile.set(file(".editorconfig"))
|
||||
disabledRules = [
|
||||
"no-wildcard-imports",
|
||||
"import-ordering",
|
||||
|
@ -134,7 +134,7 @@ subprojects {
|
|||
implementation libs.coroutines.core
|
||||
|
||||
implementation "com.squareup.okhttp3:logging-interceptor"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2"
|
||||
|
||||
testImplementation "junit:junit:4.13.2"
|
||||
testImplementation "com.squareup.okhttp3:mockwebserver"
|
||||
|
|
|
@ -70,9 +70,10 @@ internal class RepositoryManager(
|
|||
private fun getRetrofitBuilder(isJson: Boolean = true, signInterceptor: Boolean): Retrofit.Builder {
|
||||
return Retrofit.Builder()
|
||||
.apply {
|
||||
if (isJson) {
|
||||
addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||
} else addConverterFactory(ScalarsConverterFactory.create())
|
||||
when {
|
||||
isJson -> addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||
else -> addConverterFactory(ScalarsConverterFactory.create())
|
||||
}
|
||||
}
|
||||
.client(
|
||||
OkHttpClient().newBuilder()
|
||||
|
@ -81,8 +82,10 @@ internal class RepositoryManager(
|
|||
addInterceptor(SignInterceptor(keyId, privatePem, deviceModel))
|
||||
}
|
||||
interceptors.forEach {
|
||||
if (it.second) addNetworkInterceptor(it.first)
|
||||
else addInterceptor(it.first)
|
||||
when {
|
||||
it.second -> addNetworkInterceptor(it.first)
|
||||
else -> addInterceptor(it.first)
|
||||
}
|
||||
}
|
||||
}
|
||||
.build(),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.github.wulkanowy.sdk.hebe
|
||||
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import org.junit.Assert.assertTrue
|
||||
|
@ -10,7 +9,6 @@ import org.junit.Test
|
|||
import java.time.LocalDate
|
||||
|
||||
@Ignore
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class HebeRemoteTest {
|
||||
|
||||
private val hebe = Hebe()
|
||||
|
|
|
@ -300,15 +300,17 @@ class Scrapper {
|
|||
}
|
||||
|
||||
suspend fun getGrades(semester: Int): Grades {
|
||||
if (diaryId == 0) return Grades(
|
||||
details = emptyList(),
|
||||
summary = emptyList(),
|
||||
descriptive = emptyList(),
|
||||
isAverage = false,
|
||||
isPoints = false,
|
||||
isForAdults = false,
|
||||
type = -1,
|
||||
)
|
||||
if (diaryId == 0) {
|
||||
return Grades(
|
||||
details = emptyList(),
|
||||
summary = emptyList(),
|
||||
descriptive = emptyList(),
|
||||
isAverage = false,
|
||||
isPoints = false,
|
||||
isForAdults = false,
|
||||
type = -1,
|
||||
)
|
||||
}
|
||||
|
||||
return student.getGrades(semester)
|
||||
}
|
||||
|
@ -344,11 +346,13 @@ class Scrapper {
|
|||
suspend fun getMenu(date: LocalDate): List<Menu> = student.getMenu(date)
|
||||
|
||||
suspend fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null): Timetable {
|
||||
if (diaryId == 0) return Timetable(
|
||||
headers = emptyList(),
|
||||
lessons = emptyList(),
|
||||
additional = emptyList(),
|
||||
)
|
||||
if (diaryId == 0) {
|
||||
return Timetable(
|
||||
headers = emptyList(),
|
||||
lessons = emptyList(),
|
||||
additional = emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
return student.getTimetable(startDate, endDate)
|
||||
}
|
||||
|
|
|
@ -39,8 +39,10 @@ internal fun getGradeShortValue(value: String?): String {
|
|||
}
|
||||
|
||||
internal fun String.getEmptyIfDash(): String {
|
||||
return if (this == "-") ""
|
||||
else this
|
||||
return when {
|
||||
this == "-" -> ""
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
internal fun String.getGradePointPercent(): String {
|
||||
|
@ -77,7 +79,7 @@ fun String.getNormalizedSymbol(): String = this
|
|||
internal fun List<Recipient>.normalizeRecipients() = map { it.parseName() }
|
||||
|
||||
internal fun Recipient.parseName(): Recipient {
|
||||
val typeSeparatorPosition = fullName.indexOfAny(RecipientType.values().map { " - ${it.letter} - " })
|
||||
val typeSeparatorPosition = fullName.indexOfAny(RecipientType.entries.map { " - ${it.letter} - " })
|
||||
|
||||
if (typeSeparatorPosition == -1) return copy(userName = fullName)
|
||||
|
||||
|
@ -88,7 +90,7 @@ internal fun Recipient.parseName(): Recipient {
|
|||
return copy(
|
||||
userName = userName,
|
||||
studentName = studentName.takeIf { it != "($schoolName)" } ?: userName,
|
||||
type = typeLetter.let { letter -> RecipientType.values().first { it.letter == letter } },
|
||||
type = typeLetter.let { letter -> RecipientType.entries.first { it.letter == letter } },
|
||||
schoolNameShort = schoolName,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,9 +17,10 @@ internal object GradeDateDeserializer : KSerializer<LocalDate> {
|
|||
private val formatter = DateTimeFormatter.ofPattern("[$SERVER_FORMAT][$SERVER_FORMAT_2]")
|
||||
|
||||
override fun deserialize(decoder: Decoder): LocalDate {
|
||||
val date = if (decoder.decodeNotNullMark()) {
|
||||
decoder.decodeString()
|
||||
} else "01.01.1970"
|
||||
val date = when {
|
||||
decoder.decodeNotNullMark() -> decoder.decodeString()
|
||||
else -> "01.01.1970"
|
||||
}
|
||||
|
||||
return LocalDate.parse(date, formatter)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ private val gradeMinus = "-[0-6]|[0-6]-".toRegex()
|
|||
private val gradePlus = "[+][0-6]|[0-6][+]".toRegex()
|
||||
private val gradeDoublePlus = "[+]{2}[0-6]|[0-6][+]{2}".toRegex()
|
||||
private val gradeDoubleMinus = "[-|=]{1,2}[0-6]|[0-6][-|=]{1,2}".toRegex()
|
||||
private const val modifierWeight = .33
|
||||
private const val MODIFIER_WEIGHT = .33
|
||||
|
||||
fun isGradeValid(grade: String): Boolean {
|
||||
return grade.matches(validGrade)
|
||||
|
@ -19,8 +19,8 @@ fun getGradeValueWithModifier(grade: String): Pair<Int?, Double?> {
|
|||
|
||||
return gradeValue.run {
|
||||
when {
|
||||
matches(gradeMinus) -> replace("-", "").toInt() to -modifierWeight
|
||||
matches(gradePlus) -> replace("+", "").toInt() to modifierWeight
|
||||
matches(gradeMinus) -> replace("-", "").toInt() to -MODIFIER_WEIGHT
|
||||
matches(gradePlus) -> replace("+", "").toInt() to MODIFIER_WEIGHT
|
||||
matches(gradeDoublePlus) -> replace("++", "").toInt() to .5
|
||||
matches(gradeDoubleMinus) -> replace("[-|=]{1,2}".toRegex(), "").toInt() to -.5
|
||||
else -> (toIntOrNull() ?: 0) to .0
|
||||
|
|
|
@ -43,5 +43,6 @@ data class Homework(
|
|||
lateinit var teacherSymbol: String
|
||||
|
||||
@Transient
|
||||
@Suppress("PropertyName")
|
||||
var _attachments: List<Pair<String, String>> = emptyList()
|
||||
}
|
||||
|
|
|
@ -149,7 +149,9 @@ internal class AutoLoginInterceptor(
|
|||
.body(
|
||||
body = response()?.errorBody() ?: object : ResponseBody() {
|
||||
override fun contentLength() = 0L
|
||||
|
||||
override fun contentType(): MediaType? = null
|
||||
|
||||
override fun source(): BufferedSource = Buffer()
|
||||
},
|
||||
)
|
||||
|
|
|
@ -8,16 +8,20 @@ import io.github.wulkanowy.sdk.scrapper.exception.ScrapperException
|
|||
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
|
||||
|
||||
internal fun <T> ApiResponse<T>.handleErrors(): ApiResponse<T> {
|
||||
return if (!success && feedback != null) throw feedback.run {
|
||||
when {
|
||||
message.contains("niespójność danych") -> ScrapperException(message)
|
||||
message.contains("Brak uprawnień") -> AuthorizationRequiredException(message)
|
||||
message.contains("wyłączony") -> FeatureDisabledException(message)
|
||||
message.contains("DB_ERROR") -> VulcanException(message)
|
||||
message.contains("błąd") -> VulcanException(message)
|
||||
message.contains("The controller for path") -> InvalidPathException(message)
|
||||
message.contains("The parameters dictionary contains a null entry for parameter") -> InvalidPathException(message)
|
||||
else -> VulcanException(message)
|
||||
return when {
|
||||
!success && feedback != null -> throw feedback.run {
|
||||
when {
|
||||
message.contains("niespójność danych") -> ScrapperException(message)
|
||||
message.contains("Brak uprawnień") -> AuthorizationRequiredException(message)
|
||||
message.contains("wyłączony") -> FeatureDisabledException(message)
|
||||
message.contains("DB_ERROR") -> VulcanException(message)
|
||||
message.contains("błąd") -> VulcanException(message)
|
||||
message.contains("The controller for path") -> InvalidPathException(message)
|
||||
message.contains("The parameters dictionary contains a null entry for parameter") -> InvalidPathException(message)
|
||||
else -> VulcanException(message)
|
||||
}
|
||||
}
|
||||
} else this
|
||||
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,10 +54,13 @@ internal class ErrorInterceptor(
|
|||
|
||||
doc.select(".ErrorMessage, #ErrorTextLabel, #loginArea #errorText").takeIf { it.isNotEmpty() }?.let {
|
||||
val errorMessage = it.text().trimEnd('.')
|
||||
if (doc.select(SELECTOR_ADFS).isNotEmpty()) {
|
||||
if (errorMessage.isNotBlank()) throw BadCredentialsException(errorMessage)
|
||||
else logger.warn("Unexpected login page!")
|
||||
} else throw BadCredentialsException(errorMessage)
|
||||
when {
|
||||
doc.select(SELECTOR_ADFS).isNotEmpty() -> when {
|
||||
errorMessage.isNotBlank() -> throw BadCredentialsException(errorMessage)
|
||||
else -> logger.warn("Unexpected login page!")
|
||||
}
|
||||
else -> throw BadCredentialsException(errorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
doc.select(".app-error-container").takeIf { it.isNotEmpty() }?.let {
|
||||
|
|
|
@ -84,14 +84,17 @@ internal class AccountRepository(private val account: AccountService) {
|
|||
else -> throw ScrapperException("Nieznany dziennik $url")
|
||||
}
|
||||
|
||||
return if (unlockUrl.first == AUTO) {
|
||||
val loginType = getLoginType(UrlGenerator(url, domainSuffix, symbol, ""))
|
||||
loginType to when (loginType) {
|
||||
STANDARD -> "https://cufs$domainSuffix.vulcan.net.pl/$symbol/AccountManage/UnlockAccount"
|
||||
ADFSLightScoped -> "https://adfslight.vulcan.net.pl/$symbol/AccountManage/UnlockAccountRequest"
|
||||
else -> throw ScrapperException("Nieznany dziennik $registerBaseUrl, $loginType")
|
||||
return when (unlockUrl.first) {
|
||||
AUTO -> {
|
||||
val loginType = getLoginType(UrlGenerator(url, domainSuffix, symbol, ""))
|
||||
loginType to when (loginType) {
|
||||
STANDARD -> "https://cufs$domainSuffix.vulcan.net.pl/$symbol/AccountManage/UnlockAccount"
|
||||
ADFSLightScoped -> "https://adfslight.vulcan.net.pl/$symbol/AccountManage/UnlockAccountRequest"
|
||||
else -> throw ScrapperException("Nieznany dziennik $registerBaseUrl, $loginType")
|
||||
}
|
||||
}
|
||||
} else unlockUrl
|
||||
else -> unlockUrl
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getLoginType(urlGenerator: UrlGenerator): Scrapper.LoginType {
|
||||
|
|
|
@ -120,18 +120,20 @@ internal class MessagesRepository(private val api: MessagesService) {
|
|||
val appGuid = getScriptParam("appGuid", startPage)
|
||||
val appVersion = getScriptParam("version", startPage)
|
||||
|
||||
if (!removeForever) {
|
||||
api.moveMessageToTrash(
|
||||
when {
|
||||
!removeForever -> api.moveMessageToTrash(
|
||||
token = token,
|
||||
appGuid = appGuid,
|
||||
appVersion = appVersion,
|
||||
body = globalKeys,
|
||||
)
|
||||
} else api.deleteMessage(
|
||||
token = token,
|
||||
appGuid = appGuid,
|
||||
appVersion = appVersion,
|
||||
body = globalKeys,
|
||||
)
|
||||
|
||||
else -> api.deleteMessage(
|
||||
token = token,
|
||||
appGuid = appGuid,
|
||||
appVersion = appVersion,
|
||||
body = globalKeys,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,9 +246,12 @@ internal class RegisterRepository(
|
|||
val startPage = runCatching {
|
||||
student.getStart(url.generate(UrlGenerator.Site.STUDENT) + "App")
|
||||
}.recoverCatching {
|
||||
if (it is ScrapperException && it.code == HttpURLConnection.HTTP_NOT_FOUND) {
|
||||
student.getStart(url.generate(UrlGenerator.Site.STUDENT) + "Start")
|
||||
} else throw it
|
||||
when {
|
||||
it is ScrapperException && it.code == HttpURLConnection.HTTP_NOT_FOUND -> {
|
||||
student.getStart(url.generate(UrlGenerator.Site.STUDENT) + "Start")
|
||||
}
|
||||
else -> throw it
|
||||
}
|
||||
}.getOrThrow()
|
||||
|
||||
return student.getUserCache(
|
||||
|
|
|
@ -304,9 +304,10 @@ internal class StudentRepository(
|
|||
return runCatching {
|
||||
api.getStart("App")
|
||||
}.recoverCatching {
|
||||
if (it is ScrapperException && it.code == HTTP_NOT_FOUND) {
|
||||
api.getStart("Start")
|
||||
} else throw it
|
||||
when {
|
||||
it is ScrapperException && it.code == HTTP_NOT_FOUND -> api.getStart("Start")
|
||||
else -> throw it
|
||||
}
|
||||
}.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,8 +205,10 @@ internal class ServiceManager(
|
|||
.client(client.build())
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.addConverterFactory(
|
||||
if (json) this.json.asConverterFactory("application/json".toMediaType())
|
||||
else JspoonConverterFactory.create(),
|
||||
when {
|
||||
json -> this.json.asConverterFactory("application/json".toMediaType())
|
||||
else -> JspoonConverterFactory.create()
|
||||
},
|
||||
)
|
||||
.build()
|
||||
|
||||
|
@ -235,8 +237,10 @@ internal class ServiceManager(
|
|||
if (it.first is AutoLoginInterceptor && loginIntercept) addInterceptor(it.first)
|
||||
if (it.first is ErrorInterceptor && errIntercept) addInterceptor(it.first)
|
||||
} else {
|
||||
if (it.second) addNetworkInterceptor(it.first)
|
||||
else addInterceptor(it.first)
|
||||
when {
|
||||
it.second -> addNetworkInterceptor(it.first)
|
||||
else -> addInterceptor(it.first)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ import io.github.wulkanowy.sdk.scrapper.grades.GradesStatisticsRequest
|
|||
import io.github.wulkanowy.sdk.scrapper.grades.GradesStatisticsSemester
|
||||
import io.github.wulkanowy.sdk.scrapper.homework.HomeworkDay
|
||||
import io.github.wulkanowy.sdk.scrapper.homework.HomeworkRequest
|
||||
import io.github.wulkanowy.sdk.scrapper.menu.MenuRequest
|
||||
import io.github.wulkanowy.sdk.scrapper.menu.Menu
|
||||
import io.github.wulkanowy.sdk.scrapper.menu.MenuRequest
|
||||
import io.github.wulkanowy.sdk.scrapper.mobile.Device
|
||||
import io.github.wulkanowy.sdk.scrapper.mobile.TokenResponse
|
||||
import io.github.wulkanowy.sdk.scrapper.mobile.UnregisterDeviceRequest
|
||||
|
|
|
@ -30,8 +30,10 @@ internal class TimetableParser {
|
|||
else -> null
|
||||
}?.let {
|
||||
td.select(".uwaga-panel").getOrNull(0)?.let { warn ->
|
||||
if (it.info.isBlank()) it.copy(info = warn.text())
|
||||
else it.copy(info = "${it.info}: ${warn.text()}")
|
||||
when {
|
||||
it.info.isBlank() -> it.copy(info = warn.text())
|
||||
else -> it.copy(info = "${it.info}: ${warn.text()}")
|
||||
}
|
||||
} ?: it
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ internal class TimetableParser {
|
|||
private fun getLessonInfoForDuoDivs(lesson: Lesson, divs: Elements) = when {
|
||||
divs.has(1, CLASS_MOVED_OR_CANCELED) -> {
|
||||
when {
|
||||
divs[1]?.selectFirst("span")?.hasClass(CLASS_PLANNED) == true -> getLessonInfo(lesson, divs[0]).run {
|
||||
divs[1].selectFirst("span")?.hasClass(CLASS_PLANNED) == true -> getLessonInfo(lesson, divs[0]).run {
|
||||
val old = getLessonInfo(lesson, divs[1])
|
||||
copy(
|
||||
changes = true,
|
||||
|
@ -49,9 +51,11 @@ internal class TimetableParser {
|
|||
info = stripLessonInfo("${getFormattedLessonInfo(info)}, ${old.info}").replace("$subject ", "").capitalise(),
|
||||
)
|
||||
}
|
||||
|
||||
else -> getLessonInfo(lesson, divs[1])
|
||||
}
|
||||
}
|
||||
|
||||
divs.has(1, CLASS_CHANGES) -> getLessonInfo(lesson, divs[1]).run {
|
||||
val old = getLessonInfo(lesson, divs[0])
|
||||
copy(
|
||||
|
@ -62,6 +66,7 @@ internal class TimetableParser {
|
|||
roomOld = old.room,
|
||||
)
|
||||
}
|
||||
|
||||
divs.has(0, CLASS_MOVED_OR_CANCELED) && divs.has(0, CLASS_PLANNED) && divs.has(1, null) -> {
|
||||
getLessonInfo(lesson, divs[1]).run {
|
||||
val old = getLessonInfo(lesson, divs[0])
|
||||
|
@ -75,19 +80,23 @@ internal class TimetableParser {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
divs.has(0, CLASS_CHANGES) -> {
|
||||
val oldLesson = getLessonInfo(lesson, divs[0])
|
||||
val newLesson = getLessonInfo(lesson, divs[1])
|
||||
val isNewLessonEmpty = divs[1]?.select("span").isNullOrEmpty()
|
||||
if (!isNewLessonEmpty && oldLesson.teacher == newLesson.teacher) {
|
||||
newLesson.copy(
|
||||
val isNewLessonEmpty = divs[1].select("span").isNullOrEmpty()
|
||||
when {
|
||||
!isNewLessonEmpty && oldLesson.teacher == newLesson.teacher -> newLesson.copy(
|
||||
subjectOld = oldLesson.subject,
|
||||
roomOld = oldLesson.room,
|
||||
teacherOld = oldLesson.teacherOld,
|
||||
changes = true,
|
||||
)
|
||||
} else oldLesson
|
||||
|
||||
else -> oldLesson
|
||||
}
|
||||
}
|
||||
|
||||
else -> getLessonInfo(lesson, divs[0])
|
||||
}
|
||||
|
||||
|
@ -104,6 +113,7 @@ internal class TimetableParser {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
divs.has(0, CLASS_MOVED_OR_CANCELED) && divs.has(1, CLASS_MOVED_OR_CANCELED) && divs.has(2, CLASS_CHANGES) -> {
|
||||
getLessonInfo(lesson, divs[2]).run {
|
||||
val old = getLessonInfo(lesson, divs[0])
|
||||
|
@ -116,6 +126,7 @@ internal class TimetableParser {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
divs.has(0, CLASS_MOVED_OR_CANCELED) && divs.has(1, CLASS_CHANGES) && divs.has(1, CLASS_MOVED_OR_CANCELED) && divs.has(2, null) -> {
|
||||
val oldLesson = getLessonInfo(lesson, divs[0])
|
||||
getLessonInfo(lesson, divs[2]).copy(
|
||||
|
@ -124,11 +135,12 @@ internal class TimetableParser {
|
|||
roomOld = oldLesson.room,
|
||||
)
|
||||
}
|
||||
|
||||
else -> getLessonInfo(lesson, divs[1])
|
||||
}
|
||||
|
||||
private fun Elements.has(index: Int, className: String?): Boolean {
|
||||
return this[index]?.selectFirst("span").let {
|
||||
return this[index].selectFirst("span").let {
|
||||
when (className) {
|
||||
null -> it?.attr("class").isNullOrBlank()
|
||||
else -> it?.hasClass(className) == true
|
||||
|
@ -145,12 +157,14 @@ internal class TimetableParser {
|
|||
offset = 0,
|
||||
changes = div.ownText(),
|
||||
)
|
||||
|
||||
size == 3 && div.ownText().contains(INFO_REPLACEMENT_ROOM, true) -> getSimpleLessonWithNewReplacementRoom(
|
||||
lesson = lesson,
|
||||
spans = this,
|
||||
offset = 0,
|
||||
changes = div.ownText(),
|
||||
)
|
||||
|
||||
size == 3 -> getSimpleLesson(lesson, this, changes = div.ownText())
|
||||
size == 4 && div.ownText().contains(INFO_REPLACEMENT_TEACHER, true) -> getSimpleLessonWithNewReplacementTeacher(
|
||||
lesson = lesson,
|
||||
|
@ -158,12 +172,14 @@ internal class TimetableParser {
|
|||
offset = 1,
|
||||
changes = div.ownText(),
|
||||
)
|
||||
|
||||
size == 4 && div.ownText().contains(INFO_REPLACEMENT_ROOM, true) -> getSimpleLessonWithNewReplacementRoom(
|
||||
lesson = lesson,
|
||||
spans = this,
|
||||
offset = 1,
|
||||
changes = div.ownText(),
|
||||
)
|
||||
|
||||
size == 4 && last()?.hasClass(CLASS_REALIZED) == true -> getSimpleLesson(lesson, this, changes = div.ownText())
|
||||
size == 4 -> getGroupLesson(lesson, this, changes = div.ownText())
|
||||
size == 5 && first()?.hasClass(CLASS_CHANGES) == true && select(".$CLASS_REALIZED").size == 2 -> getSimpleLesson(
|
||||
|
@ -172,11 +188,13 @@ internal class TimetableParser {
|
|||
infoExtraOffset = 1,
|
||||
changes = div.ownText(),
|
||||
)
|
||||
|
||||
size == 5 && last()?.hasClass(CLASS_REALIZED) == true -> getGroupLesson(
|
||||
lesson = lesson,
|
||||
spans = this,
|
||||
changes = div.ownText(),
|
||||
)
|
||||
|
||||
size == 7 -> getSimpleLessonWithReplacement(lesson, spans = this)
|
||||
size == 9 -> getGroupLessonWithReplacement(lesson, spans = this)
|
||||
else -> lesson
|
||||
|
@ -279,6 +297,7 @@ internal class TimetableParser {
|
|||
private fun getRoomFromInfo(info: String?) = info?.substringAfter("(zmieniono salę z ")?.substringBefore(" na").orEmpty()
|
||||
|
||||
private fun getTeacherChangesWithoutSubstitution(changes: String?) = changes?.substringBefore("(zastępstwo: ").orEmpty()
|
||||
|
||||
private fun getRoomChangesWithoutSubstitution(changes: String?) = changes?.substringBefore("(zmieniono salę z ").orEmpty()
|
||||
|
||||
private fun stripLessonInfo(info: String) = info
|
||||
|
|
|
@ -77,8 +77,10 @@ abstract class BaseLocalTest : BaseTest() {
|
|||
.client(okHttp)
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.addConverterFactory(
|
||||
if (!html) json.asConverterFactory("application/json".toMediaType())
|
||||
else JspoonConverterFactory.create(),
|
||||
when {
|
||||
!html -> json.asConverterFactory("application/json".toMediaType())
|
||||
else -> JspoonConverterFactory.create()
|
||||
},
|
||||
)
|
||||
.baseUrl(url)
|
||||
.build()
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package io.github.wulkanowy.sdk.scrapper.attendance
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
class AttendanceCategoryTest {
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package io.github.wulkanowy.sdk.mapper
|
||||
|
||||
import io.github.wulkanowy.sdk.pojo.Exam
|
||||
import io.github.wulkanowy.sdk.toLocalDate
|
||||
import io.github.wulkanowy.sdk.scrapper.exams.Exam as ScrapperExam
|
||||
import io.github.wulkanowy.sdk.hebe.models.Exam as HebeExam
|
||||
import io.github.wulkanowy.sdk.scrapper.exams.Exam as ScrapperExam
|
||||
|
||||
@JvmName("mapScrapperExams")
|
||||
internal fun List<ScrapperExam>.mapExams() = map {
|
||||
|
|
Loading…
Reference in a new issue