Migrate scraper module to coroutines

This commit is contained in:
Mikołaj Pich 2020-06-14 18:26:58 +02:00
parent 48b7ed8955
commit 0165e05aae
47 changed files with 1352 additions and 1659 deletions

View file

@ -83,6 +83,8 @@ subprojects {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.3.7'
implementation "io.reactivex.rxjava2:rxjava:2.2.19"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp3"

View file

@ -14,7 +14,6 @@ import io.github.wulkanowy.sdk.scrapper.repository.StudentAndParentStartReposito
import io.github.wulkanowy.sdk.scrapper.repository.StudentRepository
import io.github.wulkanowy.sdk.scrapper.repository.StudentStartRepository
import io.github.wulkanowy.sdk.scrapper.service.ServiceManager
import io.reactivex.Single
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import org.threeten.bp.LocalDate
@ -219,74 +218,74 @@ class Scrapper {
HomepageRepository(serviceManager.getHomepageService())
}
fun getPasswordResetCaptcha(registerBaseUrl: String, symbol: String) = account.getPasswordResetCaptcha(registerBaseUrl, symbol)
suspend fun getPasswordResetCaptcha(registerBaseUrl: String, symbol: String) = account.getPasswordResetCaptcha(registerBaseUrl, symbol)
fun sendPasswordResetRequest(registerBaseUrl: String, symbol: String, email: String, captchaCode: String): Single<String> {
suspend fun sendPasswordResetRequest(registerBaseUrl: String, symbol: String, email: String, captchaCode: String): String {
return account.sendPasswordResetRequest(registerBaseUrl, symbol, email.trim(), captchaCode)
}
fun getStudents() = register.getStudents()
suspend fun getStudents() = register.getStudents()
fun getSemesters() = if (useNewStudent) studentStart.getSemesters() else snpStart.getSemesters()
suspend fun getSemesters() = if (useNewStudent) studentStart.getSemesters() else snpStart.getSemesters()
fun getAttendance(startDate: LocalDate, endDate: LocalDate? = null) =
suspend fun getAttendance(startDate: LocalDate, endDate: LocalDate? = null) =
if (useNewStudent) student.getAttendance(startDate, endDate) else snp.getAttendance(startDate, endDate)
fun getAttendanceSummary(subjectId: Int? = -1) = if (useNewStudent) student.getAttendanceSummary(subjectId) else snp.getAttendanceSummary(subjectId)
suspend fun getAttendanceSummary(subjectId: Int? = -1) = if (useNewStudent) student.getAttendanceSummary(subjectId) else snp.getAttendanceSummary(subjectId)
fun excuseForAbsence(absents: List<Absent>, content: String? = null) = student.excuseForAbsence(absents, content)
suspend fun excuseForAbsence(absents: List<Absent>, content: String? = null) = student.excuseForAbsence(absents, content)
fun getSubjects() = if (useNewStudent) student.getSubjects() else snp.getSubjects()
suspend fun getSubjects() = if (useNewStudent) student.getSubjects() else snp.getSubjects()
fun getExams(startDate: LocalDate, endDate: LocalDate? = null) =
suspend fun getExams(startDate: LocalDate, endDate: LocalDate? = null) =
if (useNewStudent) student.getExams(startDate, endDate) else snp.getExams(startDate, endDate)
fun getGrades(semesterId: Int) = if (useNewStudent) student.getGrades(semesterId) else snp.getGrades(semesterId)
suspend fun getGrades(semesterId: Int) = if (useNewStudent) student.getGrades(semesterId) else snp.getGrades(semesterId)
fun getGradesDetails(semesterId: Int? = null) = if (useNewStudent) student.getGradesDetails(semesterId) else snp.getGradesDetails(semesterId)
suspend fun getGradesDetails(semesterId: Int? = null) = if (useNewStudent) student.getGradesDetails(semesterId) else snp.getGradesDetails(semesterId)
fun getGradesSummary(semesterId: Int? = null) = if (useNewStudent) student.getGradesSummary(semesterId) else snp.getGradesSummary(semesterId)
suspend fun getGradesSummary(semesterId: Int? = null) = if (useNewStudent) student.getGradesSummary(semesterId) else snp.getGradesSummary(semesterId)
fun getGradesPartialStatistics(semesterId: Int) =
suspend fun getGradesPartialStatistics(semesterId: Int) =
if (useNewStudent) student.getGradesPartialStatistics(semesterId) else snp.getGradesStatistics(semesterId, false)
fun getGradesPointsStatistics(semesterId: Int) = student.getGradesPointsStatistics(semesterId)
suspend fun getGradesPointsStatistics(semesterId: Int) = student.getGradesPointsStatistics(semesterId)
fun getGradesAnnualStatistics(semesterId: Int) =
suspend fun getGradesAnnualStatistics(semesterId: Int) =
if (useNewStudent) student.getGradesAnnualStatistics(semesterId) else snp.getGradesStatistics(semesterId, true)
fun getHomework(startDate: LocalDate, endDate: LocalDate? = null) =
suspend fun getHomework(startDate: LocalDate, endDate: LocalDate? = null) =
if (useNewStudent) student.getHomework(startDate, endDate) else snp.getHomework(startDate, endDate)
fun getNotes() = if (useNewStudent) student.getNotes() else snp.getNotes()
suspend fun getNotes() = if (useNewStudent) student.getNotes() else snp.getNotes()
fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null) =
suspend fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null) =
if (useNewStudent) student.getTimetable(startDate, endDate) else snp.getTimetable(startDate, endDate)
fun getCompletedLessons(startDate: LocalDate, endDate: LocalDate? = null, subjectId: Int = -1) =
suspend fun getCompletedLessons(startDate: LocalDate, endDate: LocalDate? = null, subjectId: Int = -1) =
if (useNewStudent) student.getCompletedLessons(startDate, endDate, subjectId) else snp.getCompletedLessons(startDate, endDate, subjectId)
fun getRegisteredDevices() = if (useNewStudent) student.getRegisteredDevices() else snp.getRegisteredDevices()
suspend fun getRegisteredDevices() = if (useNewStudent) student.getRegisteredDevices() else snp.getRegisteredDevices()
fun getToken() = if (useNewStudent) student.getToken() else snp.getToken()
suspend fun getToken() = if (useNewStudent) student.getToken() else snp.getToken()
fun unregisterDevice(id: Int) = if (useNewStudent) student.unregisterDevice(id) else snp.unregisterDevice(id)
suspend fun unregisterDevice(id: Int) = if (useNewStudent) student.unregisterDevice(id) else snp.unregisterDevice(id)
fun getTeachers() = if (useNewStudent) student.getTeachers() else snp.getTeachers()
suspend fun getTeachers() = if (useNewStudent) student.getTeachers() else snp.getTeachers()
fun getSchool() = if (useNewStudent) student.getSchool() else snp.getSchool()
suspend fun getSchool() = if (useNewStudent) student.getSchool() else snp.getSchool()
fun getStudentInfo() = snp.getStudentInfo()
suspend fun getStudentInfo() = snp.getStudentInfo()
fun getReportingUnits() = messages.getReportingUnits()
suspend fun getReportingUnits() = messages.getReportingUnits()
fun getRecipients(unitId: Int, role: Int = 2) = messages.getRecipients(unitId, role)
suspend fun getRecipients(unitId: Int, role: Int = 2) = messages.getRecipients(unitId, role)
fun getMessages(
suspend fun getMessages(
folder: Folder,
startDate: LocalDateTime? = null,
endDate: LocalDateTime? = null
): Single<List<Message>> {
): List<Message> {
return when (folder) {
Folder.RECEIVED -> messages.getReceivedMessages(startDate, endDate)
Folder.SENT -> messages.getSentMessages(startDate, endDate)
@ -294,39 +293,39 @@ class Scrapper {
}
}
fun getReceivedMessages(startDate: LocalDateTime? = null, endDate: LocalDateTime? = null) = messages.getReceivedMessages(startDate, endDate)
suspend fun getReceivedMessages(startDate: LocalDateTime? = null, endDate: LocalDateTime? = null) = messages.getReceivedMessages(startDate, endDate)
fun getSentMessages(startDate: LocalDateTime? = null, endDate: LocalDateTime? = null) = messages.getSentMessages(startDate, endDate)
suspend fun getSentMessages(startDate: LocalDateTime? = null, endDate: LocalDateTime? = null) = messages.getSentMessages(startDate, endDate)
fun getDeletedMessages(startDate: LocalDateTime? = null, endDate: LocalDateTime? = null) = messages.getDeletedMessages(startDate, endDate)
suspend fun getDeletedMessages(startDate: LocalDateTime? = null, endDate: LocalDateTime? = null) = messages.getDeletedMessages(startDate, endDate)
fun getMessageRecipients(messageId: Int, loginId: Int = 0) = messages.getMessageRecipients(messageId, loginId)
suspend fun getMessageRecipients(messageId: Int, loginId: Int = 0) = messages.getMessageRecipients(messageId, loginId)
fun getMessageDetails(messageId: Int, folderId: Int, read: Boolean = false, id: Int? = null) = messages.getMessageDetails(messageId, folderId, read, id)
suspend fun getMessageDetails(messageId: Int, folderId: Int, read: Boolean = false, id: Int? = null) = messages.getMessageDetails(messageId, folderId, read, id)
fun getMessageContent(messageId: Int, folderId: Int, read: Boolean = false, id: Int? = null) = messages.getMessage(messageId, folderId, read, id)
suspend fun getMessageContent(messageId: Int, folderId: Int, read: Boolean = false, id: Int? = null) = messages.getMessage(messageId, folderId, read, id)
fun sendMessage(subject: String, content: String, recipients: List<Recipient>) = messages.sendMessage(subject, content, recipients)
suspend fun sendMessage(subject: String, content: String, recipients: List<Recipient>) = messages.sendMessage(subject, content, recipients)
fun deleteMessages(messagesToDelete: List<Pair<Int, Int>>) = messages.deleteMessages(messagesToDelete)
suspend fun deleteMessages(messagesToDelete: List<Pair<Int, Int>>) = messages.deleteMessages(messagesToDelete)
fun getSelfGovernments() = homepage.getSelfGovernments()
suspend fun getSelfGovernments() = homepage.getSelfGovernments()
fun getStudentThreats() = homepage.getStudentThreats()
suspend fun getStudentThreats() = homepage.getStudentThreats()
fun getStudentsTrips() = homepage.getStudentsTrips()
suspend fun getStudentsTrips() = homepage.getStudentsTrips()
fun getLastGrades() = homepage.getLastGrades()
suspend fun getLastGrades() = homepage.getLastGrades()
fun getFreeDays() = homepage.getFreeDays()
suspend fun getFreeDays() = homepage.getFreeDays()
fun getKidsLuckyNumbers() = homepage.getKidsLuckyNumbers()
suspend fun getKidsLuckyNumbers() = homepage.getKidsLuckyNumbers()
fun getKidsLessonPlan() = homepage.getKidsLessonPlan()
suspend fun getKidsLessonPlan() = homepage.getKidsLessonPlan()
fun getLastHomework() = homepage.getLastHomework()
suspend fun getLastHomework() = homepage.getLastHomework()
fun getLastTests() = homepage.getLastTests()
suspend fun getLastTests() = homepage.getLastTests()
fun getLastStudentLessons() = homepage.getLastStudentLessons()
suspend fun getLastStudentLessons() = homepage.getLastStudentLessons()
}

View file

@ -14,42 +14,28 @@ import io.github.wulkanowy.sdk.scrapper.attendance.Attendance.Category.UNKNOWN
import io.github.wulkanowy.sdk.scrapper.attendance.Attendance.Category.values
import io.github.wulkanowy.sdk.scrapper.timetable.CacheResponse.Time
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.reactivex.Observable
import io.reactivex.Single
import org.threeten.bp.LocalDate
import org.threeten.bp.Month
fun Single<AttendanceResponse?>.mapAttendanceList(start: LocalDate, end: LocalDate?, getTimes: () -> Single<List<Time>>): Single<List<Attendance>> {
fun AttendanceResponse.mapAttendanceList(start: LocalDate, end: LocalDate?, times: List<Time>): List<Attendance> {
val endDate = end ?: start.plusDays(4)
var excuseActive = false
var sentExcuses = emptyList<SentExcuse>()
return map {
it.run {
excuseActive = this.excuseActive
sentExcuses = this.sentExcuses
lessons
}
}.flatMapObservable { Observable.fromIterable(it) }.flatMap { a ->
getTimes().flatMapObservable { times ->
Observable.fromIterable(times.filter { time -> time.id == a.timeId })
}.map {
val sentExcuse = sentExcuses.firstOrNull { excuse -> excuse.date == a.date && excuse.timeId == a.timeId }
a.apply {
presence = a.categoryId == PRESENCE.id || a.categoryId == ABSENCE_FOR_SCHOOL_REASONS.id
absence = a.categoryId == ABSENCE_UNEXCUSED.id || a.categoryId == ABSENCE_EXCUSED.id
lateness = a.categoryId == EXCUSED_LATENESS.id || a.categoryId == UNEXCUSED_LATENESS.id
excused = a.categoryId == ABSENCE_EXCUSED.id || a.categoryId == EXCUSED_LATENESS.id
exemption = a.categoryId == EXEMPTION.id
excusable = excuseActive && (absence || lateness) && !excused && sentExcuse == null
name = (values().singleOrNull { category -> category.id == categoryId } ?: UNKNOWN).title
number = it.number
if (sentExcuse != null)
excuseStatus = SentExcuse.Status.getByValue(sentExcuse.status)
}
return lessons.map {
val sentExcuse = sentExcuses.firstOrNull { excuse -> excuse.date == it.date && excuse.timeId == it.timeId }
it.apply {
presence = it.categoryId == PRESENCE.id || it.categoryId == ABSENCE_FOR_SCHOOL_REASONS.id
absence = it.categoryId == ABSENCE_UNEXCUSED.id || it.categoryId == ABSENCE_EXCUSED.id
lateness = it.categoryId == EXCUSED_LATENESS.id || it.categoryId == UNEXCUSED_LATENESS.id
excused = it.categoryId == ABSENCE_EXCUSED.id || it.categoryId == EXCUSED_LATENESS.id
exemption = it.categoryId == EXEMPTION.id
excusable = excuseActive && (absence || lateness) && !excused && sentExcuse == null
name = (values().singleOrNull { category -> category.id == categoryId } ?: UNKNOWN).title
number = times.single { time -> time.id == it.timeId }.number
if (sentExcuse != null)
excuseStatus = SentExcuse.Status.getByValue(sentExcuse.status)
}
}.filter {
it.date.toLocalDate() >= start && it.date.toLocalDate() <= endDate
}.toList().map { list -> list.sortedWith(compareBy({ it.date }, { it.number })) }
}.sortedWith(compareBy({ it.date }, { it.number }))
}
fun AttendanceSummaryResponse.mapAttendanceSummaryList(gson: GsonBuilder): List<AttendanceSummary> {

View file

@ -6,26 +6,18 @@ import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
import io.github.wulkanowy.sdk.scrapper.exception.InvalidPathException
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
import io.reactivex.Single
import io.reactivex.SingleSource
import io.reactivex.SingleTransformer
class ErrorHandlerTransformer<T : Any?> : SingleTransformer<ApiResponse<T>, ApiResponse<T>> {
override fun apply(upstream: Single<ApiResponse<T>>): SingleSource<ApiResponse<T>> {
return upstream.map { res ->
if (!res.success && res.feedback != null) throw res.feedback.run {
when {
message.contains("niespójność danych") -> ScrapperException(message)
message.contains("Brak uprawnień") -> AccountPermissionException(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 res
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ń") -> AccountPermissionException(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
}

View file

@ -12,7 +12,6 @@ import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.register.SendCertificateResponse
import io.github.wulkanowy.sdk.scrapper.service.LoginService
import io.reactivex.Single
import org.slf4j.LoggerFactory
import org.threeten.bp.LocalDateTime.now
import org.threeten.bp.ZoneId
@ -31,7 +30,8 @@ class LoginHelper(
) {
companion object {
@JvmStatic private val logger = LoggerFactory.getLogger(this::class.java)
@JvmStatic
private val logger = LoggerFactory.getLogger(this::class.java)
}
init {
@ -49,22 +49,20 @@ class LoginHelper(
}
@Synchronized
fun login(email: String, password: String): Single<SendCertificateResponse> {
return sendCredentials(email, password).flatMap {
logger.info("Login started")
when {
it.title.startsWith("Witryna ucznia i rodzica") -> return@flatMap Single.just(SendCertificateResponse())
it.action.isBlank() -> throw VulcanException("Invalid certificate page: '${it.title}'. Try again")
}
sendCertificate(it, email)
}.map {
logger.debug("Login completed")
it
suspend fun login(email: String, password: String): SendCertificateResponse {
val res = sendCredentials(email, password)
logger.info("Login started")
when {
res.title.startsWith("Witryna ucznia i rodzica") -> return SendCertificateResponse()
res.action.isBlank() -> throw VulcanException("Invalid certificate page: '${res.title}'. Try again")
}
val cert = sendCertificate(res, email)
logger.debug("Login completed")
return cert
}
fun sendCredentials(email: String, password: String): Single<CertificateResponse> {
suspend fun sendCredentials(email: String, password: String): CertificateResponse {
email.substringBefore("||").let {
return when (loginType) {
AUTO -> throw ScrapperException("You must first specify Api.loginType before logging in")
@ -76,94 +74,95 @@ class LoginHelper(
}
}
fun sendCertificate(cert: CertificateResponse, email: String, url: String = cert.action): Single<SendCertificateResponse> {
suspend fun sendCertificate(cert: CertificateResponse, email: String, url: String = cert.action): SendCertificateResponse {
cookies.cookieStore.removeAll()
return api.sendCertificate(url, mapOf(
val res = api.sendCertificate(url, mapOf(
"wa" to cert.wa,
"wresult" to cert.wresult,
"wctx" to cert.wctx
)).flatMap {
if (email.contains("||")) api.switchLogin("$url?rebuild=${email.substringAfter("||", "")}")
else Single.just(it)
}
))
if (email.contains("||")) api.switchLogin("$url?rebuild=${email.substringAfter("||", "")}")
return res
}
private fun sendStandard(email: String, password: String): Single<CertificateResponse> {
return api.sendCredentials(firstStepReturnUrl, mapOf(
private suspend fun sendStandard(email: String, password: String): CertificateResponse {
return certificateAdapter.fromHtml(api.sendCredentials(firstStepReturnUrl, mapOf(
"LoginName" to email,
"Password" to password
)).map { certificateAdapter.fromHtml(it) }
)))
}
private fun sendADFSLightGeneric(email: String, password: String, type: Scrapper.LoginType): Single<CertificateResponse> {
return api.sendADFSForm(
private suspend fun sendADFSLightGeneric(email: String, password: String, type: Scrapper.LoginType): CertificateResponse {
val res = certificateAdapter.fromHtml(api.sendADFSForm(
getADFSUrl(type), mapOf(
"Username" to email,
"Password" to password,
"x" to "0",
"y" to "0"
)
).map { certificateAdapter.fromHtml(it) }.flatMap {
api.sendADFSForm(
it.action, mapOf(
"wa" to it.wa,
"wresult" to it.wresult,
"wctx" to it.wctx
)
))
return certificateAdapter.fromHtml(api.sendADFSForm(
res.action, mapOf(
"wa" to res.wa,
"wresult" to res.wresult,
"wctx" to res.wctx
)
}.map { certificateAdapter.fromHtml(it) }
))
}
private fun sendADFS(email: String, password: String): Single<CertificateResponse> {
return api.getForm(getADFSUrl(ADFS)).flatMap {
if (it.formAction.isBlank()) throw VulcanException("Invalid ADFS login page: '${it.title}'. Try again")
api.sendADFSForm("$schema://adfs.$host/${it.formAction.removePrefix("/")}", mapOf(
"__db" to it.db,
"__VIEWSTATE" to it.viewstate,
"__VIEWSTATEGENERATOR" to it.viewStateGenerator,
"__EVENTVALIDATION" to it.eventValidation,
"UsernameTextBox" to email,
"PasswordTextBox" to password,
"SubmitButton.x" to "0",
"SubmitButton.y" to "0"
))
}.map { certificateAdapter.fromHtml(it) }.flatMap {
api.sendADFSForm(it.action, mapOf(
"wa" to it.wa,
"wresult" to it.wresult,
"wctx" to it.wctx
))
}.map { certificateAdapter.fromHtml(it) }
private suspend fun sendADFS(email: String, password: String): CertificateResponse {
val res = api.getForm(getADFSUrl(ADFS))
if (res.formAction.isBlank()) throw VulcanException("Invalid ADFS login page: '${res.title}'. Try again")
val form = certificateAdapter.fromHtml(api.sendADFSForm("$schema://adfs.$host/${res.formAction.removePrefix("/")}", mapOf(
"__db" to res.db,
"__VIEWSTATE" to res.viewstate,
"__VIEWSTATEGENERATOR" to res.viewStateGenerator,
"__EVENTVALIDATION" to res.eventValidation,
"UsernameTextBox" to email,
"PasswordTextBox" to password,
"SubmitButton.x" to "0",
"SubmitButton.y" to "0"
)))
return certificateAdapter.fromHtml(api.sendADFSForm(form.action, mapOf(
"wa" to form.wa,
"wresult" to form.wresult,
"wctx" to form.wctx
)))
}
private fun sendADFSCards(email: String, password: String): Single<CertificateResponse> {
return api.getForm(getADFSUrl(ADFSCards)).flatMap {
api.sendADFSFormStandardChoice("$schema://adfs.$host/${it.formAction.removePrefix("/")}", mapOf(
"__db" to it.db,
"__VIEWSTATE" to it.viewstate,
"__VIEWSTATEGENERATOR" to it.viewStateGenerator,
"__EVENTVALIDATION" to it.eventValidation,
"PassiveSignInButton.x" to "0",
"PassiveSignInButton.y" to "0"
))
}.flatMap {
api.sendADFSForm("$schema://adfs.$host/${it.formAction.removePrefix("/")}", mapOf(
"__db" to it.db,
"__VIEWSTATE" to it.viewstate,
"__VIEWSTATEGENERATOR" to it.viewStateGenerator,
"__EVENTVALIDATION" to it.eventValidation,
"SubmitButton.x" to "0",
"SubmitButton.y" to "0",
"UsernameTextBox" to email,
"PasswordTextBox" to password
))
}.map { certificateAdapter.fromHtml(it) }.flatMap {
api.sendADFSForm(it.action, mapOf(
"wa" to it.wa,
"wresult" to it.wresult,
"wctx" to it.wctx
))
}.map { certificateAdapter.fromHtml(it) }
private suspend fun sendADFSCards(email: String, password: String): CertificateResponse {
val form = api.getForm(getADFSUrl(ADFSCards))
val form2 = api.sendADFSFormStandardChoice("$schema://adfs.$host/${form.formAction.removePrefix("/")}", mapOf(
"__db" to form.db,
"__VIEWSTATE" to form.viewstate,
"__VIEWSTATEGENERATOR" to form.viewStateGenerator,
"__EVENTVALIDATION" to form.eventValidation,
"PassiveSignInButton.x" to "0",
"PassiveSignInButton.y" to "0"
))
val form3 = certificateAdapter.fromHtml(api.sendADFSForm("$schema://adfs.$host/${form2.formAction.removePrefix("/")}", mapOf(
"__db" to form2.db,
"__VIEWSTATE" to form2.viewstate,
"__VIEWSTATEGENERATOR" to form2.viewStateGenerator,
"__EVENTVALIDATION" to form2.eventValidation,
"SubmitButton.x" to "0",
"SubmitButton.y" to "0",
"UsernameTextBox" to email,
"PasswordTextBox" to password
)))
return certificateAdapter.fromHtml(api.sendADFSForm(form3.action, mapOf(
"wa" to form3.wa,
"wresult" to form3.wresult,
"wctx" to form3.wctx
)))
}
private fun getADFSUrl(type: Scrapper.LoginType): String {

View file

@ -15,7 +15,6 @@ import io.github.wulkanowy.sdk.scrapper.exception.NoAccountFoundException
import io.github.wulkanowy.sdk.scrapper.exception.PasswordResetErrorException
import io.github.wulkanowy.sdk.scrapper.service.AccountService
import io.github.wulkanowy.sdk.scrapper.service.ServiceManager
import io.reactivex.Single
import java.net.URL
class AccountRepository(private val account: AccountService) {
@ -27,45 +26,45 @@ class AccountRepository(private val account: AccountService) {
const val SELECTOR_ADFS_CARDS = "#PassiveSignInButton"
}
fun getPasswordResetCaptcha(registerBaseUrl: String, symbol: String): Single<Pair<String, String>> {
return getPasswordResetUrl(registerBaseUrl, symbol.trim()).flatMap { (_, resetUrl) ->
account.getPasswordResetPageWithCaptcha(resetUrl)
.map { res -> resetUrl to res.recaptchaSiteKey }
}
suspend fun getPasswordResetCaptcha(registerBaseUrl: String, symbol: String): Pair<String, String> {
val (_, resetUrl) = getPasswordResetUrl(registerBaseUrl, symbol.trim())
val res = account.getPasswordResetPageWithCaptcha(resetUrl)
return resetUrl to res.recaptchaSiteKey
}
fun sendPasswordResetRequest(registerBaseUrl: String, symbol: String, email: String, captchaCode: String): Single<String> {
return getPasswordResetUrl(registerBaseUrl, symbol.trim()).flatMap { (type, url) ->
when (type) {
STANDARD -> account.sendPasswordResetRequest(url, email, captchaCode)
ADFSLight, ADFSLightScoped, ADFSLightCufs -> account.sendPasswordResetRequestADFSLight(url, email, captchaCode)
ADFS, ADFSCards -> account.getPasswordResetPageADFS(url).flatMap {
account.sendPasswordResetRequestADFS(url, email, captchaCode, (it.html.select("[type=hidden]").map { input ->
input.attr("name") to input.attr("value")
}).toMap().plus("btSend.x" to "5").plus("btSend.y" to "6"))
}
else -> Single.error(ScrapperException("Never happen"))
}
}.map { res ->
with(res.html) {
select(".ErrorMessage")?.text()?.let { // STANDARD
if (it.contains("Niepoprawny adres email")) throw InvalidEmailException(it)
}
select(".ErrorMessage, #ErrorTextLabel, #lblStatus")?.text()?.let { // STANDARD, ADFSLight, ADFSCards
if (it.contains("nie zostało odnalezione lub zostało zablokowane")) throw NoAccountFoundException(it)
if (it.contains("nie ma w systemie zarejestrowanych")) throw NoAccountFoundException(it) // 😀
if (it.contains("żądanie nie zostało poprawnie autoryzowane")) throw InvalidCaptchaException(it)
}
}
if (!res.message.startsWith("Wysłano wiadomość")) throw PasswordResetErrorException("Unexpected message: ${res.message}")
suspend fun sendPasswordResetRequest(registerBaseUrl: String, symbol: String, email: String, captchaCode: String): String {
val (type, url) = getPasswordResetUrl(registerBaseUrl, symbol.trim())
res.message
val res = when (type) {
STANDARD -> account.sendPasswordResetRequest(url, email, captchaCode)
ADFSLight, ADFSLightScoped, ADFSLightCufs -> account.sendPasswordResetRequestADFSLight(url, email, captchaCode)
ADFS, ADFSCards -> {
val page = account.getPasswordResetPageADFS(url)
account.sendPasswordResetRequestADFS(url, email, captchaCode, (page.html.select("[type=hidden]").map { input ->
input.attr("name") to input.attr("value")
}).toMap().plus("btSend.x" to "5").plus("btSend.y" to "6"))
}
else -> throw ScrapperException("Never happen")
}
with(res.html) {
select(".ErrorMessage")?.text()?.let { // STANDARD
if (it.contains("Niepoprawny adres email")) throw InvalidEmailException(it)
}
select(".ErrorMessage, #ErrorTextLabel, #lblStatus")?.text()?.let { // STANDARD, ADFSLight, ADFSCards
if (it.contains("nie zostało odnalezione lub zostało zablokowane")) throw NoAccountFoundException(it)
if (it.contains("nie ma w systemie zarejestrowanych")) throw NoAccountFoundException(it) // 😀
if (it.contains("żądanie nie zostało poprawnie autoryzowane")) throw InvalidCaptchaException(it)
}
}
if (!res.message.startsWith("Wysłano wiadomość")) throw PasswordResetErrorException("Unexpected message: ${res.message}")
return res.message
}
private fun getPasswordResetUrl(registerBaseUrl: String, symbol: String): Single<Pair<Scrapper.LoginType, String>> {
private suspend fun getPasswordResetUrl(registerBaseUrl: String, symbol: String): Pair<Scrapper.LoginType, String> {
val url = URL(registerBaseUrl)
return Single.just(when (url.host) {
val unlockUrl = when (url.host) {
"fakelog.cf" -> STANDARD to "https://cufs.fakelog.cf/Default/AccountManage/UnlockAccount"
"fakelog.tk" -> STANDARD to "https://cufs.fakelog.tk/Default/AccountManage/UnlockAccount"
"eszkola.opolskie.pl" -> ADFSCards to "https://konta.eszkola.opolskie.pl/maintenance/unlock.aspx"
@ -75,35 +74,36 @@ class AccountRepository(private val account: AccountService) {
"umt.tarnow.pl" -> ADFS to "https://konta.umt.tarnow.pl/maintenance/unlock.aspx"
"vulcan.net.pl" -> AUTO to "" // stream hack - bellow
else -> throw ScrapperException("Nieznany dziennik $url")
}).flatMap {
if (it.first == AUTO) getLoginType(ServiceManager.UrlGenerator(url, symbol, "")).map { loginType ->
loginType to when (loginType) {
STANDARD -> "https://cufs.vulcan.net.pl/$symbol/AccountManage/UnlockAccount"
ADFSLightScoped -> "https://adfslight.vulcan.net.pl/$symbol/AccountManage/UnlockAccountRequest"
else -> throw ScrapperException("Nieznany dziennik $registerBaseUrl, $loginType")
}
} else Single.just(it)
}
return if (unlockUrl.first == AUTO) {
val loginType = getLoginType(ServiceManager.UrlGenerator(url, symbol, ""))
loginType to when (loginType) {
STANDARD -> "https://cufs.vulcan.net.pl/$symbol/AccountManage/UnlockAccount"
ADFSLightScoped -> "https://adfslight.vulcan.net.pl/$symbol/AccountManage/UnlockAccountRequest"
else -> throw ScrapperException("Nieznany dziennik $registerBaseUrl, $loginType")
}
} else unlockUrl
}
private fun getLoginType(urlGenerator: ServiceManager.UrlGenerator): Single<Scrapper.LoginType> {
return account.getFormType(urlGenerator.generate(ServiceManager.UrlGenerator.Site.LOGIN) + "Account/LogOn").map { it.page }.map {
when {
it.select(SELECTOR_STANDARD).isNotEmpty() -> STANDARD
it.select(SELECTOR_ADFS).isNotEmpty() -> ADFS
it.select(SELECTOR_ADFS_LIGHT).isNotEmpty() -> {
it.selectFirst("form").attr("action").run {
when {
contains("cufs.edu.lublin.eu") -> ADFSLightCufs
startsWith("/LoginPage.aspx") -> ADFSLight
startsWith("/${urlGenerator.symbol}/LoginPage.aspx") -> ADFSLightScoped
else -> throw ScrapperException("Nieznany typ dziennika ADFS")
}
private suspend fun getLoginType(urlGenerator: ServiceManager.UrlGenerator): Scrapper.LoginType {
val page = account.getFormType(urlGenerator.generate(ServiceManager.UrlGenerator.Site.LOGIN) + "Account/LogOn").page
return when {
page.select(SELECTOR_STANDARD).isNotEmpty() -> STANDARD
page.select(SELECTOR_ADFS).isNotEmpty() -> ADFS
page.select(SELECTOR_ADFS_LIGHT).isNotEmpty() -> {
page.selectFirst("form").attr("action").run {
when {
contains("cufs.edu.lublin.eu") -> ADFSLightCufs
startsWith("/LoginPage.aspx") -> ADFSLight
startsWith("/${urlGenerator.symbol}/LoginPage.aspx") -> ADFSLightScoped
else -> throw ScrapperException("Nieznany typ dziennika ADFS")
}
}
it.select(SELECTOR_ADFS_CARDS).isNotEmpty() -> ADFSCards
else -> throw ScrapperException("Nieznany typ dziennika '${it.select("title")}")
}
page.select(SELECTOR_ADFS_CARDS).isNotEmpty() -> ADFSCards
else -> throw ScrapperException("Nieznany typ dziennika '${page.select("title")}")
}
}
}

View file

@ -3,97 +3,71 @@ package io.github.wulkanowy.sdk.scrapper.repository
import io.github.wulkanowy.sdk.scrapper.getScriptParam
import io.github.wulkanowy.sdk.scrapper.home.GovernmentUnit
import io.github.wulkanowy.sdk.scrapper.home.LuckyNumber
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorHandlerTransformer
import io.github.wulkanowy.sdk.scrapper.interceptor.handleErrors
import io.github.wulkanowy.sdk.scrapper.service.HomepageService
import io.reactivex.Single
class HomepageRepository(private val api: HomepageService) {
private lateinit var token: String
private fun getToken(): Single<String> {
if (::token.isInitialized) return Single.just(token)
private suspend fun getToken(): String {
if (::token.isInitialized) return token
return api.getStart().map {
getScriptParam("permissions", it)
}.map { it.apply { token = this } }
val page = api.getStart()
val permissions = getScriptParam("permissions", page)
token = permissions
return permissions
}
fun getSelfGovernments(): Single<List<GovernmentUnit>> {
return getToken().flatMap { api.getSelfGovernments(it) }
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
suspend fun getSelfGovernments(): List<GovernmentUnit> {
val res = api.getSelfGovernments(getToken()).handleErrors().data
return requireNotNull(res)
}
fun getStudentThreats(): Single<List<String>> {
return getToken().flatMap { api.getStudentThreats(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getStudentThreats(): List<String> {
return api.getStudentThreats(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getStudentsTrips(): Single<List<String>> {
return getToken().flatMap { api.getStudentsTrips(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getStudentsTrips(): List<String> {
return api.getStudentsTrips(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getLastGrades(): Single<List<String>> {
return getToken().flatMap { api.getLastGrades(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getLastGrades(): List<String> {
return api.getLastGrades(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getFreeDays(): Single<List<String>> {
return getToken().flatMap { api.getFreeDays(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getFreeDays(): List<String> {
return api.getFreeDays(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getKidsLuckyNumbers(): Single<List<LuckyNumber>> {
return getToken().flatMap { api.getKidsLuckyNumbers(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { res ->
res.map { unit ->
unit.content.map { school ->
school.content.map { number ->
LuckyNumber(
unitName = unit.name,
school = school.name,
number = number.name.substringAfterLast(": ").toInt()
)
}
}.flatten()
}.flatten()
}
suspend fun getKidsLuckyNumbers(): List<LuckyNumber> {
val res = api.getKidsLuckyNumbers(getToken()).handleErrors().data
return requireNotNull(res).map { unit ->
unit.content.map { school ->
school.content.map { number ->
LuckyNumber(
unitName = unit.name,
school = school.name,
number = number.name.substringAfterLast(": ").toInt()
)
}
}.flatten()
}.flatten()
}
fun getKidsLessonPlan(): Single<List<String>> {
return getToken().flatMap { api.getKidsLessonPlan(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }
.map { res -> res.map { it.name } }
suspend fun getKidsLessonPlan(): List<String> {
return api.getKidsLessonPlan(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getLastHomework(): Single<List<String>> {
return getToken().flatMap { api.getLastHomework(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getLastHomework(): List<String> {
return api.getLastHomework(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getLastTests(): Single<List<String>> {
return getToken().flatMap { api.getLastTests(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getLastTests(): List<String> {
return api.getLastTests(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
fun getLastStudentLessons(): Single<List<String>> {
return getToken().flatMap { api.getLastStudentLessons(it) }
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }.map { it[0].content }.map { res ->
res.map { it.name }
}
suspend fun getLastStudentLessons(): List<String> {
return api.getLastStudentLessons(getToken()).handleErrors().data.orEmpty()[0].content.map { it.name }
}
}

View file

@ -4,8 +4,8 @@ import com.google.gson.Gson
import io.github.wulkanowy.sdk.scrapper.ApiResponse
import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.getScriptParam
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorHandlerTransformer
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.interceptor.handleErrors
import io.github.wulkanowy.sdk.scrapper.messages.Attachment
import io.github.wulkanowy.sdk.scrapper.messages.DeleteMessageRequest
import io.github.wulkanowy.sdk.scrapper.messages.Message
@ -14,125 +14,101 @@ import io.github.wulkanowy.sdk.scrapper.messages.ReportingUnit
import io.github.wulkanowy.sdk.scrapper.messages.SendMessageRequest
import io.github.wulkanowy.sdk.scrapper.messages.SentMessage
import io.github.wulkanowy.sdk.scrapper.service.MessagesService
import io.reactivex.Single
import org.threeten.bp.LocalDateTime
import org.threeten.bp.format.DateTimeFormatter
class MessagesRepository(private val api: MessagesService) {
fun getReportingUnits(): Single<List<ReportingUnit>> {
return api.getUserReportingUnits().map { it.data.orEmpty() }
suspend fun getReportingUnits(): List<ReportingUnit> {
return api.getUserReportingUnits().data.orEmpty()
}
fun getRecipients(unitId: Int, role: Int = 2): Single<List<Recipient>> {
return api.getRecipients(unitId, role)
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { res ->
res.map { it.copy(shortName = it.name.normalizeRecipient()) }
suspend fun getRecipients(unitId: Int, role: Int = 2): List<Recipient> {
return api.getRecipients(unitId, role).handleErrors().data.orEmpty().map {
it.copy(shortName = it.name.normalizeRecipient())
}
}
suspend fun getReceivedMessages(startDate: LocalDateTime?, endDate: LocalDateTime?): List<Message> {
return api.getReceived(getDate(startDate), getDate(endDate)).handleErrors().data.orEmpty()
.map { it.copy(folderId = 1) }
.sortedBy { it.date }
.toList()
}
suspend fun getSentMessages(startDate: LocalDateTime?, endDate: LocalDateTime?): List<Message> {
return api.getSent(getDate(startDate), getDate(endDate)).handleErrors().data.orEmpty()
.map { message ->
message.copy(
messageId = message.id,
folderId = 2,
recipient = message.recipient?.split(";")?.joinToString("; ") { it.normalizeRecipient() }
)
}
.sortedBy { it.date }
.toList()
}
fun getReceivedMessages(startDate: LocalDateTime?, endDate: LocalDateTime?): Single<List<Message>> {
return api.getReceived(getDate(startDate), getDate(endDate))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { res ->
res.asSequence()
.map { it.copy(folderId = 1) }
.sortedBy { it.date }
.toList()
}
suspend fun getDeletedMessages(startDate: LocalDateTime?, endDate: LocalDateTime?): List<Message> {
return api.getDeleted(getDate(startDate), getDate(endDate)).handleErrors().data.orEmpty()
.map { it.apply { removed = true } }
.sortedBy { it.date }
.toList()
}
fun getSentMessages(startDate: LocalDateTime?, endDate: LocalDateTime?): Single<List<Message>> {
return api.getSent(getDate(startDate), getDate(endDate))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { res ->
res.asSequence()
.map { message ->
message.copy(
messageId = message.id,
folderId = 2,
recipient = message.recipient?.split(";")?.joinToString("; ") { it.normalizeRecipient() }
)
}
.sortedBy { it.date }
.toList()
}
suspend fun getMessageRecipients(messageId: Int, loginId: Int): List<Recipient> {
return (if (0 == loginId) api.getMessageRecipients(messageId).handleErrors()
else api.getMessageSender(loginId, messageId)).handleErrors().data.orEmpty().map { recipient ->
recipient.copy(shortName = recipient.name.normalizeRecipient())
}
}
fun getDeletedMessages(startDate: LocalDateTime?, endDate: LocalDateTime?): Single<List<Message>> {
return api.getDeleted(getDate(startDate), getDate(endDate))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { res ->
res.asSequence()
.map { it.apply { removed = true } }
.sortedBy { it.date }
.toList()
}
suspend fun getMessageDetails(messageId: Int, folderId: Int, read: Boolean, id: Int?): Message {
return api.getMessage(messageId, folderId, read, id).handleErrors().data!!
}
fun getMessageRecipients(messageId: Int, loginId: Int): Single<List<Recipient>> {
return (if (0 == loginId) api.getMessageRecipients(messageId)
else api.getMessageSender(loginId, messageId))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map {
it.map { recipient ->
recipient.copy(shortName = recipient.name.normalizeRecipient())
}
}
suspend fun getMessage(messageId: Int, folderId: Int, read: Boolean, id: Int?): String {
return api.getMessage(messageId, folderId, read, id).handleErrors().data?.content.orEmpty()
}
fun getMessageDetails(messageId: Int, folderId: Int, read: Boolean, id: Int?): Single<Message> {
return api.getMessage(messageId, folderId, read, id)
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
suspend fun getMessageAttachments(messageId: Int, folderId: Int): List<Attachment> {
return api.getMessage(messageId, folderId, false, null).handleErrors().data?.attachments.orEmpty()
}
fun getMessage(messageId: Int, folderId: Int, read: Boolean, id: Int?): Single<String> {
return api.getMessage(messageId, folderId, read, id)
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.content.orEmpty() }
suspend fun sendMessage(subject: String, content: String, recipients: List<Recipient>): SentMessage {
val res = api.getStart()
return api.sendMessage(
SendMessageRequest(
SendMessageRequest.Incoming(
recipients = recipients,
subject = subject,
content = content
)
),
getScriptParam("antiForgeryToken", res).ifBlank { throw ScrapperException("Can't find antiForgeryToken property!") },
getScriptParam("appGuid", res),
getScriptParam("version", res)
).handleErrors().data!!
}
fun getMessageAttachments(messageId: Int, folderId: Int): Single<List<Attachment>> {
return api.getMessage(messageId, folderId, false, null)
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.attachments.orEmpty() }
}
suspend fun deleteMessages(messages: List<Pair<Int, Int>>): Boolean {
val startPage = api.getStart()
val res = api.deleteMessage(
messages.map { (messageId, folderId) ->
DeleteMessageRequest(
messageId = messageId,
folderId = folderId
)
},
getScriptParam("antiForgeryToken", startPage),
getScriptParam("appGuid", startPage),
getScriptParam("version", startPage)
)
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> {
return api.getStart().flatMap { res ->
api.sendMessage(
SendMessageRequest(
SendMessageRequest.Incoming(
recipients = recipients,
subject = subject,
content = content
)
),
getScriptParam("antiForgeryToken", res).ifBlank { throw ScrapperException("Can't find antiForgeryToken property!") },
getScriptParam("appGuid", res),
getScriptParam("version", res)
)
}.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
}
val apiResponse = if (res.isBlank()) throw VulcanException("Unexpected empty response. Message(s) may already be deleted")
else Gson().fromJson(res, ApiResponse::class.java)
fun deleteMessages(messages: List<Pair<Int, Int>>): Single<Boolean> {
return api.getStart().flatMap { res ->
api.deleteMessage(
messages.map { (messageId, folderId) ->
DeleteMessageRequest(
messageId = messageId,
folderId = folderId
)
},
getScriptParam("antiForgeryToken", res),
getScriptParam("appGuid", res),
getScriptParam("version", res)
)
}.flatMap {
if (it.isBlank()) Single.error(VulcanException("Unexpected empty response. Message(s) may already be deleted"))
else Single.just(Gson().fromJson(it, ApiResponse::class.java))
}.compose(ErrorHandlerTransformer()).map { it.success }
return apiResponse.success
}
private fun String.normalizeRecipient(): String {

View file

@ -5,7 +5,7 @@ import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.exception.TemporarilyDisabledException
import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
import io.github.wulkanowy.sdk.scrapper.getScriptParam
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorHandlerTransformer
import io.github.wulkanowy.sdk.scrapper.interceptor.handleErrors
import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
import io.github.wulkanowy.sdk.scrapper.login.CertificateResponse
import io.github.wulkanowy.sdk.scrapper.login.LoginHelper
@ -20,8 +20,6 @@ import io.github.wulkanowy.sdk.scrapper.service.RegisterService
import io.github.wulkanowy.sdk.scrapper.service.ServiceManager
import io.github.wulkanowy.sdk.scrapper.service.StudentAndParentService
import io.github.wulkanowy.sdk.scrapper.service.StudentService
import io.reactivex.Observable
import io.reactivex.Single
import org.jsoup.Jsoup
import org.jsoup.parser.Parser
import org.slf4j.LoggerFactory
@ -44,128 +42,118 @@ class RegisterRepository(
private val logger = LoggerFactory.getLogger(this::class.java)
}
fun getStudents(): Single<List<Student>> {
return getSymbols().flatMapObservable { Observable.fromIterable(it) }.flatMap { (symbol, certificate) ->
loginHelper.sendCertificate(certificate, email, certificate.action.replace(startSymbol.getNormalizedSymbol(), symbol))
.onErrorResumeNext { t ->
if (t is AccountPermissionException) Single.just(SendCertificateResponse())
else Single.error(t)
}
.flatMapObservable { Observable.fromIterable(if (useNewStudent) it.studentSchools else it.oldStudentSchools) }
.flatMapSingle { moduleUrl ->
getLoginType(symbol).flatMap { loginType ->
getStudents(symbol, moduleUrl.attr("href")).map { students ->
students.map { student ->
Student(
email = email,
symbol = symbol,
studentId = student.id,
studentName = student.name,
schoolSymbol = getExtractedSchoolSymbolFromUrl(moduleUrl.attr("href")),
schoolShortName = moduleUrl.text().takeIf { "Uczeń" !in it }.orEmpty(),
schoolName = student.description,
className = student.className,
classId = student.classId,
baseUrl = url.generate(ServiceManager.UrlGenerator.Site.BASE),
loginType = loginType,
isParent = student.isParent
)
}
}
}
}
}.toList().map {
it.flatten().distinctBy { pupil ->
listOf(pupil.studentId, pupil.classId, pupil.schoolSymbol)
suspend fun getStudents(): List<Student> {
return getSymbols().map { (symbol, certificate) ->
val cert = try {
loginHelper.sendCertificate(certificate, email, certificate.action.replace(startSymbol.getNormalizedSymbol(), symbol))
} catch (e: AccountPermissionException) {
SendCertificateResponse()
}
}
(if (useNewStudent) cert.studentSchools else cert.oldStudentSchools).map { moduleUrl ->
val loginType = getLoginType(symbol)
getStudents(symbol, moduleUrl.attr("href")).map { student ->
Student(
email = email,
symbol = symbol,
studentId = student.id,
studentName = student.name,
schoolSymbol = getExtractedSchoolSymbolFromUrl(moduleUrl.attr("href")),
schoolShortName = moduleUrl.text().takeIf { "Uczeń" !in it }.orEmpty(),
schoolName = student.description,
className = student.className,
classId = student.classId,
baseUrl = url.generate(ServiceManager.UrlGenerator.Site.BASE),
loginType = loginType,
isParent = student.isParent
)
}
}.flatten()
}.flatten().distinctBy { pupil -> listOf(pupil.studentId, pupil.classId, pupil.schoolSymbol) }
}
private fun getSymbols(): Single<List<Pair<String, CertificateResponse>>> {
return getLoginType(startSymbol.getNormalizedSymbol()).map {
loginHelper.apply { loginType = it }
}.flatMap { login ->
login.sendCredentials(email, password).flatMap { Single.just(it) }.flatMap { cert ->
Single.just(Jsoup.parse(cert.wresult.replace(":", ""), "", Parser.xmlParser())
.select("[AttributeName$=\"Instance\"] samlAttributeValue")
.map { it.text().trim() }
.apply { logger.debug("$this") }
.filter { it.matches("[a-zA-Z0-9]*".toRegex()) } // early filter invalid symbols
.map { Pair(it, cert) }
)
}
}
private suspend fun getSymbols(): List<Pair<String, CertificateResponse>> {
val symbolLoginType = getLoginType(startSymbol.getNormalizedSymbol())
val cert = loginHelper.apply { loginType = symbolLoginType }.sendCredentials(email, password)
return Jsoup.parse(cert.wresult.replace(":", ""), "", Parser.xmlParser())
.select("[AttributeName$=\"Instance\"] samlAttributeValue")
.map { it.text().trim() }
.apply { logger.debug("$this") }
.filter { it.matches("[a-zA-Z0-9]*".toRegex()) } // early filter invalid symbols
.map { Pair(it, cert) }
}
private fun getLoginType(symbol: String): Single<Scrapper.LoginType> {
private suspend fun getLoginType(symbol: String): Scrapper.LoginType {
return getLoginType(url.also { it.symbol = symbol })
}
private fun getLoginType(urlGenerator: ServiceManager.UrlGenerator): Single<Scrapper.LoginType> {
return register.getFormType(urlGenerator.generate(ServiceManager.UrlGenerator.Site.LOGIN) + "Account/LogOn").map { it.page }.map {
when {
it.select(SELECTOR_STANDARD).isNotEmpty() -> Scrapper.LoginType.STANDARD
it.select(SELECTOR_ADFS).isNotEmpty() -> Scrapper.LoginType.ADFS
it.select(SELECTOR_ADFS_LIGHT).isNotEmpty() -> {
it.selectFirst("form").attr("action").run {
when {
contains("cufs.edu.lublin.eu") -> Scrapper.LoginType.ADFSLightCufs
startsWith("/LoginPage.aspx") -> Scrapper.LoginType.ADFSLight
startsWith("/${urlGenerator.symbol}/LoginPage.aspx") -> Scrapper.LoginType.ADFSLightScoped
else -> throw ScrapperException("Nieznany typ dziennika ADFS")
}
private suspend fun getLoginType(urlGenerator: ServiceManager.UrlGenerator): Scrapper.LoginType {
val page = register.getFormType(urlGenerator.generate(ServiceManager.UrlGenerator.Site.LOGIN) + "Account/LogOn").page
return when {
page.select(SELECTOR_STANDARD).isNotEmpty() -> Scrapper.LoginType.STANDARD
page.select(SELECTOR_ADFS).isNotEmpty() -> Scrapper.LoginType.ADFS
page.select(SELECTOR_ADFS_LIGHT).isNotEmpty() -> {
page.selectFirst("form").attr("action").run {
when {
contains("cufs.edu.lublin.eu") -> Scrapper.LoginType.ADFSLightCufs
startsWith("/LoginPage.aspx") -> Scrapper.LoginType.ADFSLight
startsWith("/${urlGenerator.symbol}/LoginPage.aspx") -> Scrapper.LoginType.ADFSLightScoped
else -> throw ScrapperException("Nieznany typ dziennika ADFS")
}
}
it.select(SELECTOR_ADFS_CARDS).isNotEmpty() -> Scrapper.LoginType.ADFSCards
else -> throw ScrapperException("Nieznany typ dziennika")
}
page.select(SELECTOR_ADFS_CARDS).isNotEmpty() -> Scrapper.LoginType.ADFSCards
else -> throw ScrapperException("Nieznany typ dziennika")
}
}
private fun getStudents(symbol: String, schoolUrl: String): Single<List<StudentAndParentResponse.Student>> {
private suspend fun getStudents(symbol: String, schoolUrl: String): List<StudentAndParentResponse.Student> {
url.schoolId = getExtractedSchoolSymbolFromUrl(schoolUrl)
url.symbol = symbol
return if (!useNewStudent) snp.getSchoolInfo(schoolUrl).map { res ->
return if (!useNewStudent) {
val res = snp.getSchoolInfo(schoolUrl)
res.students.map { student ->
student.apply {
description = res.schoolName
className = res.diaries[0].name
}
}
} else student.getStart(url.generate(ServiceManager.UrlGenerator.Site.STUDENT) + "Start").onErrorResumeNext {
if (it is TemporarilyDisabledException) Single.just("")
else Single.error(it)
}.flatMap { startPage ->
if (startPage.isBlank()) return@flatMap Single.just<List<StudentAndParentResponse.Student>>(listOf())
student.getUserCache(
} else {
val startPage = try {
student.getStart(url.generate(ServiceManager.UrlGenerator.Site.STUDENT) + "Start")
} catch (e: TemporarilyDisabledException) {
return listOf()
}
val cache = student.getUserCache(
url.generate(ServiceManager.UrlGenerator.Site.STUDENT) + "UczenCache.mvc/Get",
getScriptParam("antiForgeryToken", startPage),
getScriptParam("appGuid", startPage),
getScriptParam("version", startPage)
).flatMap { cache ->
student.getSchoolInfo(url.generate(ServiceManager.UrlGenerator.Site.STUDENT) + "UczenDziennik.mvc/Get")
.compose(ErrorHandlerTransformer())
.map { diaries ->
diaries.data.orEmpty()
.filter { diary -> diary.semesters?.isNotEmpty() ?: false }
.sortedByDescending { diary -> diary.level }
.distinctBy { diary -> listOf(diary.studentId, diary.semesters!![0].classId) }
.map {
StudentAndParentResponse.Student().apply {
id = it.studentId
name = "${it.studentName} ${it.studentSurname}"
description = getScriptParam("organizationName", startPage, it.symbol + " " + (it.year - it.level + 1))
className = it.level.toString() + it.symbol
classId = it.semesters!![0].classId
isParent = cache.data?.isParent ?: false
}
}
.ifEmpty {
logger.debug("No supported student found: $diaries")
emptyList()
}
)
val diaries = student
.getSchoolInfo(url.generate(ServiceManager.UrlGenerator.Site.STUDENT) + "UczenDziennik.mvc/Get")
.handleErrors()
.data.orEmpty()
diaries.filter { diary -> diary.semesters?.isNotEmpty() ?: false }
.sortedByDescending { diary -> diary.level }
.distinctBy { diary -> listOf(diary.studentId, diary.semesters!![0].classId) }
.map {
StudentAndParentResponse.Student().apply {
id = it.studentId
name = "${it.studentName} ${it.studentSurname}"
description = getScriptParam("organizationName", startPage, it.symbol + " " + (it.year - it.level + 1))
className = it.level.toString() + it.symbol
classId = it.semesters!![0].classId
isParent = cache.data?.isParent ?: false
}
}
}
.ifEmpty {
logger.debug("No supported student found: $diaries")
emptyList()
}
}
}

View file

@ -25,7 +25,6 @@ import io.github.wulkanowy.sdk.scrapper.timetable.TimetableParser
import io.github.wulkanowy.sdk.scrapper.toDate
import io.github.wulkanowy.sdk.scrapper.toFormat
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.reactivex.Single
import org.threeten.bp.LocalDate
import org.threeten.bp.Month
import java.util.Calendar
@ -34,207 +33,189 @@ import java.util.TimeZone
class StudentAndParentRepository(private val api: StudentAndParentService) {
fun getAttendance(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Attendance>> {
suspend fun getAttendance(startDate: LocalDate, endDate: LocalDate? = null): List<Attendance> {
val end = endDate ?: startDate.plusDays(4)
return api.getAttendance(startDate.getLastMonday().toTick()).map { res ->
res.rows.flatMap { row ->
row.lessons.mapIndexedNotNull { i, it ->
if ("null" == it.subject) return@mapIndexedNotNull null // fix empty months
it.apply {
date = res.days[i]
number = row.number
presence = it.type == Types.PRESENCE || it.type == Types.ABSENCE_FOR_SCHOOL_REASONS
absence = it.type == Types.ABSENCE_UNEXCUSED || it.type == Types.ABSENCE_EXCUSED
lateness = it.type == Types.EXCUSED_LATENESS || it.type == Types.UNEXCUSED_LATENESS
excused = it.type == Types.ABSENCE_EXCUSED || it.type == Types.EXCUSED_LATENESS
exemption = it.type == Types.EXEMPTION
excusable = res.excuseActiveSnp.isNotEmpty() && (absence || lateness) && !excused
}
}
}.asSequence().filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= end
}.sortedWith(compareBy({ it.date }, { it.number })).toList()
}
}
fun getAttendanceSummary(subjectId: Int?): Single<List<AttendanceSummary>> {
return api.getAttendanceSummary(subjectId).map { res ->
res.months.mapIndexedNotNull { i, month ->
if (res.summaryRows.all { it.value[i].isBlank() }) return@mapIndexedNotNull null
AttendanceSummary(romanToMonthEnum(month),
res.summaryRows[0].value[i].toIntOrNull() ?: 0,
res.summaryRows[1].value[i].toIntOrNull() ?: 0,
res.summaryRows[2].value[i].toIntOrNull() ?: 0,
res.summaryRows[3].value[i].toIntOrNull() ?: 0,
res.summaryRows[4].value[i].toIntOrNull() ?: 0,
res.summaryRows[5].value[i].toIntOrNull() ?: 0,
res.summaryRows[6].value[i].toIntOrNull() ?: 0
)
}
}
}
fun getSubjects(): Single<List<Subject>> {
return api.getAttendanceSummary(-1).map { it.subjects }
}
fun getExams(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Exam>> {
val end = endDate ?: startDate.plusDays(4)
return api.getExams(startDate.getLastMonday().toTick()).map { res ->
res.days.flatMap { day ->
day.exams.map { exam ->
exam.apply {
if (group.contains(" ")) group = ""
date = day.date
}
}
}.asSequence().filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= end
}.sortedBy { it.date }.toList()
}
}
fun getGrades(semesterId: Int?): Single<Pair<List<Grade>, List<GradeSummary>>> {
return getGradesDetails(semesterId).flatMap { details ->
getGradesSummary(semesterId).map { summary ->
details to summary
}
}
}
fun getGradesDetails(semesterId: Int?): Single<List<Grade>> {
return api.getGrades(semesterId).map { res ->
res.grades.asSequence().map { grade ->
grade.apply {
comment = if (entry.length > 4) "$entry ($comment)".replace(" ($comment)", "") else comment
entry = entry.run { if (length > 4) "..." else this }
if (entry == comment) comment = ""
if (description == symbol) description = ""
}
}.toList().sortedByDescending { it.date }
}
}
fun getGradesSummary(semesterId: Int?): Single<List<GradeSummary>> {
return api.getGradesSummary(semesterId).map { res ->
res.subjects.asSequence().map { summary ->
summary.apply {
predicted = if (predicted != "-") getGradeShortValue(predicted) else ""
final = if (final != "-") getGradeShortValue(final) else ""
}
}.sortedBy { it.name }.toList()
}
}
fun getGradesStatistics(semesterId: Int, annual: Boolean): Single<List<GradeStatistics>> {
return api.getGradesStatistics(if (!annual) 1 else 2, semesterId).map { res ->
res.items.map {
val res = api.getAttendance(startDate.getLastMonday().toTick())
return res.rows.flatMap { row ->
row.lessons.mapIndexedNotNull { i, it ->
if ("null" == it.subject) return@mapIndexedNotNull null // fix empty months
it.apply {
grade = getGradeShortValue(grade)
gradeValue = getGradeShortValue(grade).toIntOrNull() ?: 0
this.semesterId = res.semesterId
date = res.days[i]
number = row.number
presence = it.type == Types.PRESENCE || it.type == Types.ABSENCE_FOR_SCHOOL_REASONS
absence = it.type == Types.ABSENCE_UNEXCUSED || it.type == Types.ABSENCE_EXCUSED
lateness = it.type == Types.EXCUSED_LATENESS || it.type == Types.UNEXCUSED_LATENESS
excused = it.type == Types.ABSENCE_EXCUSED || it.type == Types.EXCUSED_LATENESS
exemption = it.type == Types.EXEMPTION
excusable = res.excuseActiveSnp.isNotEmpty() && (absence || lateness) && !excused
}
}
}.asSequence().filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= end
}.sortedWith(compareBy({ it.date }, { it.number })).toList()
}
suspend fun getAttendanceSummary(subjectId: Int?): List<AttendanceSummary> {
val res = api.getAttendanceSummary(subjectId)
return res.months.mapIndexedNotNull { i, month ->
if (res.summaryRows.all { it.value[i].isBlank() }) return@mapIndexedNotNull null
AttendanceSummary(romanToMonthEnum(month),
res.summaryRows[0].value[i].toIntOrNull() ?: 0,
res.summaryRows[1].value[i].toIntOrNull() ?: 0,
res.summaryRows[2].value[i].toIntOrNull() ?: 0,
res.summaryRows[3].value[i].toIntOrNull() ?: 0,
res.summaryRows[4].value[i].toIntOrNull() ?: 0,
res.summaryRows[5].value[i].toIntOrNull() ?: 0,
res.summaryRows[6].value[i].toIntOrNull() ?: 0
)
}
}
suspend fun getSubjects(): List<Subject> {
return api.getAttendanceSummary(-1).subjects
}
suspend fun getExams(startDate: LocalDate, endDate: LocalDate? = null): List<Exam> {
val end = endDate ?: startDate.plusDays(4)
val res = api.getExams(startDate.getLastMonday().toTick())
return res.days.flatMap { day ->
day.exams.map { exam ->
exam.apply {
if (group.contains(" ")) group = ""
date = day.date
}
}
}.asSequence().filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= end
}.sortedBy { it.date }.toList()
}
suspend fun getGrades(semesterId: Int?): Pair<List<Grade>, List<GradeSummary>> {
return getGradesDetails(semesterId) to getGradesSummary(semesterId)
}
suspend fun getGradesDetails(semesterId: Int?): List<Grade> {
val res = api.getGrades(semesterId)
return res.grades.asSequence().map { grade ->
grade.apply {
comment = if (entry.length > 4) "$entry ($comment)".replace(" ($comment)", "") else comment
entry = entry.run { if (length > 4) "..." else this }
if (entry == comment) comment = ""
if (description == symbol) description = ""
}
}.toList().sortedByDescending { it.date }
}
suspend fun getGradesSummary(semesterId: Int?): List<GradeSummary> {
val res = api.getGradesSummary(semesterId)
return res.subjects.asSequence().map { summary ->
summary.apply {
predicted = if (predicted != "-") getGradeShortValue(predicted) else ""
final = if (final != "-") getGradeShortValue(final) else ""
}
}.sortedBy { it.name }.toList()
}
suspend fun getGradesStatistics(semesterId: Int, annual: Boolean): List<GradeStatistics> {
val res = api.getGradesStatistics(if (!annual) 1 else 2, semesterId)
return res.items.map {
it.apply {
grade = getGradeShortValue(grade)
gradeValue = getGradeShortValue(grade).toIntOrNull() ?: 0
this.semesterId = res.semesterId
}
}
}
fun getHomework(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Homework>> {
suspend fun getHomework(startDate: LocalDate, endDate: LocalDate? = null): List<Homework> {
val end = endDate ?: startDate.plusDays(4)
return api.getHomework(startDate.toTick()).map { res ->
res.items.asSequence().map {
it.apply {
date = res.date
}
}.filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= end
}.sortedWith(compareBy({ it.date }, { it.subject })).toList()
}
val res = api.getHomework(startDate.toTick())
return res.items.asSequence().map {
it.apply {
date = res.date
}
}.filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= end
}.sortedWith(compareBy({ it.date }, { it.subject })).toList()
}
fun getNotes(): Single<List<Note>> {
return api.getNotes().map { res ->
res.notes.asSequence().mapIndexed { i, note ->
note.apply {
if (teacher == teacherSymbol) teacherSymbol = ""
date = res.dates[i]
}
}.sortedWith(compareBy({ it.date }, { it.category })).toList()
}
suspend fun getNotes(): List<Note> {
val res = api.getNotes()
return res.notes.asSequence().mapIndexed { i, note ->
note.apply {
if (teacher == teacherSymbol) teacherSymbol = ""
date = res.dates[i]
}
}.sortedWith(compareBy({ it.date }, { it.category })).toList()
}
fun getRegisteredDevices(): Single<List<Device>> {
return api.getRegisteredDevices().map { it.devices }
suspend fun getRegisteredDevices(): List<Device> {
return api.getRegisteredDevices().devices
}
fun getToken(): Single<TokenResponse> {
suspend fun getToken(): TokenResponse {
return api.getToken()
}
fun unregisterDevice(id: Int): Single<Boolean> {
return api.unregisterDevice(id).map { !it.devices.any { device -> device.id == id } }
suspend fun unregisterDevice(id: Int): Boolean {
return api.unregisterDevice(id).devices.any { device -> device.id == id }
}
fun getTeachers(): Single<List<Teacher>> {
return api.getSchoolAndTeachers().map { res ->
res.subjects.flatMap { subject ->
subject.teachers.split(", ").map { teacher ->
teacher.split(" [").run {
Teacher(first().getEmptyIfDash(), last().removeSuffix("]").getEmptyIfDash(), subject.name.let {
if (it.isBlank()) ""
else it
})
}
suspend fun getTeachers(): List<Teacher> {
val res = api.getSchoolAndTeachers()
return res.subjects.flatMap { subject ->
subject.teachers.split(", ").map { teacher ->
teacher.split(" [").run {
Teacher(first().getEmptyIfDash(), last().removeSuffix("]").getEmptyIfDash(), subject.name.let {
if (it.isBlank()) ""
else it
})
}
}.sortedWith(compareBy({ it.subject }, { it.name }))
}
}
fun getSchool(): Single<School> {
return api.getSchoolAndTeachers().map {
School(it.name, it.address, it.contact, it.headmaster, it.pedagogue)
}
}
fun getStudentInfo(): Single<StudentInfo> {
return api.getStudentInfo().map {
it.apply {
student.polishCitizenship = if ("Tak" == student.polishCitizenship) "1" else "0"
}
}.sortedWith(compareBy({ it.subject }, { it.name }))
}
suspend fun getSchool(): School {
val res = api.getSchoolAndTeachers()
return School(res.name, res.address, res.contact, res.headmaster, res.pedagogue)
}
suspend fun getStudentInfo(): StudentInfo {
return api.getStudentInfo().apply {
student.polishCitizenship = if ("Tak" == student.polishCitizenship) "1" else "0"
}
}
fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Timetable>> {
return api.getTimetable(startDate.getLastMonday().toTick()).map { res ->
res.rows.flatMap { row ->
row.lessons.asSequence().mapIndexed { i, it ->
it.apply {
date = res.days[i]
start = "${date.toLocalDate().toFormat("yyy-MM-dd")} ${row.startTime}".toDate("yyyy-MM-dd HH:mm")
end = "${date.toLocalDate().toFormat("yyy-MM-dd")} ${row.endTime}".toDate("yyyy-MM-dd HH:mm")
number = row.number
}
}.mapNotNull { TimetableParser().getTimetable(it) }.toList()
}.asSequence().filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= endDate ?: startDate.plusDays(4)
}.sortedWith(compareBy({ it.date }, { it.number })).toList()
}
suspend fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null): List<Timetable> {
val res = api.getTimetable(startDate.getLastMonday().toTick())
return res.rows.flatMap { row ->
row.lessons.asSequence().mapIndexed { i, it ->
it.apply {
date = res.days[i]
start = "${date.toLocalDate().toFormat("yyy-MM-dd")} ${row.startTime}".toDate("yyyy-MM-dd HH:mm")
end = "${date.toLocalDate().toFormat("yyy-MM-dd")} ${row.endTime}".toDate("yyyy-MM-dd HH:mm")
number = row.number
}
}.mapNotNull { TimetableParser().getTimetable(it) }.toList()
}.asSequence().filter {
it.date.toLocalDate() >= startDate && it.date.toLocalDate() <= endDate ?: startDate.plusDays(4)
}.sortedWith(compareBy({ it.date }, { it.number })).toList()
}
fun getCompletedLessons(start: LocalDate, endDate: LocalDate?, subjectId: Int): Single<List<CompletedLesson>> {
suspend fun getCompletedLessons(start: LocalDate, endDate: LocalDate?, subjectId: Int): List<CompletedLesson> {
val end = endDate ?: start.plusMonths(1)
return api.getCompletedLessons(start.toTick(), end.toTick(), subjectId).map { res ->
val res = api.getCompletedLessons(start.toTick(), end.toTick(), subjectId)
return res.items.mapNotNull {
lateinit var lastDate: Date
res.items.asSequence().mapNotNull {
if (it.subject.isBlank()) {
lastDate = it.date
return@mapNotNull null
}
it.apply { date = lastDate }
}.sortedWith(compareBy({ it.date }, { it.number })).toList().filter {
it.date.toLocalDate() >= start && it.date.toLocalDate() <= end
if (it.subject.isBlank()) {
lastDate = it.date
return@mapNotNull null
}
it.apply { date = lastDate }
}.sortedWith(compareBy({ it.date }, { it.number })).filter {
it.date.toLocalDate() >= start && it.date.toLocalDate() <= end
}
}

View file

@ -3,8 +3,6 @@ package io.github.wulkanowy.sdk.scrapper.repository
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.register.Semester
import io.github.wulkanowy.sdk.scrapper.service.StudentAndParentService
import io.reactivex.Observable
import io.reactivex.Single
class StudentAndParentStartRepository(
private val symbol: String,
@ -13,23 +11,21 @@ class StudentAndParentStartRepository(
private val api: StudentAndParentService
) {
fun getSemesters(): Single<List<Semester>> {
return api.getUserInfo(studentId).map {
it.apply {
if (!it.title.startsWith("Witryna ucznia i rodzica")) throw VulcanException("Unknow page with title: ${it.title}")
suspend fun getSemesters(): List<Semester> {
val userInfo = api.getUserInfo(studentId)
if (!userInfo.title.startsWith("Witryna ucznia i rodzica")) throw VulcanException("Unknow page with title: ${userInfo.title}")
return userInfo.diaries.reversed().map { diary ->
val res = api.getDiaryInfo(diary.id, "/$symbol/$schoolSymbol/Oceny.mvc/Wszystkie")
if (!res.title.endsWith("Oceny")) throw VulcanException("Unknow page with title: ${res.title}")
res.semesters.map {
Semester(diary.id,
diary.name,
diary.name.substringAfter(" ").toInt(),
it.semesterId,
it.semesterNumber,
"selected" == it.current && "selected" == diary.current)
}
}.flatMapObservable { Observable.fromIterable(it.diaries.reversed()) }.flatMapSingle { diary ->
api.getDiaryInfo(diary.id, "/$symbol/$schoolSymbol/Oceny.mvc/Wszystkie").map { res ->
if (!res.title.endsWith("Oceny")) throw VulcanException("Unknow page with title: ${res.title}")
res.semesters.map {
Semester(diary.id,
diary.name,
diary.name.substringAfter(" ").toInt(),
it.semesterId,
it.semesterNumber,
"selected" == it.current && "selected" == diary.current)
}
}
}.toList().map { it.flatten() }
}.flatten()
}
}

View file

@ -32,8 +32,8 @@ import io.github.wulkanowy.sdk.scrapper.homework.Homework
import io.github.wulkanowy.sdk.scrapper.homework.HomeworkRequest
import io.github.wulkanowy.sdk.scrapper.homework.mapHomework
import io.github.wulkanowy.sdk.scrapper.homework.mapHomeworkList
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorHandlerTransformer
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
import io.github.wulkanowy.sdk.scrapper.interceptor.handleErrors
import io.github.wulkanowy.sdk.scrapper.mobile.Device
import io.github.wulkanowy.sdk.scrapper.mobile.TokenResponse
import io.github.wulkanowy.sdk.scrapper.mobile.UnregisterDeviceRequest
@ -51,7 +51,6 @@ import io.github.wulkanowy.sdk.scrapper.timetable.mapCompletedLessonsList
import io.github.wulkanowy.sdk.scrapper.timetable.mapTimetableList
import io.github.wulkanowy.sdk.scrapper.toDate
import io.github.wulkanowy.sdk.scrapper.toFormat
import io.reactivex.Single
import org.jsoup.Jsoup
import org.threeten.bp.LocalDate
@ -65,184 +64,172 @@ class StudentRepository(private val api: StudentService) {
private fun LocalDate.toISOFormat(): String = toFormat("yyyy-MM-dd'T00:00:00'")
private fun getCache(): Single<CacheResponse> {
if (::cache.isInitialized) return Single.just(cache)
private suspend fun getCache(): CacheResponse {
if (::cache.isInitialized) return cache
return api.getStart("Start").flatMap {
api.getUserCache(
getScriptParam("antiForgeryToken", it),
getScriptParam("appGuid", it),
getScriptParam("version", it)
)
}.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.apply { cache = this } }
val it = api.getStart("Start")
val res = api.getUserCache(
getScriptParam("antiForgeryToken", it),
getScriptParam("appGuid", it),
getScriptParam("version", it)
).handleErrors()
val data = requireNotNull(res.data)
cache = data
return data
}
private fun getTimes(): Single<List<CacheResponse.Time>> {
if (::times.isInitialized) return Single.just(times)
private suspend fun getTimes(): List<CacheResponse.Time> {
if (::times.isInitialized) return times
return getCache().map { res -> res.times }.map { list ->
list.apply { times = this }
val res = getCache()
times = res.times
return res.times
}
suspend fun getAttendance(startDate: LocalDate, endDate: LocalDate?): List<Attendance> {
return api.getAttendance(AttendanceRequest(startDate.toDate()))
.handleErrors()
.data?.mapAttendanceList(startDate, endDate, getTimes())!!
}
suspend fun getAttendanceSummary(subjectId: Int?): List<AttendanceSummary> {
return api.getAttendanceStatistics(AttendanceSummaryRequest(subjectId))
.handleErrors()
.data?.mapAttendanceSummaryList(gson)!!
}
suspend fun excuseForAbsence(absents: List<Absent>, content: String?): Boolean {
val it = api.getStart("Start")
return api.excuseForAbsence(
getScriptParam("antiForgeryToken", it),
getScriptParam("appGuid", it),
getScriptParam("version", it),
AttendanceExcuseRequest(
AttendanceExcuseRequest.Excuse(
absents = absents.map { absence ->
AttendanceExcuseRequest.Excuse.Absent(
date = absence.date.toFormat("yyyy-MM-dd'T'HH:mm:ss"),
timeId = absence.timeId
)
},
content = content
)
)
).handleErrors().success
}
suspend fun getSubjects(): List<Subject> {
return api.getAttendanceSubjects().handleErrors().data.orEmpty()
}
suspend fun getExams(startDate: LocalDate, endDate: LocalDate? = null): List<Exam> {
return api.getExams(ExamRequest(startDate.toDate(), startDate.getSchoolYear()))
.handleErrors()
.data.orEmpty().mapExamsList(startDate, endDate)
}
suspend fun getGrades(semesterId: Int?): Pair<List<Grade>, List<GradeSummary>> {
val data = api.getGrades(GradeRequest(semesterId))
.handleErrors()
.data
return requireNotNull(data).mapGradesList() to data.mapGradesSummary()
}
suspend fun getGradesDetails(semesterId: Int?): List<Grade> {
return api.getGrades(GradeRequest(semesterId))
.handleErrors()
.data?.mapGradesList()!!
}
suspend fun getGradesSummary(semesterId: Int?): List<GradeSummary> {
return api.getGrades(GradeRequest(semesterId))
.handleErrors()
.data?.mapGradesSummary()!!
}
suspend fun getGradesPartialStatistics(semesterId: Int): List<GradeStatistics> {
return api.getGradesPartialStatistics(GradesStatisticsRequest(semesterId))
.handleErrors()
.data.orEmpty().mapGradesStatisticsPartial(semesterId)
}
suspend fun getGradesPointsStatistics(semesterId: Int): List<GradePointsSummary> {
return api.getGradesPointsStatistics(GradesStatisticsRequest(semesterId))
.handleErrors()
.data.orEmpty().mapGradesStatisticsPoints(semesterId)
}
suspend fun getGradesAnnualStatistics(semesterId: Int): List<GradeStatistics> {
return api.getGradesAnnualStatistics(GradesStatisticsRequest(semesterId))
.handleErrors()
.data.orEmpty().mapGradesStatisticsAnnual(semesterId)
}
suspend fun getHomework(startDate: LocalDate, endDate: LocalDate? = null): List<Homework> {
return try {
api.getHomework(HomeworkRequest(startDate.toDate(), startDate.getSchoolYear(), -1))
.handleErrors()
.data.orEmpty().mapHomework(startDate, endDate)
} catch (e: InvalidPathException) {
api.getZadaniaDomowe(ExamRequest(startDate.toDate(), startDate.getSchoolYear()))
.handleErrors()
.data.orEmpty().mapHomeworkList(startDate, endDate)
}
}
fun getAttendance(startDate: LocalDate, endDate: LocalDate?): Single<List<Attendance>> {
return api.getAttendance(AttendanceRequest(startDate.toDate()))
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.mapAttendanceList(startDate, endDate, ::getTimes)
}
fun getAttendanceSummary(subjectId: Int?): Single<List<AttendanceSummary>> {
return api.getAttendanceStatistics(AttendanceSummaryRequest(subjectId))
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.mapAttendanceSummaryList(gson) }
}
fun excuseForAbsence(absents: List<Absent>, content: String?): Single<Boolean> {
return api.getStart("Start").flatMap {
api.excuseForAbsence(
getScriptParam("antiForgeryToken", it),
getScriptParam("appGuid", it),
getScriptParam("version", it),
AttendanceExcuseRequest(
AttendanceExcuseRequest.Excuse(
absents = absents.map { absence ->
AttendanceExcuseRequest.Excuse.Absent(
date = absence.date.toFormat("yyyy-MM-dd'T'HH:mm:ss"),
timeId = absence.timeId
)
},
content = content
)
)
)
}.compose(ErrorHandlerTransformer()).map { it.success }
}
fun getSubjects(): Single<List<Subject>> {
return api.getAttendanceSubjects()
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
}
fun getExams(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Exam>> {
return api.getExams(ExamRequest(startDate.toDate(), startDate.getSchoolYear()))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { it.mapExamsList(startDate, endDate) }
}
fun getGrades(semesterId: Int?): Single<Pair<List<Grade>, List<GradeSummary>>> {
return api.getGrades(GradeRequest(semesterId))
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.mapGradesList() to it.mapGradesSummary() }
}
fun getGradesDetails(semesterId: Int?): Single<List<Grade>> {
return api.getGrades(GradeRequest(semesterId))
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.mapGradesList() }
}
fun getGradesSummary(semesterId: Int?): Single<List<GradeSummary>> {
return api.getGrades(GradeRequest(semesterId))
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.mapGradesSummary() }
}
fun getGradesPartialStatistics(semesterId: Int): Single<List<GradeStatistics>> {
return api.getGradesPartialStatistics(GradesStatisticsRequest(semesterId))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { it.mapGradesStatisticsPartial(semesterId) }
}
fun getGradesPointsStatistics(semesterId: Int): Single<List<GradePointsSummary>> {
return api.getGradesPointsStatistics(GradesStatisticsRequest(semesterId))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { it.mapGradesStatisticsPoints(semesterId) }
}
fun getGradesAnnualStatistics(semesterId: Int): Single<List<GradeStatistics>> {
return api.getGradesAnnualStatistics(GradesStatisticsRequest(semesterId))
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
.map { it.mapGradesStatisticsAnnual(semesterId) }
}
fun getHomework(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Homework>> {
return api.getHomework(HomeworkRequest(startDate.toDate(), startDate.getSchoolYear(), -1))
.compose(ErrorHandlerTransformer())
.map { it.data.orEmpty().mapHomework(startDate, endDate) }
.onErrorResumeNext { t ->
if (t is InvalidPathException) api.getZadaniaDomowe(ExamRequest(startDate.toDate(), startDate.getSchoolYear()))
.compose(ErrorHandlerTransformer())
.map { it.data.orEmpty().mapHomeworkList(startDate, endDate) }
else Single.error(t)
suspend fun getNotes(): List<Note> {
return api.getNotes().handleErrors().data?.notes.orEmpty().map {
it.apply {
teacherSymbol = teacher.split(" [").last().removeSuffix("]")
teacher = teacher.split(" [").first()
}
}.sortedWith(compareBy({ it.date }, { it.category }))
}
fun getNotes(): Single<List<Note>> {
return api.getNotes()
.compose(ErrorHandlerTransformer()).map { it.data?.notes.orEmpty() }
.map { res ->
res.map {
it.apply {
teacherSymbol = teacher.split(" [").last().removeSuffix("]")
teacher = teacher.split(" [").first()
}
}.sortedWith(compareBy({ it.date }, { it.category }))
}
suspend fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null): List<Timetable> {
return api.getTimetable(TimetableRequest(startDate.toISOFormat())).handleErrors().data
?.mapTimetableList(startDate, endDate)!!
}
fun getTimetable(startDate: LocalDate, endDate: LocalDate? = null): Single<List<Timetable>> {
return api.getTimetable(TimetableRequest(startDate.toISOFormat()))
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.mapTimetableList(startDate, endDate) }
}
fun getCompletedLessons(start: LocalDate, endDate: LocalDate?, subjectId: Int): Single<List<CompletedLesson>> {
suspend fun getCompletedLessons(start: LocalDate, endDate: LocalDate?, subjectId: Int): List<CompletedLesson> {
val end = endDate ?: start.plusMonths(1)
return getCache().map { cache ->
if (!cache.showCompletedLessons) throw FeatureDisabledException("Widok lekcji zrealizowanych został wyłączony przez Administratora szkoły")
}.flatMap {
api.getCompletedLessons(CompletedLessonsRequest(start.toISOFormat(), end.toISOFormat(), subjectId))
}.map {
gson.create().fromJson(it, ApiResponse::class.java)
}.compose<ApiResponse<*>>(ErrorHandlerTransformer()).map { it.mapCompletedLessonsList(start, endDate, gson) }
val cache = getCache()
if (!cache.showCompletedLessons) throw FeatureDisabledException("Widok lekcji zrealizowanych został wyłączony przez Administratora szkoły")
val res = api.getCompletedLessons(CompletedLessonsRequest(start.toISOFormat(), end.toISOFormat(), subjectId))
return gson.create().fromJson(res, ApiResponse::class.java).handleErrors().mapCompletedLessonsList(start, endDate, gson)
}
fun getTeachers(): Single<List<Teacher>> {
return api.getSchoolAndTeachers()
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.mapToTeachers() }
suspend fun getTeachers(): List<Teacher> {
return api.getSchoolAndTeachers().handleErrors().data?.mapToTeachers()!!
}
fun getSchool(): Single<School> {
return api.getSchoolAndTeachers()
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { it.school }
suspend fun getSchool(): School {
return api.getSchoolAndTeachers().handleErrors().data?.school!!
}
fun getRegisteredDevices(): Single<List<Device>> {
return api.getRegisteredDevices()
.compose(ErrorHandlerTransformer()).map { it.data.orEmpty() }
suspend fun getRegisteredDevices(): List<Device> {
return api.getRegisteredDevices().handleErrors().data.orEmpty()
}
fun getToken(): Single<TokenResponse> {
return api.getToken()
.compose(ErrorHandlerTransformer()).map { requireNotNull(it.data) }
.map { res ->
res.apply {
qrCodeImage = Jsoup.parse(qrCodeImage).select("img").attr("src").split("data:image/png;base64,")[1]
}
}
suspend fun getToken(): TokenResponse {
val data = api.getToken().handleErrors().data
requireNotNull(data).qrCodeImage = Jsoup.parse(data.qrCodeImage)
.select("img")
.attr("src")
.split("data:image/png;base64,")[1]
return data
}
fun unregisterDevice(id: Int): Single<Boolean> {
return api.getStart("Start").flatMap {
api.unregisterDevice(
getScriptParam("antiForgeryToken", it),
getScriptParam("appGuid", it),
getScriptParam("version", it),
UnregisterDeviceRequest(id)
)
}.compose(ErrorHandlerTransformer()).map { it.success }
suspend fun unregisterDevice(id: Int): Boolean {
val it = api.getStart("Start")
return api.unregisterDevice(
getScriptParam("antiForgeryToken", it),
getScriptParam("appGuid", it),
getScriptParam("version", it),
UnregisterDeviceRequest(id)
).handleErrors().success
}
}

View file

@ -1,10 +1,9 @@
package io.github.wulkanowy.sdk.scrapper.repository
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorHandlerTransformer
import io.github.wulkanowy.sdk.scrapper.interceptor.handleErrors
import io.github.wulkanowy.sdk.scrapper.register.Semester
import io.github.wulkanowy.sdk.scrapper.service.StudentService
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.reactivex.Single
import org.slf4j.LoggerFactory
import org.threeten.bp.LocalDate.now
@ -18,40 +17,36 @@ class StudentStartRepository(
@JvmStatic private val logger = LoggerFactory.getLogger(this::class.java)
}
fun getSemesters(): Single<List<Semester>> {
return api.getDiaries()
.compose(ErrorHandlerTransformer())
.map { diaries ->
diaries.data.orEmpty().asSequence()
.filter { diary -> diary.semesters?.isNotEmpty() ?: false }
.filter { diary -> diary.studentId == studentId }
.filter { diary -> diary.semesters!![0].classId == classId }
.map { diary ->
diary.semesters!!.map {
Semester(
diaryId = diary.diaryId,
diaryName = "${diary.level}${diary.symbol}",
schoolYear = diary.year,
semesterId = it.id,
semesterNumber = it.number,
start = it.start.toLocalDate(),
end = it.end.toLocalDate(),
current = it.start.toLocalDate() <= now() && it.end.toLocalDate() >= now(),
classId = it.classId,
unitId = it.unitId
)
}
}
.flatten()
.sortedByDescending { it.semesterId }
.toList()
.ifEmpty {
logger.debug("Student $studentId, class $classId not found in diaries: $diaries")
emptyList()
}
}.map {
if (it.isNotEmpty() && it.singleOrNull { semester -> semester.current } == null) it.apply { first().current = true }
else it
suspend fun getSemesters(): List<Semester> {
val diaries = api.getDiaries().handleErrors().data
return diaries.orEmpty()
.asSequence()
.filter { it.semesters?.isNotEmpty() ?: false }
.filter { it.studentId == studentId }
.filter { it.semesters!![0].classId == classId }
.map { diary ->
diary.semesters!!.map {
Semester(
diaryId = diary.diaryId,
diaryName = "${diary.level}${diary.symbol}",
schoolYear = diary.year,
semesterId = it.id,
semesterNumber = it.number,
start = it.start.toLocalDate(),
end = it.end.toLocalDate(),
current = it.start.toLocalDate() <= now() && it.end.toLocalDate() >= now(),
classId = it.classId,
unitId = it.unitId
)
}
}
.flatten()
.sortedByDescending { it.semesterId }
.toList()
.ifEmpty {
logger.debug("Student $studentId, class $classId not found in diaries: $diaries")
emptyList()
}.apply {
if (isNotEmpty() && singleOrNull { semester -> semester.current } == null) first().current = true }
}
}
}

View file

@ -3,7 +3,6 @@ package io.github.wulkanowy.sdk.scrapper.service
import io.github.wulkanowy.sdk.scrapper.register.LoginForm
import io.github.wulkanowy.sdk.scrapper.register.SentUnlockAccountResponse
import io.github.wulkanowy.sdk.scrapper.register.UnlockAccountResponse
import io.reactivex.Single
import retrofit2.http.Field
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
@ -14,36 +13,36 @@ import retrofit2.http.Url
interface AccountService {
@GET
fun getFormType(@Url url: String): Single<LoginForm>
suspend fun getFormType(@Url url: String): LoginForm
@GET
fun getPasswordResetPageWithCaptcha(@Url url: String): Single<UnlockAccountResponse>
suspend fun getPasswordResetPageWithCaptcha(@Url url: String): UnlockAccountResponse
@POST
@FormUrlEncoded
fun sendPasswordResetRequest(
suspend fun sendPasswordResetRequest(
@Url url: String,
@Field("Email") email: String,
@Field("g-recaptcha-response") captchaCode: String
): Single<SentUnlockAccountResponse>
): SentUnlockAccountResponse
@POST
@FormUrlEncoded
fun sendPasswordResetRequestADFSLight(
suspend fun sendPasswordResetRequestADFSLight(
@Url url: String,
@Field("UserId") username: String,
@Field("g-recaptcha-response") captchaCode: String
): Single<SentUnlockAccountResponse>
): SentUnlockAccountResponse
@GET
fun getPasswordResetPageADFS(@Url url: String): Single<SentUnlockAccountResponse>
suspend fun getPasswordResetPageADFS(@Url url: String): SentUnlockAccountResponse
@POST
@FormUrlEncoded
fun sendPasswordResetRequestADFS(
suspend fun sendPasswordResetRequestADFS(
@Url url: String,
@Field("txtUserID") username: String,
@Field("g-recaptcha-response") captchaCode: String,
@FieldMap viewStateParams: Map<String, String>
): Single<SentUnlockAccountResponse>
): SentUnlockAccountResponse
}

View file

@ -3,7 +3,6 @@ package io.github.wulkanowy.sdk.scrapper.service
import io.github.wulkanowy.sdk.scrapper.ApiResponse
import io.github.wulkanowy.sdk.scrapper.home.GovernmentUnit
import io.github.wulkanowy.sdk.scrapper.home.HomepageTileResponse
import io.reactivex.Single
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.GET
@ -12,45 +11,45 @@ import retrofit2.http.POST
interface HomepageService {
@GET("Start.mvc/Index")
fun getStart(): Single<String>
suspend fun getStart(): String
@FormUrlEncoded
@POST("Start.mvc/GetSelfGovernments")
fun getSelfGovernments(@Field("permissions") token: String): Single<ApiResponse<List<GovernmentUnit>>>
suspend fun getSelfGovernments(@Field("permissions") token: String): ApiResponse<List<GovernmentUnit>>
@FormUrlEncoded
@POST("Start.mvc/GetStudentTrips")
fun getStudentsTrips(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getStudentsTrips(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetStudentThreats")
fun getStudentThreats(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getStudentThreats(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetLastNotes")
fun getLastGrades(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getLastGrades(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetFreeDays")
fun getFreeDays(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getFreeDays(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetKidsLuckyNumbers")
fun getKidsLuckyNumbers(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getKidsLuckyNumbers(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetKidsLessonPlan")
fun getKidsLessonPlan(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getKidsLessonPlan(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetLastHomeworks")
fun getLastHomework(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getLastHomework(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetLastTests")
fun getLastTests(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getLastTests(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
@FormUrlEncoded
@POST("Start.mvc/GetLastStudentLessons")
fun getLastStudentLessons(@Field("permissions") token: String): Single<ApiResponse<List<HomepageTileResponse>>>
suspend fun getLastStudentLessons(@Field("permissions") token: String): ApiResponse<List<HomepageTileResponse>>
}

View file

@ -2,7 +2,6 @@ package io.github.wulkanowy.sdk.scrapper.service
import io.github.wulkanowy.sdk.scrapper.login.ADFSFormResponse
import io.github.wulkanowy.sdk.scrapper.register.SendCertificateResponse
import io.reactivex.Single
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.GET
@ -14,25 +13,25 @@ interface LoginService {
@POST("Account/LogOn")
@FormUrlEncoded
fun sendCredentials(@Query("ReturnUrl") returnUrl: String, @FieldMap credentials: Map<String, String>): Single<String>
suspend fun sendCredentials(@Query("ReturnUrl") returnUrl: String, @FieldMap credentials: Map<String, String>): String
@POST
@FormUrlEncoded
fun sendCertificate(@Url url: String, @FieldMap certificate: Map<String, String>): Single<SendCertificateResponse>
suspend fun sendCertificate(@Url url: String, @FieldMap certificate: Map<String, String>): SendCertificateResponse
@GET
fun switchLogin(@Url url: String): Single<SendCertificateResponse>
suspend fun switchLogin(@Url url: String): SendCertificateResponse
// ADFS
@GET
fun getForm(@Url url: String): Single<ADFSFormResponse>
suspend fun getForm(@Url url: String): ADFSFormResponse
@POST
@FormUrlEncoded
fun sendADFSFormStandardChoice(@Url url: String, @FieldMap formState: Map<String, String>): Single<ADFSFormResponse>
suspend fun sendADFSFormStandardChoice(@Url url: String, @FieldMap formState: Map<String, String>): ADFSFormResponse
@POST
@FormUrlEncoded
fun sendADFSForm(@Url url: String, @FieldMap values: Map<String, String>): Single<String>
suspend fun sendADFSForm(@Url url: String, @FieldMap values: Map<String, String>): String
}

View file

@ -7,7 +7,6 @@ import io.github.wulkanowy.sdk.scrapper.messages.Recipient
import io.github.wulkanowy.sdk.scrapper.messages.ReportingUnit
import io.github.wulkanowy.sdk.scrapper.messages.SendMessageRequest
import io.github.wulkanowy.sdk.scrapper.messages.SentMessage
import io.reactivex.Single
import retrofit2.http.Body
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
@ -19,51 +18,51 @@ import retrofit2.http.Query
interface MessagesService {
@GET(".")
fun getStart(): Single<String>
suspend fun getStart(): String
@GET("NowaWiadomosc.mvc/GetJednostkiUzytkownika")
fun getUserReportingUnits(): Single<ApiResponse<List<ReportingUnit>>>
suspend fun getUserReportingUnits(): ApiResponse<List<ReportingUnit>>
@GET("Adresaci.mvc/GetAdresaci")
fun getRecipients(@Query("IdJednostkaSprawozdawcza") reportingUnitId: Int, @Query("Rola") role: Int): Single<ApiResponse<List<Recipient>>>
suspend fun getRecipients(@Query("IdJednostkaSprawozdawcza") reportingUnitId: Int, @Query("Rola") role: Int): ApiResponse<List<Recipient>>
@GET("Wiadomosc.mvc/GetWiadomosciOdebrane")
fun getReceived(@Query("dataOd") dateStart: String, @Query("dataDo") dateEnd: String): Single<ApiResponse<List<Message>>>
suspend fun getReceived(@Query("dataOd") dateStart: String, @Query("dataDo") dateEnd: String): ApiResponse<List<Message>>
@GET("Wiadomosc.mvc/GetWiadomosciWyslane")
fun getSent(@Query("dataOd") dateStart: String, @Query("dataDo") dateEnd: String): Single<ApiResponse<List<Message>>>
suspend fun getSent(@Query("dataOd") dateStart: String, @Query("dataDo") dateEnd: String): ApiResponse<List<Message>>
@GET("Wiadomosc.mvc/GetWiadomosciUsuniete")
fun getDeleted(@Query("dataOd") dateStart: String, @Query("dataDo") dateEnd: String): Single<ApiResponse<List<Message>>>
suspend fun getDeleted(@Query("dataOd") dateStart: String, @Query("dataDo") dateEnd: String): ApiResponse<List<Message>>
@GET("Wiadomosc.mvc/GetAdresaciWiadomosci")
fun getMessageRecipients(@Query("idWiadomosci") messageId: Int): Single<ApiResponse<List<Recipient>>>
suspend fun getMessageRecipients(@Query("idWiadomosci") messageId: Int): ApiResponse<List<Recipient>>
@GET("Wiadomosc.mvc/GetRoleUzytkownika")
fun getMessageSender(@Query("idLogin") loginId: Int, @Query("idWiadomosci") messageId: Int): Single<ApiResponse<List<Recipient>>>
suspend fun getMessageSender(@Query("idLogin") loginId: Int, @Query("idWiadomosci") messageId: Int): ApiResponse<List<Recipient>>
@POST("Wiadomosc.mvc/GetTrescWiadomosci")
@FormUrlEncoded
fun getMessage(
suspend fun getMessage(
@Field("idWiadomosc") messageId: Int,
@Field("Folder") folderId: Int,
@Field("Nieprzeczytana") read: Boolean,
@Field("idWiadomoscAdresat") id: Int?
): Single<ApiResponse<Message>>
): ApiResponse<Message>
@POST("NowaWiadomosc.mvc/InsertWiadomosc")
fun sendMessage(
suspend fun sendMessage(
@Body sendMessageRequest: SendMessageRequest,
@Header("X-V-RequestVerificationToken") token: String,
@Header("X-V-AppGuid") appGuid: String,
@Header("X-V-AppVersion") appVersion: String
): Single<ApiResponse<SentMessage>>
): ApiResponse<SentMessage>
@POST("Wiadomosc.mvc/UsunWiadomosc")
fun deleteMessage(
suspend fun deleteMessage(
@Body deleteMessageRequests: List<DeleteMessageRequest>,
@Header("X-V-RequestVerificationToken") token: String,
@Header("X-V-AppGuid") appGuid: String,
@Header("X-V-AppVersion") appVersion: String
): Single<String>
): String
}

View file

@ -1,12 +1,11 @@
package io.github.wulkanowy.sdk.scrapper.service
import io.github.wulkanowy.sdk.scrapper.register.LoginForm
import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.Url
interface RegisterService {
@GET
fun getFormType(@Url url: String): Single<LoginForm>
suspend fun getFormType(@Url url: String): LoginForm
}

View file

@ -1,6 +1,5 @@
package io.github.wulkanowy.sdk.scrapper.service
import RxJava2ReauthCallAdapterFactory
import com.google.gson.GsonBuilder
import io.github.wulkanowy.sdk.scrapper.OkHttpClientBuilderFactory
import io.github.wulkanowy.sdk.scrapper.Scrapper
@ -14,9 +13,6 @@ import io.github.wulkanowy.sdk.scrapper.interceptor.NotLoggedInErrorInterceptor
import io.github.wulkanowy.sdk.scrapper.interceptor.StudentAndParentInterceptor
import io.github.wulkanowy.sdk.scrapper.interceptor.UserAgentInterceptor
import io.github.wulkanowy.sdk.scrapper.login.LoginHelper
import io.github.wulkanowy.sdk.scrapper.login.NotLoggedInException
import io.github.wulkanowy.sdk.scrapper.register.SendCertificateResponse
import io.reactivex.Flowable
import okhttp3.Interceptor
import okhttp3.JavaNetCookieJar
import okhttp3.OkHttpClient
@ -24,7 +20,6 @@ import okhttp3.logging.HttpLoggingInterceptor
import org.threeten.bp.LocalDate
import pl.droidsonroids.retrofit2.JspoonConverterFactory
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.create
@ -160,12 +155,7 @@ class ServiceManager(
.serializeNulls()
.registerTypeAdapter(GradeDate::class.java, DateDeserializer(GradeDate::class.java))
.create()) else JspoonConverterFactory.create())
.addCallAdapterFactory(if (!login) RxJava2CallAdapterFactory.create() else
RxJava2ReauthCallAdapterFactory.create(
getLoginHelper(),
{ it is NotLoggedInException }
)
).build()
.build()
}
private fun getClientBuilder(
@ -196,12 +186,11 @@ class ServiceManager(
}
}
private fun getLoginHelper(): Flowable<SendCertificateResponse> {
return loginHelper
.login(email, password)
.toFlowable()
.share()
}
// private suspend fun getLoginHelper(): Flowable<SendCertificateResponse> {
// return loginHelper
// .login(email, password)
// .share()
// }
class UrlGenerator(private val schema: String, private val host: String, var symbol: String, var schoolId: String) {

View file

@ -14,7 +14,6 @@ import io.github.wulkanowy.sdk.scrapper.school.SchoolAndTeachersResponse
import io.github.wulkanowy.sdk.scrapper.student.StudentInfo
import io.github.wulkanowy.sdk.scrapper.timetable.RealizedResponse
import io.github.wulkanowy.sdk.scrapper.timetable.TimetableResponse
import io.reactivex.Single
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.GET
@ -26,57 +25,57 @@ import retrofit2.http.Url
interface StudentAndParentService {
@GET
fun getSchoolInfo(@Url url: String): Single<StudentAndParentResponse>
suspend fun getSchoolInfo(@Url url: String): StudentAndParentResponse
@GET("Uczen/UczenOnChange")
fun getUserInfo(@Query("id") userId: Int): Single<StudentAndParentResponse>
suspend fun getUserInfo(@Query("id") userId: Int): StudentAndParentResponse
@GET("Dziennik/DziennikOnChange")
fun getDiaryInfo(@Query("id") diaryId: Int, @Header("Referer") referer: String): Single<StudentAndParentResponse>
suspend fun getDiaryInfo(@Query("id") diaryId: Int, @Header("Referer") referer: String): StudentAndParentResponse
@GET("Frekwencja.mvc")
fun getAttendance(@Query("data") date: String): Single<AttendanceResponse>
suspend fun getAttendance(@Query("data") date: String): AttendanceResponse
@GET("Frekwencja.mvc")
fun getAttendanceSummary(@Query("idPrzedmiot") subjectId: Int?): Single<AttendanceResponse>
suspend fun getAttendanceSummary(@Query("idPrzedmiot") subjectId: Int?): AttendanceResponse
@GET("Sprawdziany.mvc/Terminarz?rodzajWidoku=2")
fun getExams(@Query("data") date: String): Single<ExamResponse>
suspend fun getExams(@Query("data") date: String): ExamResponse
@GET("Oceny/Wszystkie?details=2")
fun getGrades(@Query("okres") semester: Int?): Single<GradesResponse>
suspend fun getGrades(@Query("okres") semester: Int?): GradesResponse
@GET("Oceny/Wszystkie?details=1")
fun getGradesSummary(@Query("okres") semester: Int?): Single<GradesSummaryResponse>
suspend fun getGradesSummary(@Query("okres") semester: Int?): GradesSummaryResponse
@GET("Statystyki.mvc/Uczen")
fun getGradesStatistics(@Query("rodzajWidoku") type: Int?, @Query("semestr") semesterId: Int): Single<GradesStatisticsResponse>
suspend fun getGradesStatistics(@Query("rodzajWidoku") type: Int?, @Query("semestr") semesterId: Int): GradesStatisticsResponse
@GET("ZadaniaDomowe.mvc?rodzajWidoku=Dzien")
fun getHomework(@Query("data") date: String): Single<HomeworkResponse>
suspend fun getHomework(@Query("data") date: String): HomeworkResponse
@GET("UwagiOsiagniecia.mvc/Wszystkie")
fun getNotes(): Single<NotesResponse>
suspend fun getNotes(): NotesResponse
@GET("DostepMobilny.mvc")
fun getRegisteredDevices(): Single<RegisteredDevicesResponse>
suspend fun getRegisteredDevices(): RegisteredDevicesResponse
@GET("DostepMobilny.mvc/Rejestruj")
fun getToken(): Single<TokenResponse>
suspend fun getToken(): TokenResponse
@POST("DostepMobilny.mvc/PotwierdzWyrejestrowanie")
@FormUrlEncoded
fun unregisterDevice(@Field("Id") id: Int): Single<RegisteredDevicesResponse>
suspend fun unregisterDevice(@Field("Id") id: Int): RegisteredDevicesResponse
@GET("Szkola.mvc/Nauczyciele")
fun getSchoolAndTeachers(): Single<SchoolAndTeachersResponse>
suspend fun getSchoolAndTeachers(): SchoolAndTeachersResponse
@GET("Lekcja.mvc/PlanZajec")
fun getTimetable(@Query("data") date: String): Single<TimetableResponse>
suspend fun getTimetable(@Query("data") date: String): TimetableResponse
@GET("Lekcja.mvc/Zrealizowane")
fun getCompletedLessons(@Query("start") start: String, @Query("end") end: String?, @Query("idPrzedmiot") subjectId: Int?): Single<RealizedResponse>
suspend fun getCompletedLessons(@Query("start") start: String, @Query("end") end: String?, @Query("idPrzedmiot") subjectId: Int?): RealizedResponse
@GET("Uczen.mvc/DanePodstawowe")
fun getStudentInfo(): Single<StudentInfo>
suspend fun getStudentInfo(): StudentInfo
}

View file

@ -27,7 +27,6 @@ import io.github.wulkanowy.sdk.scrapper.timetable.CacheResponse
import io.github.wulkanowy.sdk.scrapper.timetable.CompletedLessonsRequest
import io.github.wulkanowy.sdk.scrapper.timetable.TimetableRequest
import io.github.wulkanowy.sdk.scrapper.timetable.TimetableResponse
import io.reactivex.Single
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
@ -37,101 +36,101 @@ import retrofit2.http.Url
interface StudentService {
@GET
fun getStart(@Url url: String): Single<String>
suspend fun getStart(@Url url: String): String
@POST
fun getUserCache(
suspend fun getUserCache(
@Url url: String,
@Header("X-V-RequestVerificationToken") token: String,
@Header("X-V-AppGuid") appGuid: String,
@Header("X-V-AppVersion") appVersion: String,
@Body body: Any = Object()
): Single<ApiResponse<CacheResponse>>
): ApiResponse<CacheResponse>
@POST("UczenCache.mvc/Get")
fun getUserCache(
suspend fun getUserCache(
@Header("X-V-RequestVerificationToken") token: String,
@Header("X-V-AppGuid") appGuid: String,
@Header("X-V-AppVersion") appVersion: String,
@Body body: Any = Object()
): Single<ApiResponse<CacheResponse>>
): ApiResponse<CacheResponse>
@POST
fun getSchoolInfo(@Url url: String, @Body body: Any = Object()): Single<ApiResponse<List<Diary>>>
suspend fun getSchoolInfo(@Url url: String, @Body body: Any = Object()): ApiResponse<List<Diary>>
@POST("UczenDziennik.mvc/Get")
fun getDiaries(@Body body: Any = Object()): Single<ApiResponse<List<Diary>>>
suspend fun getDiaries(@Body body: Any = Object()): ApiResponse<List<Diary>>
@POST("Oceny.mvc/Get")
fun getGrades(@Body gradeRequest: GradeRequest): Single<ApiResponse<GradesResponse>>
suspend fun getGrades(@Body gradeRequest: GradeRequest): ApiResponse<GradesResponse>
@POST("Statystyki.mvc/GetOcenyCzastkowe")
fun getGradesPartialStatistics(@Body gradesStatisticsRequest: GradesStatisticsRequest): Single<ApiResponse<List<GradesStatisticsResponse.Partial>>>
suspend fun getGradesPartialStatistics(@Body gradesStatisticsRequest: GradesStatisticsRequest): ApiResponse<List<GradesStatisticsResponse.Partial>>
@POST("Statystyki.mvc/GetPunkty")
fun getGradesPointsStatistics(@Body gradesStatisticsRequest: GradesStatisticsRequest): Single<ApiResponse<List<GradePointsSummary>>>
suspend fun getGradesPointsStatistics(@Body gradesStatisticsRequest: GradesStatisticsRequest): ApiResponse<List<GradePointsSummary>>
@POST("Statystyki.mvc/GetOcenyRoczne")
fun getGradesAnnualStatistics(@Body gradesStatisticsRequest: GradesStatisticsRequest): Single<ApiResponse<List<GradesStatisticsResponse.Annual>>>
suspend fun getGradesAnnualStatistics(@Body gradesStatisticsRequest: GradesStatisticsRequest): ApiResponse<List<GradesStatisticsResponse.Annual>>
@POST("Frekwencja.mvc/Get")
fun getAttendance(@Body attendanceRequest: AttendanceRequest): Single<ApiResponse<AttendanceResponse>>
suspend fun getAttendance(@Body attendanceRequest: AttendanceRequest): ApiResponse<AttendanceResponse>
@POST("FrekwencjaStatystyki.mvc/Get")
fun getAttendanceStatistics(@Body attendanceSummaryRequest: AttendanceSummaryRequest): Single<ApiResponse<AttendanceSummaryResponse>>
suspend fun getAttendanceStatistics(@Body attendanceSummaryRequest: AttendanceSummaryRequest): ApiResponse<AttendanceSummaryResponse>
@POST("FrekwencjaStatystykiPrzedmioty.mvc/Get")
fun getAttendanceSubjects(@Body body: Any = Object()): Single<ApiResponse<List<Subject>>>
suspend fun getAttendanceSubjects(@Body body: Any = Object()): ApiResponse<List<Subject>>
@POST("Usprawiedliwienia.mvc/Post")
fun excuseForAbsence(
suspend fun excuseForAbsence(
@Header("X-V-RequestVerificationToken") token: String,
@Header("X-V-AppGuid") appGuid: String,
@Header("X-V-AppVersion") appVersion: String,
@Body attendanceExcuseRequest: AttendanceExcuseRequest
): Single<ApiResponse<Nothing>>
): ApiResponse<Nothing>
@POST("EgzaminyZewnetrzne.mvc/Get")
fun getExternalExaminations()
suspend fun getExternalExaminations()
@POST("Sprawdziany.mvc/Get")
fun getExams(@Body examRequest: ExamRequest): Single<ApiResponse<List<ExamResponse>>>
suspend fun getExams(@Body examRequest: ExamRequest): ApiResponse<List<ExamResponse>>
@POST("ZadaniaDomowe.mvc/Get")
fun getZadaniaDomowe(@Body homeworkRequest: ExamRequest): Single<ApiResponse<List<HomeworkResponse>>>
suspend fun getZadaniaDomowe(@Body homeworkRequest: ExamRequest): ApiResponse<List<HomeworkResponse>>
@POST("Homework.mvc/Get")
fun getHomework(@Body homeworkRequest: HomeworkRequest): Single<ApiResponse<List<HomeworkDay>>>
suspend fun getHomework(@Body homeworkRequest: HomeworkRequest): ApiResponse<List<HomeworkDay>>
@POST("PlanZajec.mvc/Get")
fun getTimetable(@Body timetableRequest: TimetableRequest): Single<ApiResponse<TimetableResponse>>
suspend fun getTimetable(@Body timetableRequest: TimetableRequest): ApiResponse<TimetableResponse>
@POST("LekcjeZrealizowane.mvc/GetPrzedmioty")
fun getRealizedSubjects(@Body body: Any = Object())
suspend fun getRealizedSubjects(@Body body: Any = Object())
@POST("LekcjeZrealizowane.mvc/GetZrealizowane")
fun getCompletedLessons(@Body completedLessonsRequest: CompletedLessonsRequest): Single<String>
suspend fun getCompletedLessons(@Body completedLessonsRequest: CompletedLessonsRequest): String
@POST("UwagiIOsiagniecia.mvc/Get")
fun getNotes(@Body body: Any = Object()): Single<ApiResponse<NotesResponse>>
suspend fun getNotes(@Body body: Any = Object()): ApiResponse<NotesResponse>
@POST("ZarejestrowaneUrzadzenia.mvc/Get")
fun getRegisteredDevices(@Body body: Any = Object()): Single<ApiResponse<List<Device>>>
suspend fun getRegisteredDevices(@Body body: Any = Object()): ApiResponse<List<Device>>
@POST("RejestracjaUrzadzeniaToken.mvc/Get")
fun getToken(@Body body: Any = Object()): Single<ApiResponse<TokenResponse>>
suspend fun getToken(@Body body: Any = Object()): ApiResponse<TokenResponse>
@POST("ZarejestrowaneUrzadzenia.mvc/Delete")
fun unregisterDevice(
suspend fun unregisterDevice(
@Header("X-V-RequestVerificationToken") token: String,
@Header("X-V-AppGuid") appGuid: String,
@Header("X-V-AppVersion") appVersion: String,
@Body unregisterDeviceRequest: UnregisterDeviceRequest
): Single<ApiResponse<Nothing>>
): ApiResponse<Nothing>
@POST("SzkolaINauczyciele.mvc/Get")
fun getSchoolAndTeachers(@Body body: Any = Object()): Single<ApiResponse<SchoolAndTeachersResponse>>
suspend fun getSchoolAndTeachers(@Body body: Any = Object()): ApiResponse<SchoolAndTeachersResponse>
@POST("Uczen.mvc/Get")
fun getStudentInfo()
suspend fun getStudentInfo()
}

View file

@ -17,7 +17,6 @@ import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import pl.droidsonroids.retrofit2.JspoonConverterFactory
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
@ -68,7 +67,6 @@ abstract class BaseLocalTest : BaseTest() {
.serializeNulls()
.registerTypeAdapter(GradeDate::class.java, DateDeserializer(GradeDate::class.java))
.create()) else JspoonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(url)
.build()
.create(service)

View file

@ -1,30 +1,8 @@
package io.github.wulkanowy.sdk.scrapper
import io.github.wulkanowy.sdk.scrapper.attendance.Attendance
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceSummary
import io.github.wulkanowy.sdk.scrapper.attendance.Subject
import io.github.wulkanowy.sdk.scrapper.exams.Exam
import io.github.wulkanowy.sdk.scrapper.grades.Grade
import io.github.wulkanowy.sdk.scrapper.grades.GradeStatistics
import io.github.wulkanowy.sdk.scrapper.grades.GradeSummary
import io.github.wulkanowy.sdk.scrapper.home.LuckyNumber
import io.github.wulkanowy.sdk.scrapper.homework.Homework
import io.github.wulkanowy.sdk.scrapper.messages.Folder
import io.github.wulkanowy.sdk.scrapper.messages.Message
import io.github.wulkanowy.sdk.scrapper.messages.Recipient
import io.github.wulkanowy.sdk.scrapper.messages.ReportingUnit
import io.github.wulkanowy.sdk.scrapper.messages.SentMessage
import io.github.wulkanowy.sdk.scrapper.mobile.Device
import io.github.wulkanowy.sdk.scrapper.mobile.TokenResponse
import io.github.wulkanowy.sdk.scrapper.notes.Note
import io.github.wulkanowy.sdk.scrapper.register.Semester
import io.github.wulkanowy.sdk.scrapper.register.Student
import io.github.wulkanowy.sdk.scrapper.school.School
import io.github.wulkanowy.sdk.scrapper.school.Teacher
import io.github.wulkanowy.sdk.scrapper.student.StudentInfo
import io.github.wulkanowy.sdk.scrapper.timetable.CompletedLesson
import io.github.wulkanowy.sdk.scrapper.timetable.Timetable
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import org.junit.Assert.assertEquals
@ -66,35 +44,29 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun getPasswordResetCaptchaCode() {
val code = api.getPasswordResetCaptcha("https://fakelog.cf", "Default")
val codeObserver = TestObserver<Pair<String, String>>()
code.subscribe(codeObserver)
codeObserver.assertComplete()
val code = runBlocking { api.getPasswordResetCaptcha("https://fakelog.cf", "Default") }
assertEquals("https://cufs.fakelog.cf/Default/AccountManage/UnlockAccount", codeObserver.values()[0].first)
assertEquals("6LeAGMYUAAAAAMszd5VWZTEb5WQHqsNT1F4GCqUd", codeObserver.values()[0].second)
assertEquals("https://cufs.fakelog.cf/Default/AccountManage/UnlockAccount", code.first)
assertEquals("6LeAGMYUAAAAAMszd5VWZTEb5WQHqsNT1F4GCqUd", code.second)
}
@Test
fun sendPasswordResetRequest() {
val res = api.sendPasswordResetRequest("https://fakelog.cf", "Default", "jan@fakelog.cf", "03AOLTBLQRPyr0pWvWLRAgD4hRLfxktoqD2IVweeMuXwbkpR_8S9YQtcS3cAXqUOyEw3NxfvwzV0lTjgFWyl8j3UXGQpsc2nvQcqIofj1N8DYfxvtZO-h24W_S0Z9-fDnfXErd7vERS-Ny4d5IU1FupBAEKvT8rrf3OA3GYYbMM7TwB8b_o9Tt192TqYnSxkyIYE4UdaZnLBA0KIXxlBAoqM6QGlPEsSPK9gmCGx-0hn68w-UBQkv_ghRruf4kpv2Shw5emcP-qHBlv3YjAagsb_358K0v8uGJeyLrx4dXN9Ky02TXFMKYWNHz29fjhfunxT73u_PrsLj56f-MjOXrqO894NkUlJ7RkTTclwIsqXtJ794LEBH--mtsqZBND0miR5-odmZszqiNB3V5UsS5ObsqF_fWMl2TCWyNTTvF4elOGwOEeKiumVpjB6e740COxvxN3vbkNWxP9eeghpd5nPN5l2wUV3VL2R5s44TbqHqkrkNpUOd3h7efs3cQtCfGc-tCXoqLC26LxT7aztvKpjXMuqGEf-7wbQ")
val resObserver = TestObserver<String>()
res.subscribe(resObserver)
resObserver.assertComplete()
val res = runBlocking {
api.sendPasswordResetRequest("https://fakelog.cf",
"Default",
"jan@fakelog.cf",
"03AOLTBLQRPyr0pWvWLRAgD4hRLfxktoqD2IVweeMuXwbkpR_8S9YQtcS3cAXqUOyEw3NxfvwzV0lTjgFWyl8j3UXGQpsc2nvQcqIofj1N8DYfxvtZO-h24W_S0Z9-fDnfXErd7vERS-Ny4d5IU1FupBAEKvT8rrf3OA3GYYbMM7TwB8b_o9Tt192TqYnSxkyIYE4UdaZnLBA0KIXxlBAoqM6QGlPEsSPK9gmCGx-0hn68w-UBQkv_ghRruf4kpv2Shw5emcP-qHBlv3YjAagsb_358K0v8uGJeyLrx4dXN9Ky02TXFMKYWNHz29fjhfunxT73u_PrsLj56f-MjOXrqO894NkUlJ7RkTTclwIsqXtJ794LEBH--mtsqZBND0miR5-odmZszqiNB3V5UsS5ObsqF_fWMl2TCWyNTTvF4elOGwOEeKiumVpjB6e740COxvxN3vbkNWxP9eeghpd5nPN5l2wUV3VL2R5s44TbqHqkrkNpUOd3h7efs3cQtCfGc-tCXoqLC26LxT7aztvKpjXMuqGEf-7wbQ")
}
assertTrue(resObserver.values()[0].startsWith("Wysłano wiadomość na zapisany w systemie adres e-mail"))
assertTrue(res.startsWith("Wysłano wiadomość na zapisany w systemie adres e-mail"))
}
@Test
fun studentsTest() {
val students = api.getStudents()
val studentObserver = TestObserver<List<Student>>()
students.subscribe(studentObserver)
studentObserver.assertComplete()
val students = runBlocking { api.getStudents() }
val values = studentObserver.values()[0]
values[0].run {
students[0].run {
assertEquals("powiatwulkanowy", symbol)
assertEquals("jan@fakelog.cf", email)
assertEquals("Jan Kowalski", studentName)
@ -108,26 +80,21 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun semestersTest() {
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val values = semestersObserver.values()[0]
values[0].run {
semesters[0].run {
assertEquals(15, diaryId)
assertEquals("4A", diaryName)
// assertEquals(true, current)
}
values[3].run {
semesters[3].run {
assertEquals(13, diaryId)
assertEquals("3A", diaryName)
assertEquals(2017, schoolYear)
}
values[5].run {
semesters[5].run {
assertEquals(11, diaryId)
assertEquals("2A", diaryName)
assertEquals(2016, schoolYear)
@ -135,7 +102,7 @@ class ScrapperRemoteTest : BaseTest() {
// assertEquals(1, semesterNumber)
}
values[6].run {
semesters[6].run {
// assertEquals(12, semesterId)
// assertEquals(2, semesterNumber)
}
@ -143,14 +110,9 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun attendanceTest() {
val attendance = api.getAttendance(getLocalDate(2018, 10, 1))
val attendanceObserver = TestObserver<List<Attendance>>()
attendance.subscribe(attendanceObserver)
attendanceObserver.assertComplete()
val attendance = runBlocking { api.getAttendance(getLocalDate(2018, 10, 1)) }
val values = attendanceObserver.values()[0]
values[0].run {
attendance[0].run {
assertEquals(1, number)
assertEquals("Zajęcia z wychowawcą", subject)
assertEquals(getDate(2018, 10, 1), date)
@ -159,31 +121,26 @@ class ScrapperRemoteTest : BaseTest() {
assertTrue(presence)
}
values[1].run {
attendance[1].run {
assertEquals("Nieobecność nieusprawiedliwiona", name)
assertTrue(absence)
assertFalse(excused)
}
assertEquals("Nieobecność nieusprawiedliwiona", values[3].name)
assertEquals("Nieobecność nieusprawiedliwiona", values[4].name)
assertEquals("Nieobecność usprawiedliwiona", values[5].name)
assertEquals("Spóźnienie nieusprawiedliwione", values[6].name)
assertEquals("Obecność", values[9].name)
assertEquals("Nieobecność nieusprawiedliwiona", attendance[3].name)
assertEquals("Nieobecność nieusprawiedliwiona", attendance[4].name)
assertEquals("Nieobecność usprawiedliwiona", attendance[5].name)
assertEquals("Spóźnienie nieusprawiedliwione", attendance[6].name)
assertEquals("Obecność", attendance[9].name)
}
@Test
fun getSubjects() {
val subjects = api.getSubjects()
val subjectsObserver = TestObserver<List<Subject>>()
subjects.subscribe(subjectsObserver)
subjectsObserver.assertComplete()
val subjects = runBlocking { api.getSubjects() }
val values = subjectsObserver.values()[0]
assertEquals(17, subjects.size)
assertEquals(17, values.size)
values[0].run {
subjects[0].run {
assertEquals(-1, value)
assertEquals("Wszystkie", name)
}
@ -191,16 +148,11 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun attendanceSummaryTest() {
val attendance = api.getAttendanceSummary()
val attendanceObserver = TestObserver<List<AttendanceSummary>>()
attendance.subscribe(attendanceObserver)
attendanceObserver.assertComplete()
val attendance = runBlocking { api.getAttendanceSummary() }
val values = attendanceObserver.values()[0]
assertEquals(10, attendance.size)
assertEquals(10, values.size)
values[0].run {
attendance[0].run {
assertEquals(Month.SEPTEMBER, month)
assertEquals(32, presence)
assertEquals(1, absence)
@ -211,19 +163,14 @@ class ScrapperRemoteTest : BaseTest() {
assertEquals(6, exemption)
}
assertEquals(64, values[1].presence)
assertEquals(64, attendance[1].presence)
}
@Test
fun examsTest() {
val exams = api.getExams(getLocalDate(2018, 5, 7))
val examsObserver = TestObserver<List<Exam>>()
exams.subscribe(examsObserver)
examsObserver.assertComplete()
val exams = runBlocking { api.getExams(getLocalDate(2018, 5, 7)) }
val values = examsObserver.values()[0]
values[0].run {
exams[0].run {
assertEquals(getDate(2018, 5, 7), date)
assertEquals(getDate(1970, 1, 1), entryDate)
assertEquals("Matematyka", subject)
@ -237,14 +184,9 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun homeworkTest() {
val homework = api.getHomework(getLocalDate(2018, 9, 11))
val homeworkObserver = TestObserver<List<Homework>>()
homework.subscribe(homeworkObserver)
homeworkObserver.assertComplete()
val homework = runBlocking { api.getHomework(getLocalDate(2018, 9, 11)) }
val values = homeworkObserver.values()[0]
values[1].run {
homework[1].run {
assertEquals(getDate(2018, 9, 11), date)
assertEquals(getDate(2017, 10, 26), entryDate)
assertEquals("Etyka", subject)
@ -256,14 +198,9 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun notesTest() {
val notes = api.getNotes()
val notesObserver = TestObserver<List<Note>>()
notes.subscribe(notesObserver)
notesObserver.assertComplete()
val notes = runBlocking { api.getNotes() }
val values = notesObserver.values()[0]
values[0].run {
notes[0].run {
assertEquals(getDate(2018, 1, 16), date)
assertEquals("Stanisław Krupa", teacher)
assertEquals("BS", teacherSymbol)
@ -274,14 +211,9 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun gradesTest() {
val grades = api.getGradesDetails(865)
val gradesObserver = TestObserver<List<Grade>>()
grades.subscribe(gradesObserver)
gradesObserver.assertComplete()
val grades = runBlocking { api.getGradesDetails(865) }
val values = gradesObserver.values()[0]
values[5].run {
grades[5].run {
assertEquals("Religia", subject)
assertEquals("1", entry)
assertEquals("6ECD07", color)
@ -293,7 +225,7 @@ class ScrapperRemoteTest : BaseTest() {
assertEquals("Michał Mazur", teacher)
}
values[0].run {
grades[0].run {
assertEquals("Bież", symbol)
assertEquals("", description)
}
@ -301,26 +233,21 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun gradesSummaryTest() {
val summary = api.getGradesSummary(865)
val summaryObserver = TestObserver<List<GradeSummary>>()
summary.subscribe(summaryObserver)
summaryObserver.assertComplete()
val summary = runBlocking { api.getGradesSummary(865) }
val values = summaryObserver.values()[0]
values[2].run {
summary[2].run {
assertEquals("Etyka", name)
assertEquals("4", predicted)
assertEquals("4", final)
}
values[5].run {
summary[5].run {
assertEquals("Historia", name)
assertEquals("4", predicted)
assertEquals("4", final)
}
values[8].run {
summary[8].run {
assertEquals("Język niemiecki", name)
assertEquals("", predicted)
assertEquals("", final)
@ -329,59 +256,37 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun gradesStatisticsTest() {
val stats = api.getGradesPartialStatistics(321)
val statsObserver = TestObserver<List<GradeStatistics>>()
stats.subscribe(statsObserver)
statsObserver.assertComplete()
val stats = runBlocking { api.getGradesPartialStatistics(321) }
val values = statsObserver.values()[0]
assertEquals("Język polski", stats[0].subject)
assertEquals("Matematyka", stats[7].subject)
assertEquals("Język polski", values[0].subject)
assertEquals("Matematyka", values[7].subject)
val annual = runBlocking { api.getGradesAnnualStatistics(123) }
val annual = api.getGradesAnnualStatistics(123)
val annualObserver = TestObserver<List<GradeStatistics>>()
annual.subscribe(annualObserver)
val values2 = annualObserver.values()[0]
assertEquals("Język angielski", values2[0].subject)
assertEquals("Język angielski", annual[0].subject)
}
@Test
fun teachersTest() {
val teachers = api.getTeachers()
val teachersObserver = TestObserver<List<Teacher>>()
teachers.subscribe(teachersObserver)
teachersObserver.assertComplete()
val teachers = runBlocking { api.getTeachers() }
val values = teachersObserver.values()[0]
assertEquals("Historia", values[1].subject)
assertEquals("Aleksandra Krajewska", values[1].name)
assertEquals("AK", values[1].short)
assertEquals("Historia", teachers[1].subject)
assertEquals("Aleksandra Krajewska", teachers[1].name)
assertEquals("AK", teachers[1].short)
}
@Test
fun schoolTest() {
val school = api.getSchool()
val schoolObserver = TestObserver<School>()
school.subscribe(schoolObserver)
schoolObserver.assertComplete()
val school = runBlocking { api.getSchool() }
val values = schoolObserver.values()[0]
assertEquals("Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", values.name)
assertEquals("Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", school.name)
}
@Test
fun studentInfoTest() {
val info = api.getStudentInfo()
val studentObserver = TestObserver<StudentInfo>()
info.subscribe(studentObserver)
studentObserver.assertComplete()
val info = runBlocking { api.getStudentInfo() }
studentObserver.values()[0].run {
info.run {
assertEquals("Jan Marek Kowalski", student.fullName)
assertEquals("Jan", student.firstName)
assertEquals("Marek", student.secondName)
@ -413,85 +318,52 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun messagesTest() {
val units = api.getReportingUnits()
val unitsObserver = TestObserver<List<ReportingUnit>>()
units.subscribe(unitsObserver)
unitsObserver.assertComplete()
val units = runBlocking { api.getReportingUnits() }
assertEquals(1, units.size)
val recipients = api.getRecipients(6)
val recipientsObserver = TestObserver<List<Recipient>>()
recipients.subscribe(recipientsObserver)
recipientsObserver.assertComplete()
val recipients = runBlocking { api.getRecipients(6) }
assertEquals(10, recipients.size)
val messages = api.getMessages(Folder.RECEIVED)
val messagesObserver = TestObserver<List<Message>>()
messages.subscribe(messagesObserver)
messagesObserver.assertComplete()
val messages = runBlocking { api.getMessages(Folder.RECEIVED) }
assertEquals(2, messages.size)
val inbox = api.getReceivedMessages(getLocalDateTime(2015, 10, 5))
val inboxObserver = TestObserver<List<Message>>()
inbox.subscribe(inboxObserver)
inboxObserver.assertComplete()
val inbox = runBlocking { api.getReceivedMessages(getLocalDateTime(2015, 10, 5)) }
assertEquals(2, inbox.size)
assertEquals(2, inboxObserver.values()[0].size)
val sent = runBlocking { api.getSentMessages() }
assertEquals(1, sent.size)
val sent = api.getSentMessages()
val outObserver = TestObserver<List<Message>>()
sent.subscribe(outObserver)
outObserver.assertComplete()
val trash = runBlocking { api.getDeletedMessages() }
assertEquals(1, trash.size)
assertEquals(1, outObserver.values()[0].size)
val mRecipients = runBlocking { api.getMessageRecipients(trash[0].messageId ?: 0) }
assertEquals(2, mRecipients.size)
val trash = api.getDeletedMessages()
val trashObserver = TestObserver<List<Message>>()
trash.subscribe(trashObserver)
trashObserver.assertComplete()
val del = trashObserver.values()[0]
assertEquals(1, del.size)
val mRecipients = api.getMessageRecipients(del[0].messageId ?: 0)
val mRecipientsObserver = TestObserver<List<Recipient>>()
mRecipients.subscribe(mRecipientsObserver)
mRecipientsObserver.assertComplete()
val m = api.getMessageDetails(del[0].messageId ?: 0, del[0].folderId)
val mObserver = TestObserver<Message>()
m.subscribe(mObserver)
mObserver.assertComplete()
val details = runBlocking { api.getMessageDetails(trash[0].messageId ?: 0, trash[0].folderId) }
assertEquals(27214, details.id)
}
@Test
fun sendMessage() {
val send = api.sendMessage("Temat wiadomości", "Treść",
listOf(Recipient("0", "Kowalski Jan", 0, 0, 2, "hash"))
)
val sendObserver = TestObserver<SentMessage>()
send.subscribe(sendObserver)
sendObserver.assertComplete()
runBlocking {
api.sendMessage("Temat wiadomości", "Treść",
listOf(Recipient("0", "Kowalski Jan", 0, 0, 2, "hash"))
)
}
}
@Test
fun devicesTest() {
val devices = api.getRegisteredDevices()
val devicesObserver = TestObserver<List<Device>>()
devices.subscribe(devicesObserver)
devicesObserver.assertComplete()
val devices = runBlocking { api.getRegisteredDevices() }
val values = devicesObserver.values()[0]
assertEquals(2, values.size)
assertEquals(2, devices.size)
}
@Test
fun tokenTest() {
val tokenizer = api.getToken()
val tokenObserver = TestObserver<TokenResponse>()
tokenizer.subscribe(tokenObserver)
tokenObserver.assertComplete()
val tokenizer = runBlocking { api.getToken() }
tokenObserver.values()[0].run {
tokenizer.run {
assertEquals("FK100000", token)
assertEquals("powiatwulkanowy", symbol)
assertEquals("999999", pin)
@ -500,24 +372,16 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun unregisterTest() {
val unregister = api.unregisterDevice(1234)
val unregisterObserver = TestObserver<Boolean>()
unregister.subscribe(unregisterObserver)
unregisterObserver.assertComplete()
val unregister = runBlocking { api.unregisterDevice(1234) }
assertEquals(true, unregisterObserver.values()[0])
assertEquals(true, unregister)
}
@Test
fun timetableTest() {
val timetable = api.getTimetable(getLocalDate(2018, 9, 17))
val timetableObserver = TestObserver<List<Timetable>>()
timetable.subscribe(timetableObserver)
timetableObserver.assertComplete()
val timetable = runBlocking { api.getTimetable(getLocalDate(2018, 9, 17)) }
val values = timetableObserver.values()[0]
values[0].run {
timetable[0].run {
assertEquals(1, number)
assertEquals("Fizyka", subject)
assertEquals("Karolina Kowalska", teacher)
@ -531,12 +395,9 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun realizedTest() {
val realized = api.getCompletedLessons(getLocalDate(2018, 9, 17))
val realizedObserver = TestObserver<List<CompletedLesson>>()
realized.subscribe(realizedObserver)
realizedObserver.assertComplete()
val realized = runBlocking { api.getCompletedLessons(getLocalDate(2018, 9, 17)) }
realizedObserver.values()[0][0].run {
realized[0].run {
assertEquals(getDate(2018, 9, 17), date)
assertEquals(1, number)
assertEquals("Historia i społeczeństwo", subject)
@ -549,17 +410,14 @@ class ScrapperRemoteTest : BaseTest() {
@Test
fun luckyNumberTest() {
val luckyNumber = api.getKidsLuckyNumbers()
val luckyNumberObserver = TestObserver<List<LuckyNumber>>()
luckyNumber.subscribe(luckyNumberObserver)
luckyNumberObserver.assertComplete()
val luckyNumber = runBlocking { api.getKidsLuckyNumbers() }
assertEquals(37, luckyNumberObserver.values()[0][0].number)
assertEquals(37, luckyNumber[0].number)
}
@Test
fun freeDays() {
val freeDays = api.getFreeDays().blockingGet()
val freeDays = runBlocking { api.getFreeDays() }
assertEquals(2, freeDays.size)
}
}

View file

@ -1,8 +1,7 @@
package io.github.wulkanowy.sdk.scrapper
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceSummaryTest
import io.github.wulkanowy.sdk.scrapper.attendance.Subject
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Test
@ -25,18 +24,20 @@ class ScrapperTest : BaseLocalTest() {
diaryId = 101
}
val subjects = api.getSubjects()
val subjectsObserver = TestObserver<List<Subject>>()
subjects.subscribe(subjectsObserver)
subjectsObserver.assertNotComplete() //
try {
runBlocking { api.getSubjects() }
} catch (e: Throwable) {
assert(true) //
}
api.apply {
host = "fakelog.localhost:3000" //
}
val subjects2 = api.getSubjects()
val subjectsObserver2 = TestObserver<List<Subject>>()
subjects2.subscribe(subjectsObserver2)
subjectsObserver2.assertComplete() //
try {
runBlocking { api.getSubjects() }
} catch (e: Throwable) {
assert(false) //
}
}
}

View file

@ -1,6 +1,7 @@
package io.github.wulkanowy.sdk.scrapper.attendance
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.threeten.bp.Month.SEPTEMBER
@ -10,19 +11,19 @@ import org.threeten.bp.Month.JUNE
class AttendanceSummaryTest : BaseLocalTest() {
private val snp by lazy {
getSnpRepo(AttendanceSummaryTest::class.java, "Frekwencja.html").getAttendanceSummary(-1).blockingGet()
runBlocking { getSnpRepo(AttendanceSummaryTest::class.java, "Frekwencja.html").getAttendanceSummary(-1) }
}
private val snpSubjects by lazy {
getSnpRepo(AttendanceSummaryTest::class.java, "Frekwencja.html").getSubjects().blockingGet()
runBlocking { getSnpRepo(AttendanceSummaryTest::class.java, "Frekwencja.html").getSubjects() }
}
private val student by lazy {
getStudentRepo(AttendanceSummaryTest::class.java, "StatystykiFrekwencji.json").getAttendanceSummary(-1).blockingGet()
runBlocking { getStudentRepo(AttendanceSummaryTest::class.java, "StatystykiFrekwencji.json").getAttendanceSummary(-1) }
}
private val studentSubjects by lazy {
getStudentRepo(AttendanceSummaryTest::class.java, "Przedmioty.json").getSubjects().blockingGet()
runBlocking { getStudentRepo(AttendanceSummaryTest::class.java, "Przedmioty.json").getSubjects() }
}
@Test

View file

@ -5,6 +5,7 @@ import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.register.RegisterTest
import io.github.wulkanowy.sdk.scrapper.repository.StudentRepository
import io.github.wulkanowy.sdk.scrapper.service.StudentService
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@ -16,7 +17,7 @@ import org.threeten.bp.LocalDateTime
class AttendanceTest : BaseLocalTest() {
private val student by lazy {
getStudentRepo(AttendanceTest::class.java, "Frekwencja.json").getAttendance(getLocalDate(2018, 10, 1), null).blockingGet()
runBlocking { getStudentRepo(AttendanceTest::class.java, "Frekwencja.json").getAttendance(getLocalDate(2018, 10, 1), null) }
}
override fun getStudentRepo(testClass: Class<*>, fixture: String, loginType: Scrapper.LoginType): StudentRepository {
@ -202,27 +203,32 @@ class AttendanceTest : BaseLocalTest() {
@Test
fun excuseForAbsence() {
server.enqueue(MockResponse().setBody(RegisterTest::class.java.getResource("WitrynaUcznia.html").readText()))
getStudentRepo(AttendanceTest::class.java, "Usprawiedliwione.json").excuseForAbsence(
absents = listOf(
Absent(
date = LocalDateTime.of(2019, 2, 11, 15, 53, 9),
timeId = 1
),
Absent(
date = LocalDateTime.of(2019, 2, 11, 15, 53, 9),
timeId = 2
),
Absent(
date = LocalDateTime.of(2019, 2, 11, 15, 53, 9),
timeId = 3
),
Absent(
date = LocalDateTime.of(2019, 2, 12, 15, 53, 9),
timeId = null
)
val absents = listOf(
Absent(
date = LocalDateTime.of(2019, 2, 11, 15, 53, 9),
timeId = 1
),
content = "Test"
).blockingGet()
Absent(
date = LocalDateTime.of(2019, 2, 11, 15, 53, 9),
timeId = 2
),
Absent(
date = LocalDateTime.of(2019, 2, 11, 15, 53, 9),
timeId = 3
),
Absent(
date = LocalDateTime.of(2019, 2, 12, 15, 53, 9),
timeId = null
)
)
runBlocking {
getStudentRepo(AttendanceTest::class.java, "Usprawiedliwione.json").excuseForAbsence(
absents = absents,
content = "Test"
)
}
server.takeRequest()

View file

@ -1,21 +1,22 @@
package io.github.wulkanowy.sdk.scrapper.exams
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class ExamsTest : BaseLocalTest() {
private val snp by lazy {
getSnpRepo(ExamsTest::class.java, "Sprawdziany-one-per-day.html").getExams(getLocalDate(2018, 10, 1)).blockingGet()
runBlocking { getSnpRepo(ExamsTest::class.java, "Sprawdziany-one-per-day.html").getExams(getLocalDate(2018, 10, 1)) }
}
private val snpEmpty by lazy {
getSnpRepo(ExamsTest::class.java, "Sprawdziany-empty.html").getExams(getLocalDate(2018, 10, 1)).blockingGet()
runBlocking { getSnpRepo(ExamsTest::class.java, "Sprawdziany-empty.html").getExams(getLocalDate(2018, 10, 1)) }
}
private val student by lazy {
getStudentRepo(ExamsTest::class.java, "Sprawdziany.json").getExams(getLocalDate(2018, 10, 1)).blockingGet()
runBlocking { getStudentRepo(ExamsTest::class.java, "Sprawdziany.json").getExams(getLocalDate(2018, 10, 1)) }
}
@Test

View file

@ -1,25 +1,26 @@
package io.github.wulkanowy.sdk.scrapper.grades
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class GradesGradeSummaryTest : BaseLocalTest() {
private val std by lazy {
getSnpRepo(GradesTest::class.java, "OcenyWszystkie-subjects.html").getGradesSummary(0).blockingGet()
runBlocking { getSnpRepo(GradesTest::class.java, "OcenyWszystkie-subjects.html").getGradesSummary(0) }
}
private val snp by lazy {
getSnpRepo(GradesTest::class.java, "OcenyWszystkie-subjects-average.html").getGradesSummary(0).blockingGet()
runBlocking { getSnpRepo(GradesTest::class.java, "OcenyWszystkie-subjects-average.html").getGradesSummary(0) }
}
private val student by lazy {
getStudentRepo(GradesTest::class.java, "Oceny.json").getGradesSummary(0).blockingGet()
runBlocking { getStudentRepo(GradesTest::class.java, "Oceny.json").getGradesSummary(0) }
}
private val studentPoints by lazy {
getStudentRepo(GradesTest::class.java, "Oceny-points.json").getGradesSummary(0).blockingGet()
runBlocking { getStudentRepo(GradesTest::class.java, "Oceny-points.json").getGradesSummary(0) }
}
@Test

View file

@ -1,29 +1,30 @@
package io.github.wulkanowy.sdk.scrapper.grades
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class GradesStatisticsTest : BaseLocalTest() {
private val snpPartial by lazy {
getSnpRepo(GradesStatisticsTest::class.java, "Statystyki-czastkowe.html").getGradesStatistics(123, false).blockingGet()
runBlocking { getSnpRepo(GradesStatisticsTest::class.java, "Statystyki-czastkowe.html").getGradesStatistics(123, false) }
}
private val snpAnnual by lazy {
getSnpRepo(GradesStatisticsTest::class.java, "Statystyki-roczne.html").getGradesStatistics(321, true).blockingGet()
runBlocking { getSnpRepo(GradesStatisticsTest::class.java, "Statystyki-roczne.html").getGradesStatistics(321, true) }
}
private val studentPartial by lazy {
getStudentRepo(GradesStatisticsTest::class.java, "Statystyki-czastkowe.json").getGradesPartialStatistics(123).blockingGet()
runBlocking { getStudentRepo(GradesStatisticsTest::class.java, "Statystyki-czastkowe.json").getGradesPartialStatistics(123) }
}
private val studentAnnual by lazy {
getStudentRepo(GradesStatisticsTest::class.java, "Statystyki-roczne.json").getGradesAnnualStatistics(321).blockingGet()
runBlocking { getStudentRepo(GradesStatisticsTest::class.java, "Statystyki-roczne.json").getGradesAnnualStatistics(321) }
}
private val points by lazy {
getStudentRepo(GradesStatisticsTest::class.java, "Statystyki-punkty.json").getGradesPointsStatistics(420).blockingGet()
runBlocking { getStudentRepo(GradesStatisticsTest::class.java, "Statystyki-punkty.json").getGradesPointsStatistics(420) }
}
@Test

View file

@ -1,21 +1,22 @@
package io.github.wulkanowy.sdk.scrapper.grades
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class GradesTest : BaseLocalTest() {
private val snp by lazy {
getSnpRepo(GradesTest::class.java, "OcenyWszystkie-details.html").getGradesDetails(0).blockingGet()
runBlocking { getSnpRepo(GradesTest::class.java, "OcenyWszystkie-details.html").getGradesDetails(0) }
}
private val student by lazy {
getStudentRepo(GradesTest::class.java, "Oceny.json").getGradesDetails(0).blockingGet()
runBlocking { getStudentRepo(GradesTest::class.java, "Oceny.json").getGradesDetails(0) }
}
private val studentPoints by lazy {
getStudentRepo(GradesTest::class.java, "Oceny-points.json").getGradesDetails(0).blockingGet()
runBlocking { getStudentRepo(GradesTest::class.java, "Oceny-points.json").getGradesDetails(0) }
}
@Test

View file

@ -4,6 +4,7 @@ import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.home.LuckyNumber
import io.github.wulkanowy.sdk.scrapper.repository.HomepageRepository
import io.github.wulkanowy.sdk.scrapper.service.HomepageService
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
@ -21,7 +22,7 @@ class HomepageTest : BaseLocalTest() {
server.enqueue("GetSelfGovernments.json")
server.start(3000)
val units = repo.getSelfGovernments().blockingGet()
val units = runBlocking { repo.getSelfGovernments() }
assertEquals(1, units.size)
assertEquals("ZST-I", units[0].unitName)
@ -45,7 +46,7 @@ class HomepageTest : BaseLocalTest() {
server.enqueue("GetStudentThreats.json")
server.start(3000)
val threats = repo.getStudentThreats().blockingGet()
val threats = runBlocking { repo.getStudentThreats() }
assertEquals(1, threats.size)
assertEquals("Jan Kowalski matematyka", threats[0])
}
@ -56,7 +57,7 @@ class HomepageTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(HomepageTest::class.java.getResource("GetLastNotes.json").readText()))
server.start(3000)
val res = repo.getLastGrades().blockingGet()
val res = runBlocking { repo.getLastGrades() }
assertEquals(
listOf(
"j. angielski: 1, 6",
@ -72,7 +73,7 @@ class HomepageTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(HomepageTest::class.java.getResource("GetFreeDays.json").readText()))
server.start(3000)
val res = repo.getFreeDays().blockingGet()
val res = runBlocking { repo.getFreeDays() }
assertEquals(
listOf(
"Czwartek (20.06.2019) - Sobota (31.08.2019) - Ferie letnie",
@ -107,7 +108,7 @@ class HomepageTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(HomepageTest::class.java.getResource("GetKidsLuckyNumbers.json").readText()))
server.start(3000)
val number = repo.getKidsLuckyNumbers().blockingGet()
val number = runBlocking { repo.getKidsLuckyNumbers() }
assertEquals(listOf(LuckyNumber("", "SPL", 18)), number)
server.takeRequest()
@ -123,7 +124,7 @@ class HomepageTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(HomepageTest::class.java.getResource("GetKidsLuckyNumbers-multi-institution.json").readText()))
server.start(3000)
val numbers = repo.getKidsLuckyNumbers().blockingGet()
val numbers = runBlocking { repo.getKidsLuckyNumbers() }
assertEquals(listOf(
LuckyNumber("002547", "T", 37),
LuckyNumber("010472", "ZSP Warcie", 12)

View file

@ -4,13 +4,14 @@ import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.repository.StudentRepository
import io.github.wulkanowy.sdk.scrapper.service.StudentService
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class HomeworkTest : BaseLocalTest() {
private val snp by lazy {
getSnpRepo(HomeworkTest::class.java, "ZadaniaDomowe.html").getHomework(getLocalDate(2018, 10, 1)).blockingGet()
runBlocking { getSnpRepo(HomeworkTest::class.java, "ZadaniaDomowe.html").getHomework(getLocalDate(2018, 10, 1)) }
}
private val studentRaw by lazy {
@ -18,7 +19,7 @@ class HomeworkTest : BaseLocalTest() {
}
private val student by lazy {
getStudentRepo(HomeworkTest::class.java, "Homework.json").getHomework(getLocalDate(2018, 10, 1)).blockingGet()
runBlocking { getStudentRepo(HomeworkTest::class.java, "Homework.json").getHomework(getLocalDate(2018, 10, 1)) }
}
@Test
@ -66,7 +67,7 @@ class HomeworkTest : BaseLocalTest() {
server.enqueue("ZadaniaDomowe.json")
server.start(3030)
val homework = studentRaw.getHomework(getLocalDate(2018, 10, 1)).blockingGet()
val homework = runBlocking { studentRaw.getHomework(getLocalDate(2018, 10, 1)) }
assertEquals(2, homework.size)
}
}

View file

@ -7,74 +7,82 @@ import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.login.LoginTest
import io.github.wulkanowy.sdk.scrapper.login.NotLoggedInException
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
import io.github.wulkanowy.sdk.scrapper.notes.Note
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertTrue
import org.junit.Test
class ErrorInterceptorTest : BaseLocalTest() {
@Test
fun notLoggedIn_standard() {
val notes = getSnpRepo(LoginTest::class.java, "Logowanie-standard.html", Scrapper.LoginType.STANDARD).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(NotLoggedInException::class.java)
try {
runBlocking { getSnpRepo(LoginTest::class.java, "Logowanie-standard.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is NotLoggedInException)
}
}
@Test
fun notLoggedIn_standard2() {
val notes = getSnpRepo(LoginTest::class.java, "LoginPage-standard.html", Scrapper.LoginType.STANDARD).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(NotLoggedInException::class.java)
try {
runBlocking { getSnpRepo(LoginTest::class.java, "LoginPage-standard.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is NotLoggedInException)
}
}
@Test
fun notLoggedIn_adfs() {
val notes = getSnpRepo(LoginTest::class.java, "ADFS-form-2.html", Scrapper.LoginType.ADFS).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(NotLoggedInException::class.java)
try {
runBlocking { getSnpRepo(LoginTest::class.java, "ADFS-form-2.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is NotLoggedInException)
}
}
@Test
fun notLoggedIn_adfsCards() {
val notes = getSnpRepo(LoginTest::class.java, "ADFS-form-1.html", Scrapper.LoginType.ADFSCards).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(NotLoggedInException::class.java)
try {
runBlocking { getSnpRepo(LoginTest::class.java, "ADFS-form-1.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is NotLoggedInException)
}
}
@Test
fun notLoggedInt_adfsLight() {
val notes = getSnpRepo(LoginTest::class.java, "ADFSLight-form-1.html", Scrapper.LoginType.ADFSLight).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(NotLoggedInException::class.java)
try {
runBlocking { getSnpRepo(LoginTest::class.java, "ADFSLight-form-1.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is NotLoggedInException)
}
}
@Test
fun offline_databaseUpdate() {
val notes = getSnpRepo(ErrorInterceptorTest::class.java, "AktualizacjaBazyDanych.html", Scrapper.LoginType.STANDARD).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(ServiceUnavailableException::class.java)
try {
runBlocking { getSnpRepo(ErrorInterceptorTest::class.java, "AktualizacjaBazyDanych.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is ServiceUnavailableException)
}
}
@Test
fun passwordChangeRequired() {
val notes = getSnpRepo(LoginTest::class.java, "PrzywracanieDostepu.html", Scrapper.LoginType.ADFSLight).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(PasswordChangeRequiredException::class.java)
try {
runBlocking { getSnpRepo(LoginTest::class.java, "PrzywracanieDostepu.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is PasswordChangeRequiredException)
}
}
@Test
fun error_unknown() {
val notes = getSnpRepo(ErrorInterceptorTest::class.java, "Błąd-adfs.html", Scrapper.LoginType.ADFSLight).getNotes()
val observer = TestObserver<List<Note>>()
notes.subscribe(observer)
observer.assertError(VulcanException::class.java)
observer.assertError { it.message?.startsWith("Błąd") == true }
try {
runBlocking { getSnpRepo(ErrorInterceptorTest::class.java, "Błąd-adfs.html", Scrapper.LoginType.STANDARD).getNotes() }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertTrue(e.message?.startsWith("Błąd") == true)
}
}
}

View file

@ -1,13 +1,12 @@
package io.github.wulkanowy.sdk.scrapper.login
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.homework.HomeworkTest
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorInterceptorTest
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.register.SendCertificateResponse
import io.github.wulkanowy.sdk.scrapper.service.LoginService
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@ -36,7 +35,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Login-success.html").readText()))
server.start(3000)
val res = adfs.login("jan@fakelog.cf", "jan123").blockingGet()
val res = runBlocking { adfs.login("jan@fakelog.cf", "jan123") }
assertTrue(res.oldStudentSchools.isNotEmpty())
}
@ -47,7 +46,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Login-success.html").readText()))
server.start(3000)
val res = normal.login("jan@fakelog.cf", "jan123").blockingGet()
val res = runBlocking { normal.login("jan@fakelog.cf", "jan123") }
assertTrue(res.oldStudentSchools.isNotEmpty())
}
@ -58,7 +57,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Login-success.html").readText()))
server.start(3000)
normal.login("jan@fakelog.cf", "jan123").blockingGet()
runBlocking { normal.login("jan@fakelog.cf", "jan123") }
assertEquals("[text=LoginName=jan%40fakelog.cf&Password=jan123]", server.takeRequest().body.toString())
}
@ -70,7 +69,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Login-success-account-switch.html").readText()))
server.start(3000)
normal.login("jan||jan@fakelog.cf", "jan123").blockingGet()
runBlocking { normal.login("jan||jan@fakelog.cf", "jan123") }
assertEquals("[text=LoginName=jan&Password=jan123]", server.takeRequest().body.toString())
}
@ -81,7 +80,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Login-success-old.html").readText()))
server.start(3000)
val res = normal.login("jan@fakelog.cf", "jan123").blockingGet()
val res = runBlocking { normal.login("jan@fakelog.cf", "jan123") }
assertTrue(res.oldStudentSchools.isNotEmpty())
}
@ -92,7 +91,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Login-success.html").readText()))
server.start(3000)
normal.login("jan@fakelog.cf", "jan123").blockingGet()
runBlocking { normal.login("jan@fakelog.cf", "jan123") }
server.takeRequest()
assertFalse(server.takeRequest().body.readUtf8().contains("ValueType%3D%26t%3Bhttp")) // ValueType=&t;http
@ -105,11 +104,11 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-adfs-zle-haslo.html").readText()))
server.start(3000)
val res = adfs.login("jan@fakelog.cf", "jan1234")
val observer = TestObserver<SendCertificateResponse>()
res.subscribe(observer)
observer.assertTerminated()
observer.assertError(BadCredentialsException::class.java)
try {
runBlocking { adfs.login("jan@fakelog.cf", "jan1234") }
} catch (e: Throwable) {
assertTrue(e is BadCredentialsException)
}
}
@Test
@ -118,11 +117,11 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-normal-zle-haslo.html").readText()))
server.start(3000)
val res = normal.login("jan@fakelog.cf", "jan1234")
val observer = TestObserver<SendCertificateResponse>()
res.subscribe(observer)
observer.assertTerminated()
observer.assertError(BadCredentialsException::class.java)
try {
runBlocking { adfs.login("jan@fakelog.cf", "jan1234") }
} catch (e: Throwable) {
assertTrue(e is BadCredentialsException)
}
}
@Test
@ -131,13 +130,11 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = normal.login("jan@fakelog.cf", "jan123")
val observer = TestObserver<SendCertificateResponse>()
res.subscribe(observer)
observer.assertTerminated()
observer.assertError(AccountPermissionException::class.java)
observer.assertError {
it.localizedMessage == "Adres nie został zarejestrowany w dzienniku uczniowskim jako adres rodzica, bądź ucznia."
try {
runBlocking { adfs.login("jan@fakelog.cf", "jan1234") }
} catch (e: Throwable) {
assertTrue(e is AccountPermissionException)
assertEquals("Adres nie został zarejestrowany w dzienniku uczniowskim jako adres rodzica, bądź ucznia.", e.message)
}
}
@ -146,10 +143,7 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(HomeworkTest::class.java.getResource("ZadaniaDomowe.html").readText()))
server.start(3000)
val res = normal.login("jan@fakelog.cf", "jan123")
val observer = TestObserver<SendCertificateResponse>()
res.subscribe(observer)
observer.assertComplete()
runBlocking { normal.login("jan@fakelog.cf", "jan123") }
}
@Test
@ -157,10 +151,10 @@ class LoginTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(ErrorInterceptorTest::class.java.getResource("Offline.html").readText()))
server.start(3000)
val res = normal.login("jan@fakelog.cf", "jan123")
val observer = TestObserver<SendCertificateResponse>()
res.subscribe(observer)
observer.assertTerminated()
observer.assertError(VulcanException::class.java)
try {
runBlocking { adfs.login("jan@fakelog.cf", "jan1234") }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
}
}
}

View file

@ -6,9 +6,10 @@ import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.login.LoginTest
import io.github.wulkanowy.sdk.scrapper.repository.MessagesRepository
import io.github.wulkanowy.sdk.scrapper.service.MessagesService
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
class MessagesTest : BaseLocalTest() {
@ -22,7 +23,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("Adresaci.json").readText()))
server.start(3000)
val recipients = api.getRecipients(6).blockingGet()
val recipients = runBlocking { api.getRecipients(6) }
assertEquals(4, recipients.size)
@ -52,7 +53,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WiadomosciOdebrane.json").readText()))
server.start(3000)
val messages = api.getReceivedMessages(null, null).blockingGet()
val messages = runBlocking { api.getReceivedMessages(null, null) }
assertEquals(2, messages.size)
with(messages[0]) {
@ -73,7 +74,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WiadomosciUsuniete.json").readText()))
server.start(3000)
assertEquals(1, api.getDeletedMessages(null, null).blockingGet().size)
assertEquals(1, runBlocking { api.getDeletedMessages(null, null) }.size)
}
@Test
@ -81,7 +82,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WiadomosciWyslane.json").readText()))
server.start(3000)
val messages = api.getSentMessages(null, null).blockingGet()
val messages = runBlocking { api.getSentMessages(null, null) }
assertEquals(6, messages.size)
@ -100,7 +101,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WiadomosciWyslane.json").readText()))
server.start(3000)
api.getSentMessages(null, null).blockingGet()[1].run {
runBlocking { api.getSentMessages(null, null) }[1].run {
assertEquals("Czerwieńska - Kowalska Joanna", recipient)
}
}
@ -110,7 +111,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WiadomosciWyslane.json").readText()))
server.start(3000)
api.getSentMessages(null, null).blockingGet()[3].run {
runBlocking { api.getSentMessages(null, null) }[3].run {
assertEquals("Czerwieńska - Kowalska Joanna; Tracz Janusz", recipient)
}
}
@ -120,7 +121,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WiadomosciWyslane.json").readText()))
server.start(3000)
api.getSentMessages(null, null).blockingGet()[5].run {
runBlocking { api.getSentMessages(null, null) }[5].run {
assertEquals("Tracz Antoni; Kowalska Joanna", recipient)
}
}
@ -130,7 +131,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("Adresaci.json").readText()))
server.start(3000)
api.getMessageRecipients(421, 0).blockingGet()[0].run {
runBlocking { api.getMessageRecipients(421, 0) }[0].run {
assertEquals("18rPracownik", id)
assertEquals("Tracz Janusz [TJ] - pracownik (Fake123456)", name)
assertEquals(18, loginId)
@ -146,7 +147,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("Adresaci.json").readText()))
server.start(3000)
api.getMessageRecipients(421, 94).blockingGet()[1].run {
runBlocking { api.getMessageRecipients(421, 94) }[1].run {
assertEquals("94rPracownik", id)
assertEquals(94, loginId)
}
@ -157,7 +158,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("Wiadomosc.json").readText()))
server.start(3000)
assertEquals(90, api.getMessage(1, 1, false, 0).blockingGet().length)
assertEquals(90, runBlocking { api.getMessage(1, 1, false, 0) }.length)
}
@Test
@ -165,7 +166,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("Wiadomosc.json").readText()))
server.start(3000)
val attachments = api.getMessageAttachments(1, 1).blockingGet()
val attachments = runBlocking { api.getMessageAttachments(1, 1) }
assertEquals(1, attachments.size)
with(attachments[0]) {
@ -183,10 +184,12 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(MessagesTest::class.java.getResource("WyslanaWiadomosc.json").readText()))
server.start(3000)
api.sendMessage(
"Temat wiadomości", "Tak wygląda zawartość wiadomości.\nZazwyczaj ma wiele linijek.\n\nZ poważaniem,\nNazwisko Imię",
listOf(Recipient("0", "Kowalski Jan", 0, 0, 2, "hash"))
).blockingGet()
runBlocking {
api.sendMessage(
"Temat wiadomości", "Tak wygląda zawartość wiadomości.\nZazwyczaj ma wiele linijek.\n\nZ poważaniem,\nNazwisko Imię",
listOf(Recipient("0", "Kowalski Jan", 0, 0, 2, "hash"))
)
}
server.takeRequest()
@ -209,12 +212,12 @@ class MessagesTest : BaseLocalTest() {
server.start(3000)
val api = MessagesRepository(getService(MessagesService::class.java, "http://fakelog.localhost:3000/", false, loginType = Scrapper.LoginType.ADFSLight))
val sent = api.sendMessage("Temat", "Treść", listOf())
val observer = TestObserver<SentMessage>()
sent.subscribe(observer)
observer.assertNotComplete()
observer.assertError(ScrapperException::class.java)
observer.assertErrorMessage("User not logged in")
try {
runBlocking { api.sendMessage("Temat", "Treść", listOf()) }
} catch (e: Throwable) {
assertTrue(e is ScrapperException)
assertEquals("User not logged in", e.message)
}
}
@Test
@ -223,7 +226,7 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody("{\"success\": true}"))
server.start(3000)
assertEquals(api.deleteMessages(listOf(Pair(74, 1), Pair(69, 2))).blockingGet(), true)
assertEquals(runBlocking { api.deleteMessages(listOf(Pair(74, 1), Pair(69, 2))) }, true)
server.takeRequest()
@ -246,9 +249,10 @@ class MessagesTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(""))
server.start(3000)
val deleted = api.deleteMessages(listOf(Pair(74, 1), Pair(69, 2)))
val observer = TestObserver<Boolean>()
deleted.subscribe(observer)
observer.assertErrorMessage("Unexpected empty response. Message(s) may already be deleted")
try {
runBlocking { api.deleteMessages(listOf(Pair(74, 1), Pair(69, 2))) }
} catch (e: Throwable) {
assertEquals("Unexpected empty response. Message(s) may already be deleted", e.message)
}
}
}

View file

@ -1,6 +1,7 @@
package io.github.wulkanowy.sdk.scrapper.mobile
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
@ -8,19 +9,19 @@ import org.junit.Test
class MobileTest : BaseLocalTest() {
private val devicesSnp by lazy {
getSnpRepo(MobileTest::class.java, "DostepMobilny-filled.html").getRegisteredDevices().blockingGet()
runBlocking { getSnpRepo(MobileTest::class.java, "DostepMobilny-filled.html").getRegisteredDevices() }
}
private val tokenSnp by lazy {
getSnpRepo(MobileTest::class.java, "Rejestruj.html").getToken().blockingGet()
runBlocking { getSnpRepo(MobileTest::class.java, "Rejestruj.html").getToken() }
}
private val devicesStudent by lazy {
getStudentRepo(MobileTest::class.java, "ZarejestrowaneUrzadzenia.json").getRegisteredDevices().blockingGet()
runBlocking { getStudentRepo(MobileTest::class.java, "ZarejestrowaneUrzadzenia.json").getRegisteredDevices() }
}
private val tokenStudent by lazy {
getStudentRepo(MobileTest::class.java, "RejestracjaUrzadzeniaToken.json").getToken().blockingGet()
runBlocking { getStudentRepo(MobileTest::class.java, "RejestracjaUrzadzeniaToken.json").getToken() }
}
@Test

View file

@ -1,17 +1,18 @@
package io.github.wulkanowy.sdk.scrapper.notes
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class NotesTest : BaseLocalTest() {
private val student by lazy {
getStudentRepo(NotesTest::class.java, "UwagiIOsiagniecia.json").getNotes().blockingGet()
runBlocking { getStudentRepo(NotesTest::class.java, "UwagiIOsiagniecia.json").getNotes() }
}
private val studentPoints by lazy {
getStudentRepo(NotesTest::class.java, "UwagiIOsiagniecia-points.json").getNotes().blockingGet()
runBlocking { getStudentRepo(NotesTest::class.java, "UwagiIOsiagniecia-points.json").getNotes() }
}
@Test

View file

@ -1,7 +1,7 @@
package io.github.wulkanowy.sdk.scrapper.register
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.grades.GradesTest
import io.github.wulkanowy.sdk.scrapper.login.LoginHelper
import io.github.wulkanowy.sdk.scrapper.login.LoginTest
@ -12,6 +12,7 @@ import io.github.wulkanowy.sdk.scrapper.service.RegisterService
import io.github.wulkanowy.sdk.scrapper.service.ServiceManager
import io.github.wulkanowy.sdk.scrapper.service.StudentAndParentService
import io.github.wulkanowy.sdk.scrapper.service.StudentService
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Test
@ -21,7 +22,7 @@ class RegisterTest : BaseLocalTest() {
private val login by lazy {
LoginHelper(Scrapper.LoginType.STANDARD, "http", "fakelog.localhost:3000", "default", CookieManager(),
getService(LoginService::class.java, "http://fakelog.localhost:3000/", true, true, false, Scrapper.LoginType.STANDARD))
getService(LoginService::class.java, "http://fakelog.localhost:3000/", true, true, false, Scrapper.LoginType.STANDARD))
}
private val registerSnp by lazy {
@ -44,7 +45,7 @@ class RegisterTest : BaseLocalTest() {
private val snp by lazy {
StudentAndParentStartRepository("default", "0012345", 123,
getService(StudentAndParentService::class.java, "http://fakelog.localhost:3000/"))
getService(StudentAndParentService::class.java, "http://fakelog.localhost:3000/"))
}
@Test
@ -62,7 +63,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(1, res.size)
assertEquals("Jan Kowal", res[0].studentName)
@ -83,7 +84,7 @@ class RegisterTest : BaseLocalTest() {
server.start(3000)
val res = registerStudent.getStudents().blockingGet()
val res = runBlocking { registerStudent.getStudents() }
assertEquals(2, res.size)
@ -119,7 +120,7 @@ class RegisterTest : BaseLocalTest() {
server.start(3000)
val res = registerStudent.getStudents().blockingGet()
val res = runBlocking { registerStudent.getStudents() }
assertEquals(1, res.size)
@ -147,7 +148,7 @@ class RegisterTest : BaseLocalTest() {
server.start(3000)
val res = registerStudent.getStudents().blockingGet()
val res = runBlocking { registerStudent.getStudents() }
assertEquals(1, res.size)
@ -175,7 +176,7 @@ class RegisterTest : BaseLocalTest() {
server.start(3000)
val res = registerStudent.getStudents().blockingGet()
val res = runBlocking { registerStudent.getStudents() }
assertEquals(2, res.size)
@ -205,7 +206,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(GradesTest::class.java.getResource("OcenyWszystkie-details.html").readText().replace("1234568", "1234572")))
server.start(3000)
val res = snp.getSemesters().blockingGet()
val res = runBlocking { snp.getSemesters() }
assertEquals(6, res.size)
assertEquals(1234567, res[0].semesterId)
@ -231,7 +232,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(Scrapper.LoginType.STANDARD, res[0].loginType)
}
@ -252,7 +253,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(Scrapper.LoginType.ADFS, res[0].loginType)
}
@ -274,7 +275,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(Scrapper.LoginType.ADFSCards, res[0].loginType)
}
@ -294,7 +295,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(Scrapper.LoginType.ADFSLight, res[0].loginType)
}
@ -314,7 +315,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(Scrapper.LoginType.ADFSLight, res[0].loginType)
}
@ -334,7 +335,7 @@ class RegisterTest : BaseLocalTest() {
server.enqueue(MockResponse().setBody(LoginTest::class.java.getResource("Logowanie-brak-dostepu.html").readText()))
server.start(3000)
val res = registerSnp.getStudents().blockingGet()
val res = runBlocking { registerSnp.getStudents() }
assertEquals(Scrapper.LoginType.ADFSLightScoped, res[0].loginType)
}
}

View file

@ -1,19 +1,19 @@
package io.github.wulkanowy.sdk.scrapper.repository
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorInterceptorTest
import io.github.wulkanowy.sdk.scrapper.login.LoginHelper
import io.github.wulkanowy.sdk.scrapper.login.LoginTest
import io.github.wulkanowy.sdk.scrapper.register.RegisterTest
import io.github.wulkanowy.sdk.scrapper.register.Student
import io.github.wulkanowy.sdk.scrapper.service.LoginService
import io.github.wulkanowy.sdk.scrapper.service.RegisterService
import io.github.wulkanowy.sdk.scrapper.service.ServiceManager
import io.github.wulkanowy.sdk.scrapper.service.StudentAndParentService
import io.github.wulkanowy.sdk.scrapper.service.StudentService
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
@ -50,11 +50,7 @@ class RegisterRepositoryTest : BaseLocalTest() {
}
server.start(3000)
val res = getRegisterRepository("Default", true).getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertComplete()
val students = observer.values()[0]
val students = runBlocking { getRegisterRepository("Default", true).getStudents() }
assertEquals(1, students.size)
with(students[0]) {
@ -81,11 +77,7 @@ class RegisterRepositoryTest : BaseLocalTest() {
}
server.start(3000)
val res = getRegisterRepository("Default", true).getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertComplete()
val students = observer.values()[0]
val students = runBlocking { getRegisterRepository("Default", true).getStudents() }
assertEquals(3, students.size)
with(students[0]) {
@ -125,11 +117,7 @@ class RegisterRepositoryTest : BaseLocalTest() {
}
server.start(3000)
val res = getRegisterRepository("Default", true).getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertComplete()
val students = observer.values()[0]
val students = runBlocking { getRegisterRepository("Default", true).getStudents() }
assertEquals(2, students.size)
}
@ -141,11 +129,11 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.enqueue("Offline.html", ErrorInterceptorTest::class.java)
server.start(3000)
val res = normal.getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertTerminated()
observer.assertError(ScrapperException::class.java)
try {
runBlocking { normal.getStudents() }
} catch (e: Throwable) {
assertTrue(e is ScrapperException)
}
}
@Test
@ -161,10 +149,7 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.start(3000)
val res = normal.getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertComplete()
runBlocking { normal.getStudents() }
}
@Test
@ -176,10 +161,12 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.start(3000)
val res = getRegisterRepository("Default").getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertTerminated()
try {
runBlocking { getRegisterRepository("Default").getStudents() }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertEquals("Wystąpił nieoczekiwany błąd. Wystąpił błąd aplikacji. Prosimy zalogować się ponownie. Jeśli problem będzie się powtarzał, prosimy o kontakt z serwisem.", e.message)
}
assertEquals("/Default/Account/LogOn", server.takeRequest().path)
}
@ -193,10 +180,12 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.start(3000)
val res = getRegisterRepository(" Rzeszów + ").getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertTerminated()
try {
runBlocking { getRegisterRepository(" Rzeszów + ").getStudents() }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertEquals("Wystąpił nieoczekiwany błąd. Wystąpił błąd aplikacji. Prosimy zalogować się ponownie. Jeśli problem będzie się powtarzał, prosimy o kontakt z serwisem.", e.message)
}
assertEquals("/rzeszow/Account/LogOn", server.takeRequest().path)
}
@ -210,10 +199,12 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.start(3000)
val res = getRegisterRepository(" Niepoprawny symbol no ale + ").getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertTerminated()
try {
runBlocking { getRegisterRepository(" Niepoprawny symbol no ale + ").getStudents() }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertEquals("Wystąpił nieoczekiwany błąd. Wystąpił błąd aplikacji. Prosimy zalogować się ponownie. Jeśli problem będzie się powtarzał, prosimy o kontakt z serwisem.", e.message)
}
assertEquals("/niepoprawnysymbolnoale/Account/LogOn", server.takeRequest().path)
}
@ -227,10 +218,12 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.start(3000)
val res = getRegisterRepository(" + ").getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertTerminated()
try {
runBlocking { getRegisterRepository(" + ").getStudents() }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertEquals("Wystąpił nieoczekiwany błąd. Wystąpił błąd aplikacji. Prosimy zalogować się ponownie. Jeśli problem będzie się powtarzał, prosimy o kontakt z serwisem.", e.message)
}
assertEquals("/Default/Account/LogOn", server.takeRequest().path)
}
@ -244,10 +237,12 @@ class RegisterRepositoryTest : BaseLocalTest() {
server.start(3000)
val res = getRegisterRepository("Default").getStudents()
val observer = TestObserver<List<Student>>()
res.subscribe(observer)
observer.assertTerminated()
try {
runBlocking { getRegisterRepository("Default").getStudents() }
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertEquals("Wystąpił nieoczekiwany błąd. Wystąpił błąd aplikacji. Prosimy zalogować się ponownie. Jeśli problem będzie się powtarzał, prosimy o kontakt z serwisem.", e.message)
}
assertEquals("/Default/Account/LogOn", server.takeRequest().path)
assertTrue(server.takeRequest().path.startsWith("/Account/LogOn?ReturnUrl=%2FDefault"))

View file

@ -5,8 +5,7 @@ import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.grades.GradesTest
import io.github.wulkanowy.sdk.scrapper.login.LoginTest
import io.github.wulkanowy.sdk.scrapper.register.RegisterTest
import io.github.wulkanowy.sdk.scrapper.register.Semester
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Test
@ -34,11 +33,11 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.STANDARD
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertTerminated()
semestersObserver.assertErrorMessage("Unknow page with title: Uonet+")
try {
runBlocking { api.getSemesters() }
} catch (e: Throwable) {
assertEquals("Unknow page with title: Uonet+", e.message)
}
}
@Test
@ -54,11 +53,11 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.STANDARD
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertTerminated()
semestersObserver.assertErrorMessage("Unknow page with title: Witryna ucznia i rodzica Strona główna")
try {
runBlocking { api.getSemesters() }
} catch (e: Throwable) {
assertEquals("Unknow page with title: Witryna ucznia i rodzica Strona główna", e.message)
}
}
@Test
@ -71,17 +70,12 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.STANDARD
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234567, items[0].semesterId)
assertEquals(1234568, items[1].semesterId)
assertEquals(1234567, semesters[0].semesterId)
assertEquals(1234568, semesters[1].semesterId)
}
@Test
@ -99,17 +93,12 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.STANDARD
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234567, items[0].semesterId)
assertEquals(1234568, items[1].semesterId)
assertEquals(1234567, semesters[0].semesterId)
assertEquals(1234568, semesters[1].semesterId)
}
@Test
@ -129,17 +118,12 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.ADFS
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234567, items[0].semesterId)
assertEquals(1234568, items[1].semesterId)
assertEquals(1234567, semesters[0].semesterId)
assertEquals(1234568, semesters[1].semesterId)
}
@Test
@ -158,17 +142,12 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.ADFSLight
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234567, items[0].semesterId)
assertEquals(1234568, items[1].semesterId)
assertEquals(1234567, semesters[0].semesterId)
assertEquals(1234568, semesters[1].semesterId)
}
@Test
@ -189,18 +168,13 @@ class StudentAndParentStartRepositoryTest : BaseLocalTest() {
api.loginType = Scrapper.LoginType.ADFSCards
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234567, items[0].semesterId)
assertEquals(1234568, items[1].semesterId)
assertEquals(2015, items[0].schoolYear)
assertEquals(2015, items[1].schoolYear)
assertEquals(1234567, semesters[0].semesterId)
assertEquals(1234568, semesters[1].semesterId)
assertEquals(2015, semesters[0].schoolYear)
assertEquals(2015, semesters[1].schoolYear)
}
}

View file

@ -3,8 +3,7 @@ package io.github.wulkanowy.sdk.scrapper.repository
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.register.RegisterTest
import io.github.wulkanowy.sdk.scrapper.register.Semester
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
@ -34,24 +33,19 @@ class StudentStartRepositoryTest : BaseLocalTest() {
api.studentId = 1
api.classId = 1
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234568, semesters[0].semesterId)
assertEquals(1234567, semesters[1].semesterId)
assertEquals(2018, semesters[0].schoolYear)
assertEquals(2018, semesters[1].schoolYear)
assertEquals(1234568, items[0].semesterId)
assertEquals(1234567, items[1].semesterId)
assertEquals(2018, items[0].schoolYear)
assertEquals(2018, items[1].schoolYear)
assertEquals(1234566, items[2].semesterId)
assertEquals(2017, items[2].schoolYear)
assertEquals(2017, items[3].schoolYear)
assertTrue(items.single { it.current }.current)
assertEquals(1234566, semesters[2].semesterId)
assertEquals(2017, semesters[2].schoolYear)
assertEquals(2017, semesters[3].schoolYear)
assertTrue(semesters.single { it.current }.current)
}
@Test
@ -62,14 +56,9 @@ class StudentStartRepositoryTest : BaseLocalTest() {
api.studentId = 1
api.classId = 2 //
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(0, items.size)
assertEquals(0, semesters.size)
}
@Test
@ -80,18 +69,13 @@ class StudentStartRepositoryTest : BaseLocalTest() {
api.studentId = 3881
api.classId = 121
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(2, semesters.size)
assertEquals(2, items.size)
assertEquals(714, items[0].semesterId)
assertEquals(713, items[1].semesterId)
assertTrue(items.single { it.current }.current)
assertEquals(714, semesters[0].semesterId)
assertEquals(713, semesters[1].semesterId)
assertTrue(semesters.single { it.current }.current)
}
@Test
@ -102,19 +86,14 @@ class StudentStartRepositoryTest : BaseLocalTest() {
api.studentId = 2
api.classId = 2
val semesters = api.getSemesters()
val semestersObserver = TestObserver<List<Semester>>()
semesters.subscribe(semestersObserver)
semestersObserver.assertComplete()
val semesters = runBlocking { api.getSemesters() }
val items = semestersObserver.values()[0]
assertEquals(6, semesters.size)
assertEquals(6, items.size)
assertEquals(1234568, items[0].semesterId)
assertEquals(1234568, items.single { it.current }.semesterId)
assertEquals(1234567, items[1].semesterId)
assertTrue(items.single { it.current }.current)
assertTrue(items[0].current)
assertEquals(1234568, semesters[0].semesterId)
assertEquals(1234568, semesters.single { it.current }.semesterId)
assertEquals(1234567, semesters[1].semesterId)
assertTrue(semesters.single { it.current }.current)
assertTrue(semesters[0].current)
}
}

View file

@ -1,17 +1,18 @@
package io.github.wulkanowy.sdk.scrapper.school
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class TeachersTest : BaseLocalTest() {
private val snp by lazy {
getSnpRepo(TeachersTest::class.java, "Szkola.html").getTeachers().blockingGet()
runBlocking { getSnpRepo(TeachersTest::class.java, "Szkola.html").getTeachers() }
}
private val student by lazy {
getStudentRepo(TeachersTest::class.java, "Szkola.json").getTeachers().blockingGet()
runBlocking { getStudentRepo(TeachersTest::class.java, "Szkola.json").getTeachers() }
}
@Test

View file

@ -1,22 +1,20 @@
package io.github.wulkanowy.sdk.scrapper.service
import io.github.wulkanowy.sdk.scrapper.ApiResponse
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.BaseTest
import io.github.wulkanowy.sdk.scrapper.OkHttpClientBuilderFactory
import io.github.wulkanowy.sdk.scrapper.Scrapper
import io.github.wulkanowy.sdk.scrapper.ScrapperException
import io.github.wulkanowy.sdk.scrapper.interceptor.ErrorInterceptorTest
import io.github.wulkanowy.sdk.scrapper.login.LoginTest
import io.github.wulkanowy.sdk.scrapper.notes.NotesResponse
import io.github.wulkanowy.sdk.scrapper.notes.NotesTest
import io.github.wulkanowy.sdk.scrapper.register.Student
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import java.net.URL
@ -45,12 +43,11 @@ class ServiceManagerTest : BaseTest() {
throw ScrapperException("Test")
})
val notes = manager.getSnpService().getNotes()
val observer = TestObserver<NotesResponse>()
notes.subscribe(observer)
observer.assertTerminated()
observer.assertNotComplete()
observer.assertError(ScrapperException::class.java)
try {
runBlocking { manager.getSnpService().getNotes() }
} catch (e: Throwable) {
assertTrue(e is ScrapperException)
}
}
@Test
@ -69,12 +66,11 @@ class ServiceManagerTest : BaseTest() {
throw ScrapperException("Test")
}, false)
val notes = manager.getStudentService().getNotes()
val observer = TestObserver<ApiResponse<NotesResponse>>()
notes.subscribe(observer)
observer.assertTerminated()
observer.assertNotComplete()
observer.assertError(ScrapperException::class.java)
try {
runBlocking { manager.getStudentService().getNotes() }
} catch (e: Throwable) {
assertTrue(e is ScrapperException)
}
}
@Test
@ -98,11 +94,11 @@ class ServiceManagerTest : BaseTest() {
symbol = ""
}
val pupils = api.getStudents()
val observer = TestObserver<List<Student>>()
pupils.subscribe(observer)
observer.assertTerminated()
observer.assertError(ScrapperException::class.java)
try {
runBlocking { api.getStudents() }
} catch (e: Throwable) {
assertTrue(e is ScrapperException)
}
server.takeRequest()
// /Default/Account/LogOn < default symbol set

View file

@ -1,13 +1,14 @@
package io.github.wulkanowy.sdk.scrapper.student
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class StudentInfoTest : BaseLocalTest() {
private val info by lazy {
getSnpRepo(StudentInfoTest::class.java, "UczenDanePodstawowe.html").getStudentInfo().blockingGet()
runBlocking { getSnpRepo(StudentInfoTest::class.java, "UczenDanePodstawowe.html").getStudentInfo() }
}
@Test

View file

@ -4,8 +4,9 @@ import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
import io.github.wulkanowy.sdk.scrapper.register.RegisterTest
import io.reactivex.observers.TestObserver
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
@ -20,11 +21,13 @@ class CompletedLessonsTest : BaseLocalTest() {
// }
private val student by lazy {
getStudentRepo(CompletedLessonsTest::class.java, "Zrealizowane.json").getCompletedLessons(
getLocalDate(2018, 9, 17),
getLocalDate(2018, 9, 18),
-1
).blockingGet()
runBlocking {
getStudentRepo(CompletedLessonsTest::class.java, "Zrealizowane.json").getCompletedLessons(
getLocalDate(2018, 9, 17),
getLocalDate(2018, 9, 18),
-1
)
}
}
@Before
@ -41,28 +44,34 @@ class CompletedLessonsTest : BaseLocalTest() {
@Test
fun getRealized_disabled() {
val lessons = getStudentRepo(CompletedLessonsTest::class.java, "Zrealizowane-disabled.json").getCompletedLessons(
getLocalDate(2018, 9, 17),
getLocalDate(2018, 9, 18),
-1
)
val lessonsObserver = TestObserver<List<CompletedLesson>>()
lessons.subscribe(lessonsObserver)
lessonsObserver.assertError(FeatureDisabledException::class.java)
lessonsObserver.assertErrorMessage("Widok lekcji zrealizowanych został wyłączony przez Administratora szkoły.")
try {
runBlocking {
getStudentRepo(CompletedLessonsTest::class.java, "Zrealizowane-disabled.json").getCompletedLessons(
getLocalDate(2018, 9, 17),
getLocalDate(2018, 9, 18),
-1
)
}
} catch (e: Throwable) {
assertTrue(e is FeatureDisabledException)
assertEquals("Widok lekcji zrealizowanych został wyłączony przez Administratora szkoły.", e.message)
}
}
@Test
fun getRealized_errored() {
val lessons = getStudentRepo(CompletedLessonsTest::class.java, "Zrealizowane-errored.json").getCompletedLessons(
getLocalDate(2018, 9, 17),
getLocalDate(2018, 9, 18),
-1
)
val lessonsObserver = TestObserver<List<CompletedLesson>>()
lessons.subscribe(lessonsObserver)
lessonsObserver.assertError(VulcanException::class.java)
lessonsObserver.assertErrorMessage("DB_ERROR")
try {
runBlocking {
getStudentRepo(CompletedLessonsTest::class.java, "Zrealizowane-errored.json").getCompletedLessons(
getLocalDate(2018, 9, 17),
getLocalDate(2018, 9, 18),
-1
)
}
} catch (e: Throwable) {
assertTrue(e is VulcanException)
assertEquals("DB_ERROR", e.message)
}
}
@Test

View file

@ -1,6 +1,7 @@
package io.github.wulkanowy.sdk.scrapper.timetable
import io.github.wulkanowy.sdk.scrapper.BaseLocalTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
@ -8,15 +9,15 @@ import org.junit.Test
class TimetableTest : BaseLocalTest() {
private val snp by lazy {
getSnpRepo(TimetableTest::class.java, "PlanLekcji.html").getTimetable(getLocalDate(2018, 9, 24)).blockingGet()
runBlocking { getSnpRepo(TimetableTest::class.java, "PlanLekcji.html").getTimetable(getLocalDate(2018, 9, 24)) }
}
private val student by lazy {
getStudentRepo(TimetableTest::class.java, "PlanLekcji.json").getTimetable(getLocalDate(2018, 9, 24)).blockingGet()
runBlocking { getStudentRepo(TimetableTest::class.java, "PlanLekcji.json").getTimetable(getLocalDate(2018, 9, 24)) }
}
private val studentBefore1911 by lazy {
getStudentRepo(TimetableTest::class.java, "PlanLekcji-before-19.11.json").getTimetable(getLocalDate(2018, 9, 24)).blockingGet()
runBlocking { getStudentRepo(TimetableTest::class.java, "PlanLekcji-before-19.11.json").getTimetable(getLocalDate(2018, 9, 24)) }
}
@Test

View file

@ -10,6 +10,7 @@ import io.reactivex.Completable
import io.reactivex.Maybe
import io.reactivex.Observable
import io.reactivex.Single
import kotlinx.coroutines.rx2.rxSingle
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import org.threeten.bp.LocalDate
@ -173,10 +174,10 @@ class Sdk {
}
}
fun getPasswordResetCaptchaCode(registerBaseUrl: String, symbol: String) = scrapper.getPasswordResetCaptcha(registerBaseUrl, symbol)
fun getPasswordResetCaptchaCode(registerBaseUrl: String, symbol: String) = rxSingle { scrapper.getPasswordResetCaptcha(registerBaseUrl, symbol) }
fun sendPasswordResetRequest(registerBaseUrl: String, symbol: String, email: String, captchaCode: String): Single<String> {
return scrapper.sendPasswordResetRequest(registerBaseUrl, symbol, email, captchaCode)
return rxSingle { scrapper.sendPasswordResetRequest(registerBaseUrl, symbol, email, captchaCode) }
}
fun getStudentsFromMobileApi(token: String, pin: String, symbol: String, firebaseToken: String, apiKey: String = ""): Single<List<Student>> {
@ -191,7 +192,7 @@ class Sdk {
it.email = email
it.password = password
it.symbol = symbol
it.getStudents().compose(ScrapperExceptionTransformer()).map { students -> students.mapStudents() }
rxSingle { it.getStudents() }.compose(ScrapperExceptionTransformer()).map { students -> students.mapStudents() }
}
}
@ -209,7 +210,7 @@ class Sdk {
it.classId = scrapperStudent.classId
it.loginType = Scrapper.LoginType.valueOf(scrapperStudent.loginType.name)
}
scrapper.getToken().compose(ScrapperExceptionTransformer())
rxSingle { scrapper.getToken() }.compose(ScrapperExceptionTransformer())
.flatMap { getStudentsFromMobileApi(it.token, it.pin, it.symbol, firebaseToken, apiKey) }
.map { apiStudents ->
apiStudents.map { student ->
@ -225,14 +226,14 @@ class Sdk {
fun getSemesters(now: LocalDate = LocalDate.now()): Single<List<Semester>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSemesters().compose(ScrapperExceptionTransformer()).map { it.mapSemesters() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getSemesters() }.compose(ScrapperExceptionTransformer()).map { it.mapSemesters() }
Mode.API -> mobile.getStudents().map { it.mapSemesters(studentId, now) }
}
}
fun getAttendance(startDate: LocalDate, endDate: LocalDate, semesterId: Int): Single<List<Attendance>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getAttendance(startDate, endDate).compose(ScrapperExceptionTransformer()).map { it.mapAttendance() }
Mode.SCRAPPER -> rxSingle { scrapper.getAttendance(startDate, endDate) }.compose(ScrapperExceptionTransformer()).map { it.mapAttendance() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getAttendance(startDate, endDate, semesterId).map { it.mapAttendance(dict) }
}
@ -241,28 +242,28 @@ class Sdk {
fun getAttendanceSummary(subjectId: Int? = -1): Single<List<AttendanceSummary>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getAttendanceSummary(subjectId).compose(ScrapperExceptionTransformer()).map { it.mapAttendanceSummary() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getAttendanceSummary(subjectId) }.compose(ScrapperExceptionTransformer()).map { it.mapAttendanceSummary() }
Mode.API -> throw FeatureNotAvailableException("Attendance summary is not available in API mode")
}
}
fun excuseForAbsence(absents: List<Absent>, content: String? = null): Single<Boolean> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.excuseForAbsence(absents.mapToScrapperAbsent(), content).compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.excuseForAbsence(absents.mapToScrapperAbsent(), content) }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Absence excusing is not available in API mode")
}
}
fun getSubjects(): Single<List<Subject>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSubjects().compose(ScrapperExceptionTransformer()).map { it.mapSubjects() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getSubjects() }.compose(ScrapperExceptionTransformer()).map { it.mapSubjects() }
Mode.API -> mobile.getDictionaries().map { it.subjects }.map { it.mapSubjects() }
}
}
fun getExams(start: LocalDate, end: LocalDate, semesterId: Int): Single<List<Exam>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getExams(start, end).compose(ScrapperExceptionTransformer()).map { it.mapExams() }
Mode.SCRAPPER -> rxSingle { scrapper.getExams(start, end) }.compose(ScrapperExceptionTransformer()).map { it.mapExams() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getExams(start, end, semesterId).map { it.mapExams(dict) }
}
@ -271,7 +272,7 @@ class Sdk {
fun getGrades(semesterId: Int): Single<Pair<List<Grade>, List<GradeSummary>>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getGrades(semesterId).compose(ScrapperExceptionTransformer()).map { grades -> grades.mapGrades() }
Mode.SCRAPPER -> rxSingle { scrapper.getGrades(semesterId) }.compose(ScrapperExceptionTransformer()).map { grades -> grades.mapGrades() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getGrades(semesterId).map { grades -> grades.mapGrades(dict) }
}
@ -280,7 +281,7 @@ class Sdk {
fun getGradesDetails(semesterId: Int): Single<List<Grade>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getGradesDetails(semesterId).compose(ScrapperExceptionTransformer()).map { grades -> grades.mapGradesDetails() }
Mode.SCRAPPER -> rxSingle { scrapper.getGradesDetails(semesterId) }.compose(ScrapperExceptionTransformer()).map { grades -> grades.mapGradesDetails() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getGradesDetails(semesterId).map { it.mapGradesDetails(dict) }
}
@ -289,7 +290,7 @@ class Sdk {
fun getGradesSummary(semesterId: Int): Single<List<GradeSummary>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getGradesSummary(semesterId).compose(ScrapperExceptionTransformer()).map { it.mapGradesSummary() }
Mode.SCRAPPER -> rxSingle { scrapper.getGradesSummary(semesterId) }.compose(ScrapperExceptionTransformer()).map { it.mapGradesSummary() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getGradesSummary(semesterId).map { it.mapGradesSummary(dict) }
}
@ -298,28 +299,28 @@ class Sdk {
fun getGradesAnnualStatistics(semesterId: Int): Single<List<GradeStatistics>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGradesAnnualStatistics(semesterId).compose(ScrapperExceptionTransformer()).map { it.mapGradeStatistics() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getGradesAnnualStatistics(semesterId) }.compose(ScrapperExceptionTransformer()).map { it.mapGradeStatistics() }
Mode.API -> throw FeatureNotAvailableException("Class grades annual statistics is not available in API mode")
}
}
fun getGradesPartialStatistics(semesterId: Int): Single<List<GradeStatistics>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGradesPartialStatistics(semesterId).compose(ScrapperExceptionTransformer()).map { it.mapGradeStatistics() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getGradesPartialStatistics(semesterId) }.compose(ScrapperExceptionTransformer()).map { it.mapGradeStatistics() }
Mode.API -> throw FeatureNotAvailableException("Class grades partial statistics is not available in API mode")
}
}
fun getGradesPointsStatistics(semesterId: Int): Single<List<GradePointsStatistics>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGradesPointsStatistics(semesterId).compose(ScrapperExceptionTransformer()).map { it.mapGradePointsStatistics() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getGradesPointsStatistics(semesterId) }.compose(ScrapperExceptionTransformer()).map { it.mapGradePointsStatistics() }
Mode.API -> throw FeatureNotAvailableException("Class grades points statistics is not available in API mode")
}
}
fun getHomework(start: LocalDate, end: LocalDate, semesterId: Int = 0): Single<List<Homework>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getHomework(start, end).compose(ScrapperExceptionTransformer()).map { it.mapHomework() }
Mode.SCRAPPER -> rxSingle { scrapper.getHomework(start, end) }.compose(ScrapperExceptionTransformer()).map { it.mapHomework() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getHomework(start, end, semesterId).map { it.mapHomework(dict) }
}
@ -328,7 +329,7 @@ class Sdk {
fun getNotes(semesterId: Int): Single<List<Note>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getNotes().compose(ScrapperExceptionTransformer()).map { it.mapNotes() }
Mode.SCRAPPER -> rxSingle { scrapper.getNotes() }.compose(ScrapperExceptionTransformer()).map { it.mapNotes() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getNotes(semesterId).map { it.mapNotes(dict) }
}
@ -337,28 +338,28 @@ class Sdk {
fun getRegisteredDevices(): Single<List<Device>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getRegisteredDevices().compose(ScrapperExceptionTransformer()).map { it.mapDevices() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getRegisteredDevices() }.compose(ScrapperExceptionTransformer()).map { it.mapDevices() }
Mode.API -> throw FeatureNotAvailableException("Devices management is not available in API mode")
}
}
fun getToken(): Single<Token> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getToken().compose(ScrapperExceptionTransformer()).map { it.mapToken() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getToken() }.compose(ScrapperExceptionTransformer()).map { it.mapToken() }
Mode.API -> throw FeatureNotAvailableException("Devices management is not available in API mode")
}
}
fun unregisterDevice(id: Int): Single<Boolean> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.unregisterDevice(id).compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.unregisterDevice(id) }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Devices management is not available in API mode")
}
}
fun getTeachers(semesterId: Int): Single<List<Teacher>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getTeachers().compose(ScrapperExceptionTransformer()).map { it.mapTeachers() }
Mode.SCRAPPER -> rxSingle { scrapper.getTeachers() }.compose(ScrapperExceptionTransformer()).map { it.mapTeachers() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getTeachers(studentId, semesterId).map { it.mapTeachers(dict) }
}
@ -367,28 +368,28 @@ class Sdk {
fun getSchool(): Single<School> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSchool().compose(ScrapperExceptionTransformer()).map { it.mapSchool() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getSchool() }.compose(ScrapperExceptionTransformer()).map { it.mapSchool() }
Mode.API -> throw FeatureNotAvailableException("School info is not available in API mode")
}
}
fun getStudentInfo(): Single<StudentInfo> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentInfo().compose(ScrapperExceptionTransformer()).map { it.mapStudent() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getStudentInfo() }.compose(ScrapperExceptionTransformer()).map { it.mapStudent() }
Mode.API -> throw FeatureNotAvailableException("Student info is not available in API mode")
}
}
fun getReportingUnits(): Single<List<ReportingUnit>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getReportingUnits().compose(ScrapperExceptionTransformer()).map { it.mapReportingUnits() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getReportingUnits() }.compose(ScrapperExceptionTransformer()).map { it.mapReportingUnits() }
Mode.API -> mobile.getStudents().map { it.mapReportingUnits(studentId) }
}
}
fun getRecipients(unitId: Int, role: Int = 2): Single<List<Recipient>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getRecipients(unitId, role).compose(ScrapperExceptionTransformer()).map { it.mapRecipients() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getRecipients(unitId, role) }.compose(ScrapperExceptionTransformer()).map { it.mapRecipients() }
Mode.API -> mobile.getDictionaries().map { it.teachers }.map { it.mapRecipients(unitId) }
}
}
@ -403,7 +404,7 @@ class Sdk {
fun getReceivedMessages(start: LocalDateTime, end: LocalDateTime): Single<List<Message>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getReceivedMessages().compose(ScrapperExceptionTransformer()).map { it.mapMessages() } // TODO
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getReceivedMessages() }.compose(ScrapperExceptionTransformer()).map { it.mapMessages() } // TODO
Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getMessages(start, end).map { it.mapMessages(dict) }
}
@ -412,7 +413,7 @@ class Sdk {
fun getSentMessages(start: LocalDateTime, end: LocalDateTime): Single<List<Message>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSentMessages().compose(ScrapperExceptionTransformer()).map { it.mapMessages() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getSentMessages() }.compose(ScrapperExceptionTransformer()).map { it.mapMessages() }
Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getMessagesSent(start, end).map { it.mapMessages(dict) }
}
@ -421,7 +422,7 @@ class Sdk {
fun getDeletedMessages(start: LocalDateTime, end: LocalDateTime): Single<List<Message>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getDeletedMessages().compose(ScrapperExceptionTransformer()).map { it.mapMessages() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getDeletedMessages() }.compose(ScrapperExceptionTransformer()).map { it.mapMessages() }
Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getMessagesDeleted(start, end).map { it.mapMessages(dict) }
}
@ -430,14 +431,14 @@ class Sdk {
fun getMessageRecipients(messageId: Int, senderId: Int): Single<List<Recipient>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getMessageRecipients(messageId, senderId).compose(ScrapperExceptionTransformer()).map { it.mapRecipients() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getMessageRecipients(messageId, senderId) }.compose(ScrapperExceptionTransformer()).map { it.mapRecipients() }
Mode.API -> TODO()
}
}
fun getMessageDetails(messageId: Int, folderId: Int, read: Boolean = false, id: Int? = null): Single<MessageDetails> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getMessageDetails(messageId, folderId, read, id).compose(ScrapperExceptionTransformer()).map { it.mapScrapperMessage() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getMessageDetails(messageId, folderId, read, id) }.compose(ScrapperExceptionTransformer()).map { it.mapScrapperMessage() }
Mode.API -> mobile.changeMessageStatus(messageId, when (folderId) {
1 -> "Odebrane"
2 -> "Wysłane"
@ -448,7 +449,7 @@ class Sdk {
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.sendMessage(subject, content, recipients.mapFromRecipientsToScraper())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.sendMessage(subject, content, recipients.mapFromRecipientsToScraper()) }
.compose(ScrapperExceptionTransformer())
.map { it.mapSentMessage() }
Mode.API -> mobile.sendMessage(subject, content, recipients.mapFromRecipientsToMobile()).map { it.mapSentMessage(loginId) }
@ -457,7 +458,7 @@ class Sdk {
fun deleteMessages(messages: List<Pair<Int, Int>>): Single<Boolean> {
return when (mode) {
Mode.SCRAPPER -> scrapper.deleteMessages(messages).compose(ScrapperExceptionTransformer())
Mode.SCRAPPER -> rxSingle { scrapper.deleteMessages(messages) }.compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.API -> Completable.mergeDelayError(messages.map { (messageId, folderId) ->
mobile.changeMessageStatus(messageId, when (folderId) {
1 -> "Odebrane"
@ -470,7 +471,7 @@ class Sdk {
fun getTimetable(start: LocalDate, end: LocalDate): Single<List<Timetable>> {
return when (mode) {
Mode.SCRAPPER -> scrapper.getTimetable(start, end).compose(ScrapperExceptionTransformer()).map { it.mapTimetable() }
Mode.SCRAPPER -> rxSingle { scrapper.getTimetable(start, end) }.compose(ScrapperExceptionTransformer()).map { it.mapTimetable() }
Mode.HYBRID, Mode.API -> mobile.getDictionaries().flatMap { dict ->
mobile.getTimetable(start, end, 0).map { it.mapTimetable(dict) }
}
@ -479,7 +480,7 @@ class Sdk {
fun getCompletedLessons(start: LocalDate, end: LocalDate? = null, subjectId: Int = -1): Single<List<CompletedLesson>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getCompletedLessons(start, end, subjectId).compose(ScrapperExceptionTransformer()).map { it.mapCompletedLessons() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getCompletedLessons(start, end, subjectId) }.compose(ScrapperExceptionTransformer()).map { it.mapCompletedLessons() }
Mode.API -> throw FeatureNotAvailableException("Completed lessons are not available in API mode")
}
}
@ -508,70 +509,70 @@ class Sdk {
fun getSelfGovernments(): Single<List<GovernmentUnit>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSelfGovernments().compose(ScrapperExceptionTransformer()).map { it.mapToUnits() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getSelfGovernments() }.compose(ScrapperExceptionTransformer()).map { it.mapToUnits() }
Mode.API -> throw FeatureNotAvailableException("Self governments is not available in API mode")
}
}
fun getStudentThreats(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentThreats().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getStudentThreats() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Student threats are not available in API mode")
}
}
fun getStudentsTrips(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentsTrips().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getStudentsTrips() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Students trips is not available in API mode")
}
}
fun getLastGrades(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastGrades().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getLastGrades() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Last grades is not available in API mode")
}
}
fun getFreeDays(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getFreeDays().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getFreeDays() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Free days is not available in API mode")
}
}
fun getKidsLuckyNumbers(): Single<List<LuckyNumber>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getKidsLuckyNumbers().compose(ScrapperExceptionTransformer()).map { it.mapLuckyNumbers() }
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getKidsLuckyNumbers() }.compose(ScrapperExceptionTransformer()).map { it.mapLuckyNumbers() }
Mode.API -> throw FeatureNotAvailableException("Kids Lucky number is not available in API mode")
}
}
fun getKidsTimetable(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getKidsLessonPlan().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getKidsLessonPlan() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Kids timetable is not available in API mode")
}
}
fun getLastHomework(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastHomework().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getLastHomework() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Last homework is not available in API mode")
}
}
fun getLastExams(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastTests().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getLastTests() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Last exams is not available in API mode")
}
}
fun getLastStudentLessons(): Single<List<String>> {
return when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastStudentLessons().compose(ScrapperExceptionTransformer())
Mode.HYBRID, Mode.SCRAPPER -> rxSingle { scrapper.getLastStudentLessons() }.compose(ScrapperExceptionTransformer())
Mode.API -> throw FeatureNotAvailableException("Last student lesson is not available in API mode")
}
}