Remove deprecated sdk-mobile module

This commit is contained in:
Mikołaj Pich 2023-04-08 01:09:29 +02:00
parent d9638eeba7
commit 76e6a0e5bd
103 changed files with 15 additions and 4593 deletions

View file

@ -158,7 +158,6 @@ subprojects {
dependencies {
api project(":sdk")
api project(":sdk-mobile")
api project(":sdk-scrapper")
api "com.squareup.okhttp3:okhttp"

View file

@ -1,20 +0,0 @@
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm'
id "com.google.devtools.ksp"
}
dependencies {
implementation "com.github.wulkanowy:uonet-request-signer:c0b8b8ac54"
implementation "com.brsanthu:migbase64:2.2"
implementation libs.retrofit.core
implementation libs.retrofit.moshi
implementation libs.retrofit.scalars
def moshi = "1.14.0"
implementation "com.squareup.moshi:moshi:$moshi"
implementation "com.squareup.moshi:moshi-adapters:$moshi"
ksp "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
}

View file

@ -1,31 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import java.time.LocalDateTime.now
import java.time.ZoneOffset
import java.util.UUID
@Suppress("unused")
@JsonClass(generateAdapter = true)
open class ApiRequest(
@Json(name = "RemoteMobileTimeKey")
val remoteMobileTimeKey: Long = now().toEpochSecond(ZoneOffset.UTC),
@Json(name = "TimeKey")
val timeKey: Long = now().toEpochSecond(ZoneOffset.UTC) - 1,
@Json(name = "RequestId")
val requestId: String = UUID.randomUUID().toString(),
@Json(name = "RemoteMobileAppVersion")
val remoteMobileAppVersion: String = MOBILE_APP_VERSION,
@Json(name = "RemoteMobileAppName")
val remoteMobileAppName: String = "VULCAN-Android-ModulUcznia",
) {
companion object {
const val MOBILE_APP_VERSION = "20.1.1.447"
}
}

View file

@ -1,29 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class ApiResponse<out T>(
@Json(name = "Status")
val status: String,
@Json(name = "TimeKey")
val timeKey: String,
@Json(name = "TimeValue")
val timeValue: String,
@Json(name = "RequestId")
val requestId: String,
@Json(name = "DayOfWeek")
val dayOfWeek: String,
@Json(name = "AppVersion")
val appVersion: String,
@Json(name = "Data")
val data: T?,
)

View file

@ -1,189 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import com.migcomponents.migbase64.Base64
import io.github.wulkanowy.sdk.mobile.attendance.Attendance
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException
import io.github.wulkanowy.sdk.mobile.exception.NoStudentsException
import io.github.wulkanowy.sdk.mobile.exception.TokenDeadException
import io.github.wulkanowy.sdk.mobile.exception.TokenNotFoundException
import io.github.wulkanowy.sdk.mobile.exception.UnknownTokenException
import io.github.wulkanowy.sdk.mobile.exception.UnsupportedTokenException
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.messages.Message
import io.github.wulkanowy.sdk.mobile.messages.Recipient
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.repository.RepositoryManager
import io.github.wulkanowy.sdk.mobile.school.Teacher
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.signer.getPrivateKeyFromCert
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import java.nio.charset.Charset
import java.time.LocalDate
import java.time.LocalDateTime
class Mobile {
var classId = 0
var studentId = 0
var loginId = 0
private val resettableManager = resettableManager()
var logLevel = HttpLoggingInterceptor.Level.BASIC
set(value) {
field = value
resettableManager.reset()
}
var privateKey = ""
set(value) {
field = value
resettableManager.reset()
}
var certKey = ""
set(value) {
field = value
resettableManager.reset()
}
var baseUrl = ""
set(value) {
field = value
resettableManager.reset()
}
var schoolSymbol = ""
set(value) {
field = value
resettableManager.reset()
}
private val serviceManager by resettableLazy(resettableManager) { RepositoryManager(logLevel, privateKey, certKey, interceptors, baseUrl, schoolSymbol) }
private val routes by resettableLazy(resettableManager) { serviceManager.getRoutesRepository() }
private val mobile by resettableLazy(resettableManager) { serviceManager.getMobileRepository() }
private val interceptors: MutableList<Pair<Interceptor, Boolean>> = mutableListOf()
fun setInterceptor(interceptor: Interceptor, network: Boolean = false) {
interceptors.add(interceptor to network)
}
private lateinit var dictionaries: Dictionaries
suspend fun getDictionaries(): Dictionaries {
if (::dictionaries.isInitialized) return dictionaries
return mobile.getDictionaries(0, 0, classId)
.apply { dictionaries = this }
}
suspend fun getCertificate(token: String, pin: String, symbol: String, deviceName: String, androidVer: String, firebaseToken: String): CertificateResponse {
val baseUrl = routes.getRouteByToken(token)
return serviceManager.getRegisterRepository(baseUrl, symbol).getCertificate(token, pin, deviceName, androidVer, firebaseToken)
}
suspend fun getStudents(certRes: CertificateResponse, apiKey: String = ""): List<Student> {
if (certRes.isError) {
when {
certRes.message == "TokenDead" -> throw TokenDeadException(certRes.message)
certRes.message == "TokenNotFound" -> throw TokenNotFoundException(certRes.message)
certRes.message?.startsWith("Podany numer PIN jest niepoprawny") == true -> throw InvalidPinException(certRes.message)
certRes.message?.startsWith("Trzykrotnie wpisano niepoprawny kod PIN") == true -> throw InvalidPinException(certRes.message)
certRes.message == "NoPupils" -> throw NoStudentsException(certRes.message)
certRes.message == "OnlyKindergarten" -> throw UnsupportedTokenException(certRes.message)
else -> throw UnknownTokenException(certRes.message.orEmpty())
}
}
val cert = certRes.tokenCert!!
val privateKeyValue = apiKey.ifEmpty {
Base64.decode(if (cert.baseUrl.contains("fakelog")) "KDAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OUFCKQ==" else "KENFNzVFQTU5OEM3NzQzQUQ5QjBCNzMyOERFRDg1QjA2KQ==")
.toString(Charset.defaultCharset())
.removeSurrounding("(", ")")
}
certKey = cert.certificateKey
baseUrl = cert.baseUrl.removeSuffix("/")
privateKey = getPrivateKeyFromCert(privateKeyValue, cert.certificatePfx)
return serviceManager.getRegisterRepository(cert.baseUrl).getStudents().map {
it.copy().apply {
certificateKey = this@Mobile.certKey
privateKey = this@Mobile.privateKey
mobileBaseUrl = this@Mobile.baseUrl
}
}
}
suspend fun getStudents(): List<Student> {
return serviceManager.getRegisterRepository(baseUrl).getStudents()
}
suspend fun getAttendance(start: LocalDate, end: LocalDate, classificationPeriodId: Int): List<Attendance> {
return mobile.getAttendance(start, end, classId, classificationPeriodId, studentId)
}
suspend fun getExams(start: LocalDate, end: LocalDate, classificationPeriodId: Int): List<Exam> {
return mobile.getExams(start, end, classId, classificationPeriodId, studentId)
}
suspend fun getGrades(classificationPeriodId: Int): Pair<List<Grade>, GradesSummaryResponse> {
return getGradesDetails(classificationPeriodId) to getGradesSummary(classificationPeriodId)
}
suspend fun getGradesDetails(classificationPeriodId: Int): List<Grade> {
return mobile.getGradesDetails(classId, classificationPeriodId, studentId)
}
suspend fun getGradesSummary(classificationPeriodId: Int): GradesSummaryResponse {
return mobile.getGradesSummary(classId, classificationPeriodId, studentId)
}
suspend fun getHomework(start: LocalDate, end: LocalDate, classificationPeriodId: Int): List<Homework> {
return mobile.getHomework(start, end, classId, classificationPeriodId, studentId)
}
suspend fun getNotes(classificationPeriodId: Int): List<Note> {
return mobile.getNotes(classificationPeriodId, studentId)
}
suspend fun getTeachers(studentId: Int, semesterId: Int): List<Teacher> {
return mobile.getTeachers(studentId, semesterId)
}
suspend fun getMessages(start: LocalDateTime, end: LocalDateTime): List<Message> {
return mobile.getMessages(start, end, loginId, studentId)
}
suspend fun getMessagesSent(start: LocalDateTime, end: LocalDateTime): List<Message> {
return mobile.getMessagesSent(start, end, loginId, studentId)
}
suspend fun getMessagesDeleted(start: LocalDateTime, end: LocalDateTime): List<Message> {
return mobile.getMessagesDeleted(start, end, loginId, studentId)
}
suspend fun changeMessageStatus(messageId: String, folder: String, status: String): String {
return mobile.changeMessageStatus(messageId, folder, status, loginId, studentId)
}
suspend fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Message {
val sender = getStudents().singleOrNull { it.loginId == loginId }?.name.orEmpty()
return mobile.sendMessage(sender, subject, content, recipients, loginId, studentId)
}
suspend fun getTimetable(start: LocalDate, end: LocalDate, classificationPeriodId: Int): List<Lesson> {
return mobile.getTimetable(start, end, classId, classificationPeriodId, studentId)
}
}

View file

@ -1,55 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import java.util.LinkedList
import kotlin.reflect.KProperty
/**
* see https://stackoverflow.com/a/35757638/6695449
*/
class ResettableLazyManager {
// we synchronize to make sure the timing of a reset() call and new inits do not collide
val managedDelegates = LinkedList<Resettable>()
fun register(managed: Resettable) {
synchronized(managedDelegates) {
managedDelegates.add(managed)
}
}
fun reset() {
synchronized(managedDelegates) {
managedDelegates.forEach { it.reset() }
managedDelegates.clear()
}
}
}
interface Resettable {
fun reset()
}
class ResettableLazy<PROPTYPE>(val manager: ResettableLazyManager, val init: () -> PROPTYPE) : Resettable {
@Volatile
var lazyHolder = makeInitBlock()
operator fun getValue(thisRef: Any?, property: KProperty<*>): PROPTYPE {
return lazyHolder.value
}
override fun reset() {
lazyHolder = makeInitBlock()
}
fun makeInitBlock(): Lazy<PROPTYPE> {
return lazy {
manager.register(this)
init()
}
}
}
fun <PROPTYPE> resettableLazy(manager: ResettableLazyManager, init: () -> PROPTYPE): ResettableLazy<PROPTYPE> {
return ResettableLazy(manager, init)
}
fun resettableManager(): ResettableLazyManager = ResettableLazyManager()

View file

@ -1,9 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter.ofPattern
fun LocalDate.toFormat(): String = format(ofPattern("yyyy-MM-dd"))
fun LocalDateTime.toFormat(): String = format(ofPattern("yyyy-MM-dd"))

View file

@ -1,29 +0,0 @@
package io.github.wulkanowy.sdk.mobile.attendance
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Attendance(
@Json(name = "IdKategoria")
val categoryId: Int,
@Json(name = "Numer")
val number: Int,
@Json(name = "IdPoraLekcji")
val lessonTimeId: Int,
@Json(name = "Dzien")
val date: Long,
@Json(name = "DzienTekst")
val dateText: String,
@Json(name = "IdPrzedmiot")
val subjectId: Int,
@Json(name = "PrzedmiotNazwa")
val subjectName: String,
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.attendance
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class AttendanceRequest(
@Json(name = "DataPoczatkowa")
val startDate: String,
@Json(name = "DataKoncowa")
val endDate: String,
@Json(name = "IdOddzial")
val classId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,23 +0,0 @@
package io.github.wulkanowy.sdk.mobile.attendance
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class AttendanceResponse(
@Json(name = "DataPoczatkowa")
val dateStart: Long,
@Json(name = "DataPoczatkowaTekst")
val dateStartText: String,
@Json(name = "DataKoncowa")
val dateEnd: Long,
@Json(name = "DataKoncowaTekst")
val dateEndText: String,
@Json(name = "Frekwencje")
val items: List<Attendance>,
)

View file

@ -1,35 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class AttendanceCategory(
@Json(name = "Id")
val id: Int,
@Json(name = "Nazwa")
val name: String,
@Json(name = "Pozycja")
val position: Int,
@Json(name = "Obecnosc")
val presence: Boolean,
@Json(name = "Nieobecnosc")
val absence: Boolean,
@Json(name = "Zwolnienie")
val exemption: Boolean,
@Json(name = "Spoznienie")
val lateness: Boolean,
@Json(name = "Usprawiedliwione")
val excused: Boolean,
@Json(name = "Usuniete")
val deleted: Boolean,
)

View file

@ -1,26 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class AttendanceType(
@Json(name = "Id")
val id: Int,
@Json(name = "Symbol")
val symbol: String,
@Json(name = "Nazwa")
val name: String,
@Json(name = "Aktywny")
val active: Boolean,
@Json(name = "WpisDomyslny")
val defaultEntry: Boolean,
@Json(name = "IdKategoriaFrek")
val categoryId: Int,
)

View file

@ -1,35 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Dictionaries(
@Json(name = "TimeKey")
val timeKey: Long,
@Json(name = "Nauczyciele")
val teachers: List<Teacher>,
@Json(name = "Pracownicy")
val employees: List<Employee>,
@Json(name = "Przedmioty")
val subjects: List<Subject>,
@Json(name = "PoryLekcji")
val lessonTimes: List<LessonTime>,
@Json(name = "KategorieOcen")
val gradeCategories: List<GradeCategory>,
@Json(name = "KategorieUwag")
val noteCategories: List<NoteCategory>,
@Json(name = "KategorieFrekwencji")
val attendanceCategories: List<AttendanceCategory>,
@Json(name = "TypyFrekwencji")
val attendanceTypes: List<AttendanceType>,
)

View file

@ -1,19 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class DictionariesRequest(
@Json(name = "IdUczen")
val userId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdOddzial")
val classId: Int,
) : ApiRequest()

View file

@ -1,29 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Employee(
@Json(name = "Id")
val id: Int,
@Json(name = "Imie")
val name: String,
@Json(name = "Nazwisko")
val surname: String,
@Json(name = "Kod")
val code: String,
@Json(name = "Aktywny")
val active: Boolean,
@Json(name = "Nauczyciel")
val teacher: Boolean,
@Json(name = "LoginId")
val loginId: Int,
)

View file

@ -1,17 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class GradeCategory(
@Json(name = "Id")
val id: Int,
@Json(name = "Kod")
val code: String,
@Json(name = "Nazwa")
val name: String,
)

View file

@ -1,26 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class LessonTime(
@Json(name = "Id")
val id: Int,
@Json(name = "Numer")
val number: Int,
@Json(name = "Poczatek")
val start: Long,
@Json(name = "PoczatekTekst")
val startText: String,
@Json(name = "Koniec")
val end: Long,
@Json(name = "KoniecTekst")
val endText: String,
)

View file

@ -1,17 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class NoteCategory(
@Json(name = "Id")
val id: Int,
@Json(name = "Nazwa")
val name: String,
@Json(name = "Aktywny")
val isActive: Boolean,
)

View file

@ -1,23 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Subject(
@Json(name = "Id")
val id: Int,
@Json(name = "Nazwa")
val name: String,
@Json(name = "Kod")
val code: String,
@Json(name = "Aktywny")
val active: Boolean,
@Json(name = "Pozycja")
val position: Int,
)

View file

@ -1,29 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Teacher(
@Json(name = "Id")
val id: Int,
@Json(name = "Imie")
val name: String,
@Json(name = "Nazwisko")
val surname: String,
@Json(name = "Kod")
val code: String,
@Json(name = "Aktywny")
val active: Boolean,
@Json(name = "Nauczyciel")
val teacher: Boolean,
@Json(name = "LoginId")
val loginId: Int,
)

View file

@ -1,41 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exams
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Exam(
@Json(name = "Id")
val id: Int,
@Json(name = "IdPrzedmiot")
val subjectId: Int,
@Json(name = "IdPracownik")
val employeeId: Int,
@Json(name = "IdOddzial")
val classId: Int?,
@Json(name = "IdPodzial")
val divideId: Int?,
@Json(name = "PodzialNazwa")
val divideName: String?,
@Json(name = "Rodzaj")
val type: Boolean, // false - quiz, true - test
@Json(name = "RodzajNumer")
val typeNumber: Int,
@Json(name = "Opis")
val description: String,
@Json(name = "Data")
val date: Long,
@Json(name = "DataTekst")
val dateText: String,
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exams
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class ExamsRequest(
@Json(name = "DataPoczatkowa")
val startDate: String,
@Json(name = "DataKoncowa")
val endDate: String,
@Json(name = "IdOddzial")
val classId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class InvalidPinException(message: String) : IOException(message)

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class InvalidSymbolException : IOException()

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
open class InvalidTokenException internal constructor(message: String) : IOException(message)

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class NoStudentsException(message: String) : IOException(message)

View file

@ -1,3 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
class TokenDeadException(message: String) : InvalidTokenException(message)

View file

@ -1,3 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
class TokenNotFoundException(message: String) : InvalidTokenException(message)

View file

@ -1,3 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
class UnknownTokenException(message: String) : InvalidTokenException(message)

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class UnsupportedTokenException(message: String) : IOException(message)

View file

@ -1,68 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Grade(
@Json(name = "Id")
val id: Int,
@Json(name = "Pozycja")
val position: Int,
@Json(name = "PrzedmiotPozycja")
val subjectPosition: Int,
@Json(name = "IdPrzedmiot")
val subjectId: Int,
@Json(name = "IdKategoria")
val categoryId: Int,
@Json(name = "Wpis")
val entry: String,
@Json(name = "Wartosc")
val value: Double,
@Json(name = "WagaModyfikatora")
val modificationWeight: Double?,
@Json(name = "WagaOceny")
val gradeWeight: Double,
@Json(name = "Licznik")
val counter: Double?,
@Json(name = "Mianownik")
val denominator: Int?,
@Json(name = "Komentarz")
val comment: String?,
@Json(name = "Waga")
val weight: String,
@Json(name = "Opis")
val description: String,
@Json(name = "DataUtworzenia")
val creationDate: Long,
@Json(name = "DataUtworzeniaTekst")
val creationDateText: String,
@Json(name = "DataModyfikacji")
val modificationDate: Long,
@Json(name = "DataModyfikacjiTekst")
val modificationDateText: String,
@Json(name = "IdPracownikD")
val employeeIdD: Int,
@Json(name = "IdPracownikM")
val employeeIdM: Int,
)

View file

@ -1,20 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class GradeSummary(
@Json(name = "IdPrzedmiot")
val subjectId: Int = 0,
@Json(name = "Wpis")
val entry: String = "",
@Json(name = "SredniaOcen")
val average: String = "0",
@Json(name = "SumaPunktow")
val pointsSum: String = "",
)

View file

@ -1,18 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class GradesRequest(
@Json(name = "IdOddzial")
val classId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,17 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class GradesSummaryResponse(
@Json(name = "OcenyPrzewidywane")
val predicted: List<GradeSummary>,
@Json(name = "OcenyKlasyfikacyjne")
val evaluative: List<GradeSummary>,
@Json(name = "SrednieOcen")
val average: List<GradeSummary>,
)

View file

@ -1,29 +0,0 @@
package io.github.wulkanowy.sdk.mobile.homework
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Homework(
@Json(name = "Id")
val id: Int,
@Json(name = "IdUczen")
val studentId: Int,
@Json(name = "Data")
val date: Long,
@Json(name = "DataTekst")
val dateText: String,
@Json(name = "IdPracownik")
val employeeId: Int,
@Json(name = "IdPrzedmiot")
val subjectId: Int,
@Json(name = "Opis")
val content: String,
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.homework
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class HomeworkRequest(
@Json(name = "DataPoczatkowa")
val startDate: String,
@Json(name = "DataKoncowa")
val endDate: String,
@Json(name = "IdOddzial")
val classId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.interceptor
import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException
class ErrorInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
val body = response.peekBody(Long.MAX_VALUE).string()
when {
body == "Bad Request" -> throw IOException(body)
body.contains("Podany symbol grupujący jest nieprawidłowy") -> throw InvalidSymbolException()
}
return response
}
}

View file

@ -1,32 +0,0 @@
package io.github.wulkanowy.sdk.mobile.interceptor
import io.github.wulkanowy.signer.signContent
import okhttp3.Interceptor
import okhttp3.Response
import okio.Buffer
import java.nio.charset.Charset
class SignInterceptor(
private val privateKey: String,
private val certKey: String,
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val original = chain.request()
val request = original.newBuilder()
request.header("User-Agent", "MobileUserAgent")
if (privateKey.isNotBlank()) {
val signature = Buffer().run {
original.body?.writeTo(this)
signContent(privateKey, readString(Charset.defaultCharset()))
}
request.header("RequestCertificateKey", certKey)
request.header("RequestSignatureValue", signature)
}
return chain.proceed(request.method(original.method, original.body).build())
}
}

View file

@ -1,56 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Message(
@Json(name = "WiadomoscId")
val messageId: Int,
@Json(name = "Nadawca")
val senderName: String?,
@Json(name = "NadawcaId")
val senderId: Int,
@Json(name = "Adresaci")
val recipients: List<Recipient>?,
@Json(name = "Tytul")
val subject: String,
@Json(name = "Tresc")
val content: String,
@Json(name = "DataWyslania")
val sentDate: String,
@Json(name = "DataWyslaniaUnixEpoch")
val sentDateTime: Long,
@Json(name = "GodzinaWyslania")
val sentHour: String,
@Json(name = "DataPrzeczytania")
val readDate: String?,
@Json(name = "DataPrzeczytaniaUnixEpoch")
val readDateTime: Long?,
@Json(name = "GodzinaPrzeczytania")
val readHour: String?,
@Json(name = "StatusWiadomosci")
val status: String,
@Json(name = "FolderWiadomosci")
val folder: String,
@Json(name = "Nieprzeczytane")
val unread: String?,
@Json(name = "Przeczytane")
val read: String?,
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class MessageStatusChangeRequest(
@Json(name = "WiadomoscId")
val messageId: Int,
@Json(name = "FolderWiadomosci")
val folder: String,
@Json(name = "Status")
val status: String,
@Json(name = "LoginId")
val loginId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class MessagesRequest(
@Json(name = "DataPoczatkowa")
val startDate: String,
@Json(name = "DataKoncowa")
val endDate: String,
@Json(name = "LoginId")
val loginId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,14 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Recipient(
@Json(name = "LoginId")
val loginId: Int,
@Json(name = "Nazwa")
val name: String,
)

View file

@ -1,26 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class SendMessageRequest(
@Json(name = "NadawcaWiadomosci")
val sender: String,
@Json(name = "Tytul")
val subject: String,
@Json(name = "Tresc")
val content: String,
@Json(name = "Adresaci")
val recipients: List<Recipient>,
@Json(name = "LoginId")
val loginId: Int,
@Json(name = "IdUczen")
val studentId: Int,
)

View file

@ -1,50 +0,0 @@
package io.github.wulkanowy.sdk.mobile.notes
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Note(
@Json(name = "Id")
val id: Int,
@Json(name = "IdKategoriaUwag")
val noteCategoryId: Int,
@Json(name = "IdUczen")
val studentId: Int,
@Json(name = "UczenImie")
val studentName: String,
@Json(name = "UczenNazwisko")
val studentSurname: String,
@Json(name = "IdPracownik")
val employeeId: Int,
@Json(name = "PracownikImie")
val employeeName: String,
@Json(name = "PracownikNazwisko")
val employeeSurname: String,
@Json(name = "DataWpisu")
val entryDate: Long,
@Json(name = "DataWpisuTekst")
val entryDateText: String,
@Json(name = "DataModyfikacji")
val modificationDate: Long?,
@Json(name = "DataModyfikacjiTekst")
val modificationDateText: String?,
@Json(name = "UwagaKey")
val noteKey: String,
@Json(name = "TrescUwagi")
val content: String,
)

View file

@ -1,15 +0,0 @@
package io.github.wulkanowy.sdk.mobile.notes
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class NotesRequest(
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,41 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
import java.util.UUID
@JsonClass(generateAdapter = true)
data class CertificateRequest(
@Json(name = "PIN")
val pin: String,
@Json(name = "TokenKey")
val tokenKey: String,
@Json(name = "AppVersion")
val appVersion: String = MOBILE_APP_VERSION,
@Json(name = "DeviceId")
val deviceId: String = UUID.randomUUID().toString(),
@Json(name = "DeviceName")
val deviceName: String,
@Json(name = "DeviceNameUser")
val deviceNameUser: String = "",
@Json(name = "DeviceDescription")
val deviceDescription: String = "",
@Json(name = "DeviceSystemType")
val deviceSystemType: String = "Android",
@Json(name = "DeviceSystemVersion")
val deviceSystemVersion: String = "8.1.0",
@Json(name = "FirebaseTokenKey")
val firebaseToken: String,
) : ApiRequest()

View file

@ -1,26 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class CertificateResponse(
@Json(name = "IsError")
val isError: Boolean,
@Json(name = "IsMessageForUser")
val isMessageForUser: Boolean,
@Json(name = "Message")
val message: String?,
@Json(name = "TokenKey")
val tokenKey: String?,
@Json(name = "TokenStatus")
val tokenStatus: String?,
@Json(name = "TokenCert")
val tokenCert: TokenCert?,
)

View file

@ -1,102 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Student(
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "OkresPoziom")
val periodLevel: Int,
@Json(name = "OkresNumer")
val periodNumber: Int,
@Json(name = "OkresDataOd")
val periodDateFrom: Long,
@Json(name = "OkresDataDo")
val periodDateTo: Long,
@Json(name = "OkresDataOdTekst")
val periodDateFromText: String,
@Json(name = "OkresDataDoTekst")
val periodDateToText: String,
@Json(name = "IdJednostkaSprawozdawcza")
val reportingUnitId: Int,
@Json(name = "JednostkaSprawozdawczaSkrot")
val reportingUnitShortcut: String,
@Json(name = "JednostkaSprawozdawczaNazwa")
val reportingUnitName: String,
@Json(name = "JednostkaSprawozdawczaSymbol")
val reportingUnitSymbol: String,
@Json(name = "IdJednostka")
val unitId: Int,
@Json(name = "JednostkaNazwa")
val unitName: String,
@Json(name = "JednostkaSkrot")
val unitShortcut: String,
@Json(name = "OddzialSymbol")
val classSymbol: String,
@Json(name = "OddzialKod")
val classCode: String?,
@Json(name = "UzytkownikRola")
val userRole: String,
@Json(name = "UzytkownikLogin")
val userLogin: String,
@Json(name = "UzytkownikLoginId")
val userLoginId: Int,
@Json(name = "UzytkownikNazwa")
val userName: String,
@Json(name = "Id")
val id: Int,
@Json(name = "IdOddzial")
val classId: Int,
@Json(name = "Imie")
val name: String,
@Json(name = "Imie2")
val nameSecond: String?,
@Json(name = "Nazwisko")
val surname: String,
@Json(name = "Pseudonim")
val nick: String?,
@Json(name = "UczenPlec")
val pupilGender: Int,
@Json(name = "Pozycja")
val position: Int,
@Json(name = "LoginId")
val loginId: Int?,
) {
var privateKey = ""
var certificateKey = ""
var mobileBaseUrl = ""
}

View file

@ -1,38 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class TokenCert(
@Json(name = "CertyfikatKlucz")
val certificateKey: String,
@Json(name = "CertyfikatKluczSformatowanyTekst")
val certificateKeyFormatted: String,
@Json(name = "CertyfikatDataUtworzenia")
val certificateCreatedDate: Int,
@Json(name = "CertyfikatDataUtworzeniaSformatowanyTekst")
val certificateCreatedDateText: String,
@Json(name = "CertyfikatPfx")
val certificatePfx: String,
@Json(name = "GrupaKlientow")
val symbol: String,
@Json(name = "AdresBazowyRestApi")
val baseUrl: String,
@Json(name = "UzytkownikLogin")
val userLogin: String,
@Json(name = "UzytkownikNazwa")
val userName: String,
@Json(name = "TypKonta")
val accountType: String?,
)

View file

@ -1,101 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.ApiResponse
import io.github.wulkanowy.sdk.mobile.attendance.Attendance
import io.github.wulkanowy.sdk.mobile.attendance.AttendanceRequest
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.dictionaries.DictionariesRequest
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.exams.ExamsRequest
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.grades.GradesRequest
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.homework.HomeworkRequest
import io.github.wulkanowy.sdk.mobile.messages.Message
import io.github.wulkanowy.sdk.mobile.messages.MessageStatusChangeRequest
import io.github.wulkanowy.sdk.mobile.messages.MessagesRequest
import io.github.wulkanowy.sdk.mobile.messages.Recipient
import io.github.wulkanowy.sdk.mobile.messages.SendMessageRequest
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.notes.NotesRequest
import io.github.wulkanowy.sdk.mobile.school.Teacher
import io.github.wulkanowy.sdk.mobile.school.TeachersRequest
import io.github.wulkanowy.sdk.mobile.service.MobileService
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.sdk.mobile.timetable.TimetableRequest
import io.github.wulkanowy.sdk.mobile.toFormat
import java.time.LocalDate
import java.time.LocalDateTime
class MobileRepository(private val api: MobileService) {
suspend fun logStart(): ApiResponse<String> = api.logAppStart(ApiRequest())
suspend fun getDictionaries(userId: Int, classificationPeriodId: Int, classId: Int): Dictionaries {
return api.getDictionaries(DictionariesRequest(userId, classificationPeriodId, classId)).data!!
}
suspend fun getTeachers(studentId: Int, semesterId: Int): List<Teacher> {
return api.getTeachers(TeachersRequest(studentId, semesterId)).data.let {
it?.schoolTeachers.orEmpty().union(it?.teachersSubjects.orEmpty()).toList()
}
}
suspend fun getTimetable(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): List<Lesson> {
return api.getTimetable(TimetableRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).data!!
}
suspend fun getGradesDetails(classId: Int, classificationPeriodId: Int, studentId: Int): List<Grade> {
return api.getGrades(GradesRequest(classId, classificationPeriodId, studentId)).data!!
}
suspend fun getGradesSummary(classId: Int, classificationPeriodId: Int, studentId: Int): GradesSummaryResponse {
return api.getGradesSummary(GradesRequest(classId, classificationPeriodId, studentId)).data!!
}
suspend fun getExams(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): List<Exam> {
return api.getExams(ExamsRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).data!!
}
suspend fun getNotes(classificationPeriodId: Int, studentId: Int): List<Note> {
return api.getNotes(NotesRequest(classificationPeriodId, studentId)).data!!
}
suspend fun getAttendance(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): List<Attendance> {
return api.getAttendance(AttendanceRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).data!!.items
}
suspend fun getHomework(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): List<Homework> {
return api.getHomework(HomeworkRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).data!!
}
suspend fun getMessages(start: LocalDateTime, end: LocalDateTime, loginId: Int, studentId: Int): List<Message> {
return api.getMessages(MessagesRequest(start.toFormat(), end.toFormat(), loginId, studentId)).data!!
}
suspend fun getMessagesDeleted(start: LocalDateTime, end: LocalDateTime, loginId: Int, studentId: Int): List<Message> {
return api.getMessagesDeleted(MessagesRequest(start.toFormat(), end.toFormat(), loginId, studentId)).data!!
}
suspend fun getMessagesSent(start: LocalDateTime, end: LocalDateTime, loginId: Int, studentId: Int): List<Message> {
return api.getMessagesSent(MessagesRequest(start.toFormat(), end.toFormat(), loginId, studentId)).data!!
}
suspend fun changeMessageStatus(messageId: String, folder: String, status: String, loginId: Int, studentId: Int): String {
return api.changeMessageStatus(MessageStatusChangeRequest(messageId.toInt(), folder, status, loginId, studentId)).data!!
}
suspend fun sendMessage(sender: String, subject: String, content: String, recipients: List<Recipient>, loginId: Int, studentId: Int): Message {
val request = SendMessageRequest(
sender = sender,
subject = subject,
content = content,
recipients = recipients,
loginId = loginId,
studentId = studentId,
)
return api.sendMessage(request)
}
}

View file

@ -1,23 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.register.CertificateRequest
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.service.RegisterService
class RegisterRepository(private val api: RegisterService) {
suspend fun getCertificate(token: String, pin: String, deviceName: String, android: String, firebaseToken: String): CertificateResponse {
val request = CertificateRequest(
tokenKey = token,
pin = pin,
deviceName = "$deviceName (Wulkanowy)",
deviceSystemVersion = android,
firebaseToken = firebaseToken,
)
return api.getCertificate(request)
}
suspend fun getStudents(): List<Student> = api.getPupils(object : ApiRequest() {}).data.orEmpty()
}

View file

@ -1,55 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.interceptor.ErrorInterceptor
import io.github.wulkanowy.sdk.mobile.interceptor.SignInterceptor
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.create
class RepositoryManager(
private val logLevel: HttpLoggingInterceptor.Level,
private val privateKey: String,
private val certKey: String,
private val interceptors: MutableList<Pair<Interceptor, Boolean>>,
private val baseUrl: String,
private val schoolSymbol: String,
) {
fun getRoutesRepository(): RoutingRulesRepository {
return RoutingRulesRepository(getRetrofitBuilder(interceptors).baseUrl("http://komponenty.vulcan.net.pl").build().create())
}
fun getMobileRepository(): MobileRepository {
return MobileRepository(getRetrofitBuilder(interceptors).baseUrl("$baseUrl/$schoolSymbol/mobile-api/Uczen.v3.Uczen/").build().create())
}
fun getRegisterRepository(baseUrl: String, symbol: String) = getRegisterRepository("${baseUrl.removeSuffix("/")}/$symbol")
fun getRegisterRepository(baseUrl: String): RegisterRepository {
return RegisterRepository(getRetrofitBuilder(interceptors).baseUrl("${baseUrl.removeSuffix("/")}/mobile-api/Uczen.v3.UczenStart/").build().create())
}
private fun getRetrofitBuilder(interceptors: MutableList<Pair<Interceptor, Boolean>>): Retrofit.Builder {
return Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.client(
OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
.addInterceptor(ErrorInterceptor())
.addInterceptor(SignInterceptor(privateKey, certKey))
.apply {
interceptors.forEach {
if (it.second) {
addNetworkInterceptor(it.first)
} else addInterceptor(it.first)
}
}
.build(),
)
}
}

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException
import io.github.wulkanowy.sdk.mobile.exception.UnknownTokenException
import io.github.wulkanowy.sdk.mobile.service.RoutingRulesService
class RoutingRulesRepository(private val api: RoutingRulesService) {
suspend fun getRouteByToken(token: String): String {
if (token.length < 4) throw InvalidTokenException("Token '$token' is too short")
val tokenSymbol = token.substring(0..2)
if ("FK1" == tokenSymbol) return "https://api.fakelog.tk"
return api.getRoutingRules().split("\r?\n".toRegex())
.singleOrNull { tokenSymbol == it.substringBefore(",") }
?.substringAfter(",")
?: throw UnknownTokenException("This token: '$token' is unsupported")
}
}

View file

@ -1,17 +0,0 @@
package io.github.wulkanowy.sdk.mobile.school
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Teacher(
@Json(name = "IdPracownik")
val employeeId: Int,
@Json(name = "IdPrzedmiot")
val subjectId: Int,
@Json(name = "Rola")
val role: String,
)

View file

@ -1,15 +0,0 @@
package io.github.wulkanowy.sdk.mobile.school
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
class TeachersRequest(
@Json(name = "IdUczen")
val studentId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val semesterId: Int,
) : ApiRequest()

View file

@ -1,14 +0,0 @@
package io.github.wulkanowy.sdk.mobile.school
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class TeachersResponse(
@Json(name = "NauczycieleSzkola")
val schoolTeachers: List<Teacher>,
@Json(name = "NauczycielePrzedmioty")
val teachersSubjects: List<Teacher>,
)

View file

@ -1,75 +0,0 @@
package io.github.wulkanowy.sdk.mobile.service
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.ApiResponse
import io.github.wulkanowy.sdk.mobile.attendance.AttendanceRequest
import io.github.wulkanowy.sdk.mobile.attendance.AttendanceResponse
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.dictionaries.DictionariesRequest
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.exams.ExamsRequest
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.grades.GradesRequest
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.homework.HomeworkRequest
import io.github.wulkanowy.sdk.mobile.messages.Message
import io.github.wulkanowy.sdk.mobile.messages.MessageStatusChangeRequest
import io.github.wulkanowy.sdk.mobile.messages.MessagesRequest
import io.github.wulkanowy.sdk.mobile.messages.SendMessageRequest
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.notes.NotesRequest
import io.github.wulkanowy.sdk.mobile.school.TeachersRequest
import io.github.wulkanowy.sdk.mobile.school.TeachersResponse
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.sdk.mobile.timetable.TimetableRequest
import retrofit2.http.Body
import retrofit2.http.POST
interface MobileService {
@POST("LogAppStart")
suspend fun logAppStart(@Body logAppStartRequest: ApiRequest): ApiResponse<String>
@POST("Slowniki")
suspend fun getDictionaries(@Body dictionariesRequest: DictionariesRequest): ApiResponse<Dictionaries>
@POST("Nauczyciele")
suspend fun getTeachers(@Body teachersRequest: TeachersRequest): ApiResponse<TeachersResponse>
@POST("PlanLekcjiZeZmianami")
suspend fun getTimetable(@Body timetableRequest: TimetableRequest): ApiResponse<List<Lesson>>
@POST("Oceny")
suspend fun getGrades(@Body gradesRequest: GradesRequest): ApiResponse<List<Grade>>
@POST("OcenyPodsumowanie")
suspend fun getGradesSummary(@Body gradesRequest: GradesRequest): ApiResponse<GradesSummaryResponse>
@POST("Sprawdziany")
suspend fun getExams(@Body examsRequest: ExamsRequest): ApiResponse<List<Exam>>
@POST("UwagiUcznia")
suspend fun getNotes(@Body notesRequest: NotesRequest): ApiResponse<List<Note>>
@POST("Frekwencje")
suspend fun getAttendance(@Body attendanceRequest: AttendanceRequest): ApiResponse<AttendanceResponse>
@POST("ZadaniaDomowe")
suspend fun getHomework(@Body homeworkRequest: HomeworkRequest): ApiResponse<List<Homework>>
@POST("WiadomosciOdebrane")
suspend fun getMessages(@Body messagesRequest: MessagesRequest): ApiResponse<List<Message>>
@POST("WiadomosciWyslane")
suspend fun getMessagesSent(@Body messagesRequest: MessagesRequest): ApiResponse<List<Message>>
@POST("WiadomosciUsuniete")
suspend fun getMessagesDeleted(@Body messagesRequest: MessagesRequest): ApiResponse<List<Message>>
@POST("ZmienStatusWiadomosci")
suspend fun changeMessageStatus(@Body messageStatusChangeRequest: MessageStatusChangeRequest): ApiResponse<String>
@POST("DodajWiadomosc")
suspend fun sendMessage(@Body sendMessageRequest: SendMessageRequest): Message
}

View file

@ -1,20 +0,0 @@
package io.github.wulkanowy.sdk.mobile.service
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.ApiResponse
import io.github.wulkanowy.sdk.mobile.register.CertificateRequest
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
interface RegisterService {
@POST("Certyfikat")
@Headers("RequestMobileType: RegisterDevice")
suspend fun getCertificate(@Body certificateRequest: CertificateRequest): CertificateResponse
@POST("ListaUczniow")
suspend fun getPupils(@Body pupilsListRequest: ApiRequest): ApiResponse<List<Student>>
}

View file

@ -1,9 +0,0 @@
package io.github.wulkanowy.sdk.mobile.service
import retrofit2.http.GET
interface RoutingRulesService {
@GET("/UonetPlusMobile/RoutingRules.txt")
suspend fun getRoutingRules(): String
}

View file

@ -1,59 +0,0 @@
package io.github.wulkanowy.sdk.mobile.timetable
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Lesson(
@Json(name = "Dzien")
val day: Long,
@Json(name = "DzienTekst")
val dayText: String,
@Json(name = "NumerLekcji")
val lessonNumber: Int,
@Json(name = "IdPoraLekcji")
val lessonTimeId: Int,
@Json(name = "IdPrzedmiot")
val subjectId: Int,
@Json(name = "PrzedmiotNazwa")
val subjectName: String,
@Json(name = "PodzialSkrot")
val divisionShort: String?,
@Json(name = "Sala")
val room: String?,
@Json(name = "IdPracownik")
val employeeId: Int,
@Json(name = "IdPracownikWspomagajacy")
val employeeSupporterId: Int?,
@Json(name = "IdPracownikOld")
val employeeOldId: Int?,
@Json(name = "IdPracownikWspomagajacyOld")
val employeeSupporterOldId: Int?,
@Json(name = "IdPlanLekcji")
val timetableId: Int,
@Json(name = "AdnotacjaOZmianie")
val annotationAboutChange: String?,
@Json(name = "PrzekreslonaNazwa")
val overriddenName: Boolean,
@Json(name = "PogrubionaNazwa")
val boldName: Boolean,
@Json(name = "PlanUcznia")
val studentPlan: Boolean,
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.timetable
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import io.github.wulkanowy.sdk.mobile.ApiRequest
@JsonClass(generateAdapter = true)
data class TimetableRequest(
@Json(name = "DataPoczatkowa")
val startDate: String,
@Json(name = "DataKoncowa")
val endDate: String,
@Json(name = "IdOddzial")
val classId: Int,
@Json(name = "IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@Json(name = "IdUczen")
val studentId: Int,
) : ApiRequest()

View file

@ -1,42 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import io.github.wulkanowy.sdk.mobile.interceptor.ErrorInterceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
open class BaseLocalTest {
val server = MockWebServer()
fun MockWebServer.enqueue(fileName: String, clazz: Class<*>) {
enqueue(MockResponse().setBody(clazz.getResource(fileName).readText()))
}
fun MockWebServer.enqueueAndStart(fileName: String, clazz: Class<*> = this@BaseLocalTest.javaClass, port: Int = 3030) {
enqueue(fileName, clazz)
start(port)
}
@After
fun tearDown() {
server.shutdown()
}
fun getRetrofit(baseUrl: String = server.url("/").toString()): Retrofit = getRetrofitBuilder().baseUrl(baseUrl).build()
fun getRetrofitBuilder(): Retrofit.Builder = Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.client(
OkHttpClient().newBuilder()
.addInterceptor(ErrorInterceptor())
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.build(),
)
}

View file

@ -1,124 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import io.github.wulkanowy.sdk.mobile.interceptor.SignInterceptor
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import io.github.wulkanowy.sdk.mobile.repository.RegisterRepository
import io.github.wulkanowy.signer.getPrivateKeyFromCert
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Test
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.create
import java.time.LocalDate.of
const val PASSWORD = "012345678901234567890123456789AB"
const val DEVICE_NAME = "Wulkanowy#client"
const val HOST = "https://api.fakelog.cf"
const val SYMBOL = "powiatwulkanowy"
const val TOKEN = "FK100000"
const val PIN = "999999"
@Ignore
class UonetTest {
companion object {
private lateinit var mobile: MobileRepository
private lateinit var student: Student
private fun getRetrofitBuilder(privateKey: String, certKey: String): Retrofit.Builder {
return Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.client(
OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.addInterceptor(SignInterceptor(privateKey, certKey))
.build(),
)
}
@JvmStatic
@BeforeClass
fun setUp() {
// RegisterRepository
val register = RegisterRepository(
api = getRetrofitBuilder("", "")
.baseUrl("$HOST/$SYMBOL/mobile-api/Uczen.v3.UczenStart/")
.build().create(),
)
val certificate = runBlocking { register.getCertificate(TOKEN, PIN, DEVICE_NAME, "8.1.0", "") }
assertEquals(false, certificate.isError)
val tokenCrt = certificate.tokenCert
val certKey = tokenCrt!!.certificateKey
val cert = tokenCrt.certificatePfx
val privateKey = getPrivateKeyFromCert(PASSWORD, cert)
val pupils = runBlocking { register.getStudents() }
assertEquals(2, pupils.size)
student = pupils[0]
// MobileRepository
mobile = MobileRepository(
api = getRetrofitBuilder(privateKey, certKey)
.baseUrl("$HOST/powiatwulkanowy/${student.reportingUnitSymbol}/mobile-api/Uczen.v3.Uczen/")
.build().create(),
)
}
}
@Test
fun logStartTest() {
val start = runBlocking { mobile.logStart() }
assertEquals("Ok", start.status)
}
@Test
fun dictionariesTest() {
runBlocking { mobile.getDictionaries(student.userLoginId, student.classificationPeriodId, student.classId) }
}
@Test
fun timetableTest() {
runBlocking { mobile.getTimetable(of(2018, 4, 23), of(2018, 4, 24), student.classId, student.classificationPeriodId, student.id) }
}
@Test
fun gradesTest() {
runBlocking { mobile.getGradesDetails(student.classId, student.classificationPeriodId, student.id) }
}
@Test
fun examsTest() {
runBlocking { mobile.getExams(of(2018, 5, 28), of(2018, 6, 3), student.classId, student.classificationPeriodId, student.id) }
}
@Test
fun notesTest() {
runBlocking { mobile.getNotes(student.classificationPeriodId, student.id) }
}
@Test
fun attendanceTest() {
runBlocking { mobile.getAttendance(of(2018, 4, 23), of(2018, 4, 24), student.classId, student.classificationPeriodId, student.id) }
}
@Test
fun homeworkTest() {
runBlocking { mobile.getHomework(of(2017, 10, 23), of(2017, 10, 27), student.classId, student.classificationPeriodId, student.id) }
}
}

View file

@ -1,23 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exams
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
import java.time.LocalDate.of
class ExamsTest : BaseLocalTest() {
private val exams by lazy { MobileRepository(getRetrofit().create()) }
@Test
fun getExams() {
server.enqueueAndStart("Sprawdziany.json")
val items = runBlocking { exams.getExams(of(2020, 1, 16), of(2020, 1, 17), 1, 2, 3) }
assertEquals(3, items.size)
}
}

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
class GradesTest : BaseLocalTest() {
private val grades by lazy { MobileRepository(getRetrofit().create()) }
@Test
fun getGrades() {
server.enqueueAndStart("Oceny.json")
val items = runBlocking { grades.getGradesDetails(0, 0, 0) }
assertEquals(2, items.size)
}
}

View file

@ -1,39 +0,0 @@
package io.github.wulkanowy.sdk.mobile.interceptor
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException
import io.github.wulkanowy.sdk.mobile.repository.RegisterRepository
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertTrue
import org.junit.Test
import retrofit2.create
import java.io.IOException
class ErrorInterceptorTest : BaseLocalTest() {
@Test
fun unknownError() {
server.enqueueAndStart("bad-request.txt")
val repo = RegisterRepository(getRetrofitBuilder().baseUrl("http://localhost:3030/").build().create())
try {
runBlocking { repo.getStudents() }
} catch (e: Throwable) {
assertTrue(e is IOException)
}
}
@Test
fun invalidSymbol_diacritics() {
server.enqueueAndStart("invalid-symbol.html")
val repo = RegisterRepository(getRetrofitBuilder().baseUrl("http://localhost:3030/").build().create())
try {
runBlocking { repo.getStudents() }
} catch (e: Throwable) {
assertTrue(e is InvalidSymbolException)
}
}
}

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.RegisterRepository
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
class RegisterTest : BaseLocalTest() {
private val repo by lazy { RegisterRepository(getRetrofit().create()) }
@Test
fun getStudents() {
server.enqueueAndStart("ListaUczniow.json")
val students = runBlocking { repo.getStudents() }
assertEquals(2, students.size)
}
}

View file

@ -1,49 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import retrofit2.create
class RoutingRulesRepositoryTest : BaseLocalTest() {
@Test
fun getRouteByToken() {
server.enqueueAndStart("RoutingRules.txt")
val repo = RoutingRulesRepository(getRetrofit().create())
val route = runBlocking { repo.getRouteByToken("KA2000") }
assertEquals("https://uonetplus-komunikacja-test.mcuw.katowice.eu", route)
}
@Test
fun getRouteByToken_invalid() {
server.enqueueAndStart("RoutingRules.txt")
val repo = RoutingRulesRepository(getRetrofit().create())
try {
runBlocking { repo.getRouteByToken("ERR00000") }
} catch (e: Throwable) {
assertTrue(e is InvalidTokenException)
}
}
@Test
fun getRouteByToken_tooShort() {
server.enqueueAndStart("RoutingRules.txt")
val repo = RoutingRulesRepository(getRetrofit().create())
// TODO: fix assert to run event if no exception thrown
try {
runBlocking { repo.getRouteByToken("ER") }
} catch (e: Throwable) {
assertTrue(e is InvalidTokenException)
}
}
}

View file

@ -1,23 +0,0 @@
package io.github.wulkanowy.sdk.mobile.timetable
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
import java.time.LocalDate.of
class TimetableTest : BaseLocalTest() {
private val timetable by lazy { MobileRepository(getRetrofit().create()) }
@Test
fun getTimetable() {
server.enqueueAndStart("PlanLekcji.json")
val items = runBlocking { timetable.getTimetable(of(2020, 1, 10), of(2020, 2, 11), 1, 2, 3) }
assertEquals(5, items.size)
}
}

View file

@ -1,911 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579118032,
"TimeValue": "Wed, 15 Jan 2020 19:53:51 GMT",
"RequestId": "38af6dfe-cd51-4b74-b7d3-52f764b48d85",
"DayOfWeek": 3,
"AppVersion": "17.09.0009.26859",
"Data": {
"TimeKey": 1579118032,
"Nauczyciele": [
{
"Id": 1,
"Imie": "Karolina",
"Nazwisko": "Kowalska",
"Kod": "AN",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 100
},
{
"Id": 2,
"Imie": "Zofia",
"Nazwisko": "Czerwińska",
"Kod": "NA",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 101
},
{
"Id": 3,
"Imie": "Aleksandra",
"Nazwisko": "Krajewska",
"Kod": "AK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 102
},
{
"Id": 4,
"Imie": "Stanisław",
"Nazwisko": "Krupa",
"Kod": "BS",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 103
},
{
"Id": 5,
"Imie": "Aleksandra",
"Nazwisko": "Wójtowicz",
"Kod": "AW",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 104
},
{
"Id": 6,
"Imie": "Sara",
"Nazwisko": "Wierzbicka",
"Kod": "KB",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 105
},
{
"Id": 7,
"Imie": "Mateusz",
"Nazwisko": "Kowal",
"Kod": "MK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 106
},
{
"Id": 8,
"Imie": "Amelia",
"Nazwisko": "Mazur",
"Kod": "AM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 107
},
{
"Id": 9,
"Imie": "Barbara",
"Nazwisko": "Markowska",
"Kod": "BM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 108
},
{
"Id": 10,
"Imie": "Michał",
"Nazwisko": "Mazur",
"Kod": "MM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 109
}
],
"Pracownicy": [
{
"Id": 1,
"Imie": "Karolina",
"Nazwisko": "Kowalska",
"Kod": "AN",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 100
},
{
"Id": 2,
"Imie": "Zofia",
"Nazwisko": "Czerwińska",
"Kod": "NA",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 101
},
{
"Id": 3,
"Imie": "Aleksandra",
"Nazwisko": "Krajewska",
"Kod": "AK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 102
},
{
"Id": 4,
"Imie": "Stanisław",
"Nazwisko": "Krupa",
"Kod": "BS",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 103
},
{
"Id": 5,
"Imie": "Aleksandra",
"Nazwisko": "Wójtowicz",
"Kod": "AW",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 104
},
{
"Id": 6,
"Imie": "Sara",
"Nazwisko": "Wierzbicka",
"Kod": "KB",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 105
},
{
"Id": 7,
"Imie": "Mateusz",
"Nazwisko": "Kowal",
"Kod": "MK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 106
},
{
"Id": 8,
"Imie": "Amelia",
"Nazwisko": "Mazur",
"Kod": "AM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 107
},
{
"Id": 9,
"Imie": "Barbara",
"Nazwisko": "Markowska",
"Kod": "BM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 108
},
{
"Id": 10,
"Imie": "Michał",
"Nazwisko": "Mazur",
"Kod": "MM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 109
}
],
"Przedmioty": [
{
"Id": 300,
"Nazwa": "Zajęcia z wychowawcą",
"Kod": "godz.wych",
"Aktywny": true,
"Pozycja": 0
},
{
"Id": 301,
"Nazwa": "Język polski",
"Kod": "j. polski",
"Aktywny": true,
"Pozycja": 3
},
{
"Id": 302,
"Nazwa": "Historia",
"Kod": "historia",
"Aktywny": true,
"Pozycja": 1
},
{
"Id": 303,
"Nazwa": "Etyka",
"Kod": "etyka",
"Aktywny": true,
"Pozycja": 2
},
{
"Id": 304,
"Nazwa": "Język angielski",
"Kod": "j. angielski",
"Aktywny": true,
"Pozycja": 4
},
{
"Id": 305,
"Nazwa": "Język niemiecki",
"Kod": "j. niemiecki",
"Aktywny": true,
"Pozycja": 5
},
{
"Id": 306,
"Nazwa": "Metodologia programowania",
"Kod": "metod.programowania",
"Aktywny": true,
"Pozycja": 6
},
{
"Id": 307,
"Nazwa": "Matematyka",
"Kod": "matematyka",
"Aktywny": true,
"Pozycja": 7
},
{
"Id": 308,
"Nazwa": "Fizyka",
"Kod": "fizyka",
"Aktywny": true,
"Pozycja": 8
},
{
"Id": 309,
"Nazwa": "Chemia",
"Kod": "chemia",
"Aktywny": true,
"Pozycja": 9
},
{
"Id": 310,
"Nazwa": "Biologia",
"Kod": "biologia",
"Aktywny": true,
"Pozycja": 10
},
{
"Id": 311,
"Nazwa": "Geografia",
"Kod": "geografia",
"Aktywny": true,
"Pozycja": 11
},
{
"Id": 312,
"Nazwa": "Informatyka",
"Kod": "informatyka",
"Aktywny": true,
"Pozycja": 12
},
{
"Id": 313,
"Nazwa": "Religia",
"Kod": "religia",
"Aktywny": true,
"Pozycja": 13
}
],
"PoryLekcji": [
{
"Id": 76,
"Numer": 1,
"Poczatek": 25200,
"PoczatekTekst": "08:00",
"Koniec": 27900,
"KoniecTekst": "08:45"
},
{
"Id": 77,
"Numer": 2,
"Poczatek": 28500,
"PoczatekTekst": "08:55",
"Koniec": 31200,
"KoniecTekst": "09:40"
},
{
"Id": 78,
"Numer": 3,
"Poczatek": 31800,
"PoczatekTekst": "09:50",
"Koniec": 34500,
"KoniecTekst": "10:35"
},
{
"Id": 79,
"Numer": 4,
"Poczatek": 35100,
"PoczatekTekst": "10:45",
"Koniec": 37800,
"KoniecTekst": "11:30"
},
{
"Id": 80,
"Numer": 5,
"Poczatek": 38400,
"PoczatekTekst": "11:40",
"Koniec": 41100,
"KoniecTekst": "12:25"
},
{
"Id": 81,
"Numer": 6,
"Poczatek": 42300,
"PoczatekTekst": "12:45",
"Koniec": 45000,
"KoniecTekst": "13:30"
},
{
"Id": 82,
"Numer": 7,
"Poczatek": 45600,
"PoczatekTekst": "13:40",
"Koniec": 48300,
"KoniecTekst": "14:25"
},
{
"Id": 83,
"Numer": 8,
"Poczatek": 48600,
"PoczatekTekst": "14:30",
"Koniec": 51300,
"KoniecTekst": "15:15"
},
{
"Id": 84,
"Numer": 9,
"Poczatek": 51600,
"PoczatekTekst": "15:20",
"Koniec": 54300,
"KoniecTekst": "16:05"
},
{
"Id": 85,
"Numer": 10,
"Poczatek": 54600,
"PoczatekTekst": "16:10",
"Koniec": 57300,
"KoniecTekst": "16:55"
},
{
"Id": 86,
"Numer": 11,
"Poczatek": 57600,
"PoczatekTekst": "17:00",
"Koniec": 60300,
"KoniecTekst": "17:45"
},
{
"Id": 87,
"Numer": 12,
"Poczatek": 60600,
"PoczatekTekst": "17:50",
"Koniec": 63300,
"KoniecTekst": "18:35"
}
],
"KategorieOcen": [
{
"Id": 26,
"Kod": "Akt",
"Nazwa": "A - aktywność (czarny)"
},
{
"Id": 27,
"Kod": "Bież",
"Nazwa": "B - bieżące (fiol)"
},
{
"Id": 28,
"Kod": "Kart",
"Nazwa": "K - kartkówka (zielony)"
},
{
"Id": 29,
"Kod": "Spr",
"Nazwa": "S - sprawdzian (czerwony)"
},
{
"Id": 30,
"Kod": "Z.dom",
"Nazwa": "Zd - zadanie domowe (czarny)"
},
{
"Id": 65,
"Kod": "odp",
"Nazwa": "OD - odpowiedź ustna (nieb)"
},
{
"Id": 67,
"Kod": "ref",
"Nazwa": "Referat"
},
{
"Id": 68,
"Kod": "zewn",
"Nazwa": "Sprawdzian zewnętrzny"
},
{
"Id": 69,
"Kod": "tsm",
"Nazwa": "Test sprawności motorycznej"
},
{
"Id": 70,
"Kod": "tu",
"Nazwa": "Test umiejętności"
},
{
"Id": 71,
"Kod": "zs",
"Nazwa": "Zawody sportowe"
},
{
"Id": 72,
"Kod": "bs",
"Nazwa": "Brak stroju"
},
{
"Id": 73,
"Kod": "r",
"Nazwa": "Rozgrzewka"
},
{
"Id": 74,
"Kod": "pr_dł",
"Nazwa": "Praca długoterminowa"
},
{
"Id": 75,
"Kod": "ze_ćwi",
"Nazwa": "Zeszyt ćwiczeń"
},
{
"Id": 76,
"Kod": "Inne",
"Nazwa": "Inne"
},
{
"Id": 77,
"Kod": "popspr",
"Nazwa": "Poprawa sprawdzianu"
},
{
"Id": 78,
"Kod": "PK",
"Nazwa": "Praca klasowa"
},
{
"Id": 79,
"Kod": "Re",
"Nazwa": "Recytacja"
},
{
"Id": 80,
"Kod": "dyk",
"Nazwa": "Dyktando"
},
{
"Id": 81,
"Kod": "lek",
"Nazwa": "Lektura"
},
{
"Id": 82,
"Kod": "sp_wiedzy",
"Nazwa": "Sprawdzian wiedzy"
},
{
"Id": 83,
"Kod": "egz_próbny",
"Nazwa": "Egzamin próbny"
}
],
"KategorieUwag": [
{
"Id": 46,
"Nazwa": "Wypełnianie obowiązków ucznia",
"Aktywny": false
},
{
"Id": 47,
"Nazwa": "Zaangażowanie społeczne",
"Aktywny": false
},
{
"Id": 48,
"Nazwa": "Kultura języka",
"Aktywny": false
},
{
"Id": 49,
"Nazwa": "Kultura osobista",
"Aktywny": false
},
{
"Id": 50,
"Nazwa": "Dbałość o bezpieczeństwo i zdrowie",
"Aktywny": false
},
{
"Id": 51,
"Nazwa": "Szacunek dla innych osób",
"Aktywny": false
},
{
"Id": 52,
"Nazwa": "Zachowanie norm etycznych",
"Aktywny": false
},
{
"Id": 53,
"Nazwa": "Reprezentowanie szkoły",
"Aktywny": false
},
{
"Id": 54,
"Nazwa": "Zachowanie na lekcji",
"Aktywny": false
},
{
"Id": 58,
"Nazwa": "Inne (informacja bez punktów)",
"Aktywny": true
},
{
"Id": 59,
"Nazwa": "Udział w konkursie szkolnym +20 pkt",
"Aktywny": false
},
{
"Id": 61,
"Nazwa": "Przeszkadzanie na lekcjach -5 pkt",
"Aktywny": false
},
{
"Id": 66,
"Nazwa": "+ Udział w olimpiadzie przedmiotowej i konkursach pozaszk. (rza w sem. 20-30-50)",
"Aktywny": true
},
{
"Id": 67,
"Nazwa": "+ Udział w konkursie szkolnym (0-20)",
"Aktywny": true
},
{
"Id": 68,
"Nazwa": "+ Funkcja w szkole (0-20)",
"Aktywny": true
},
{
"Id": 69,
"Nazwa": "+ Funkcja w klasie (0-30)",
"Aktywny": true
},
{
"Id": 70,
"Nazwa": "+ Reprezentowanie szkoły w rozgrywkach sport.( raz w sem. 0-100)",
"Aktywny": true
},
{
"Id": 71,
"Nazwa": "+ Pomoc podczas imprezy szkolnej (0-10)",
"Aktywny": false
},
{
"Id": 72,
"Nazwa": "+ Praca na rzecz klasy (0-20)",
"Aktywny": true
},
{
"Id": 73,
"Nazwa": "+ Praca na rzecz szkoły (0-20)",
"Aktywny": true
},
{
"Id": 74,
"Nazwa": "+ Punktualność (0-20)",
"Aktywny": true
},
{
"Id": 75,
"Nazwa": "+ Pomoc kolegom (0-10)",
"Aktywny": true
},
{
"Id": 76,
"Nazwa": "+ Kulturalne zachowanie się w szkole i poza nią (0-50)",
"Aktywny": false
},
{
"Id": 77,
"Nazwa": "+ Przeciwstawianie się przejawom agresji i wulgarności (0-20)",
"Aktywny": false
},
{
"Id": 79,
"Nazwa": "+ Do dyspozycji wychowawcy (0-50)",
"Aktywny": true
},
{
"Id": 80,
"Nazwa": "+ Realizacja projektu edukacyjnego (0-50)",
"Aktywny": true
},
{
"Id": 81,
"Nazwa": "- Przeszkadzanie na lekcjach -5p.",
"Aktywny": true
},
{
"Id": 82,
"Nazwa": "- Okłamywanie i oszukiwanie nauczyciela 20p.",
"Aktywny": true
},
{
"Id": 83,
"Nazwa": "- Niewykonywanie poleceń nauczyciela (10-20)",
"Aktywny": true
},
{
"Id": 84,
"Nazwa": "- Aroganckie zachowanie wobec nauczyciela lub pracownika szkoły -50p.",
"Aktywny": true
},
{
"Id": 85,
"Nazwa": "- Ubliżanie kolegom/koleżankom (10-30)",
"Aktywny": true
},
{
"Id": 86,
"Nazwa": "- Przemoc fizyczna (10-30)",
"Aktywny": true
},
{
"Id": 87,
"Nazwa": "- Wulgarne słownictwo (10-30)",
"Aktywny": true
},
{
"Id": 88,
"Nazwa": "- Opuszczanie terenu szkoły w czasie zajęć -10p.",
"Aktywny": true
},
{
"Id": 89,
"Nazwa": "- Niszczenie mienia (10-30)",
"Aktywny": true
},
{
"Id": 90,
"Nazwa": "- Zaśmiecanie otoczenia (5-10)",
"Aktywny": true
},
{
"Id": 91,
"Nazwa": "- Strój i wygląd niezgodny z regulaminem ucznia (2-20)",
"Aktywny": true
},
{
"Id": 92,
"Nazwa": "- Spóźnienia się na lekcję do 10 min. (3p.)",
"Aktywny": true
},
{
"Id": 93,
"Nazwa": "- Niewykonywanie zobowiązania (10-20)",
"Aktywny": true
},
{
"Id": 94,
"Nazwa": "- Nieusprawiedliwiona nieobecność (5p.)",
"Aktywny": true
},
{
"Id": 95,
"Nazwa": "- Wyłudzanie pieniędzy (50p.)",
"Aktywny": true
},
{
"Id": 96,
"Nazwa": "- Kradzież (50p.)",
"Aktywny": true
},
{
"Id": 97,
"Nazwa": "- Palenie papierosów (50p.)",
"Aktywny": true
},
{
"Id": 98,
"Nazwa": "- Picie alkoholu (50p.)",
"Aktywny": true
},
{
"Id": 99,
"Nazwa": "- Stosowanie środków odurzających (50p.)",
"Aktywny": true
},
{
"Id": 100,
"Nazwa": "- Korzystanie z tel. kom. i urz. elek. niezgodnie z regulaminem (5-20)",
"Aktywny": true
},
{
"Id": 101,
"Nazwa": "- Drastyczne naruszenie ogólnie przyjętych norm społ. (100-250)",
"Aktywny": true
}
],
"KategorieFrekwencji": [
{
"Id": 1,
"Nazwa": "obecność",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 2,
"Nazwa": "nieobecność nieusprawiedliwiona",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": true,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 3,
"Nazwa": "nieobecność usprawiedliwiona",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": true,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": true,
"Usuniete": false
},
{
"Id": 4,
"Nazwa": "spóźnienie nieusprawiedliwione",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": true,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 5,
"Nazwa": "spóźnienie usprawiedliwione",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": true,
"Usprawiedliwione": true,
"Usuniete": false
},
{
"Id": 6,
"Nazwa": "nieobecny z przyczyn szkolnych",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 7,
"Nazwa": "zwolniony",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": false,
"Zwolnienie": true,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 8,
"Nazwa": "usunięty wpis",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": true
}
],
"TypyFrekwencji": [
{
"Id": 40,
"Symbol": "●",
"Nazwa": "obecność",
"Aktywny": true,
"WpisDomyslny": true,
"IdKategoriaFrek": 1
},
{
"Id": 41,
"Symbol": "—",
"Nazwa": "nieobecność",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 2
},
{
"Id": 42,
"Symbol": "u",
"Nazwa": "nieob. uspraw.",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 3
},
{
"Id": 43,
"Symbol": "s",
"Nazwa": "spóźnienie",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 4
},
{
"Id": 44,
"Symbol": "su",
"Nazwa": "spóźn. uspr.",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 5
},
{
"Id": 45,
"Symbol": "ns",
"Nazwa": "nieob. uspr. p.s.",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 6
},
{
"Id": 46,
"Symbol": "z",
"Nazwa": "zwolniony",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 7
},
{
"Id": 47,
"Symbol": "",
"Nazwa": "usunięty wpis",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 8
},
{
"Id": 55,
"Symbol": "zr",
"Nazwa": "zwolniony przez rodzica",
"Aktywny": false,
"WpisDomyslny": false,
"IdKategoriaFrek": 3
}
]
}
}

View file

@ -1,52 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579113877,
"TimeValue": "Wed, 15 Jan 2020 18:44:36 GMT",
"RequestId": "79ff96b3-5c63-4b03-9922-b5e22ed3ba6f",
"DayOfWeek": 3,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"Id": 2740,
"IdPrzedmiot": 118,
"IdPracownik": 94,
"IdOddzial": 52,
"IdPodzial": null,
"PodzialNazwa": null,
"PodzialSkrot": null,
"Rodzaj": true,
"RodzajNumer": 1,
"Opis": "Bajki - Ignacy Krasicki",
"Data": 1579215600,
"DataTekst": "2020-01-17"
},
{
"Id": 2741,
"IdPrzedmiot": 118,
"IdPracownik": 94,
"IdOddzial": 52,
"IdPodzial": null,
"PodzialNazwa": null,
"PodzialSkrot": null,
"Rodzaj": false,
"RodzajNumer": 2,
"Opis": "Epopeja - Pan Tadeusz",
"Data": 1579215600,
"DataTekst": "2020-01-17"
},
{
"Id": 2742,
"IdPrzedmiot": 118,
"IdPracownik": 94,
"IdOddzial": 52,
"IdPodzial": null,
"PodzialNazwa": null,
"PodzialSkrot": null,
"Rodzaj": false,
"RodzajNumer": 3,
"Opis": "Wielki Poeta - Słowacki",
"Data": 1579215600,
"DataTekst": "2020-01-17"
}
]
}

View file

@ -1,54 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1580410527,
"TimeValue": "Thu, 30 Jan 2020 18:55:27 GMT",
"RequestId": "090cdefc-64a7-4a06-908c-d12703a5f465",
"DayOfWeek": 4,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"Id": 1000,
"Pozycja": 1,
"PrzedmiotPozycja": 1,
"IdPrzedmiot": 300,
"IdKategoria": 26,
"Wpis": "3",
"Wartosc": 3,
"WagaModyfikatora": null,
"WagaOceny": 5,
"Licznik": null,
"Mianownik": null,
"Komentarz": null,
"Waga": "5,00",
"Opis": "Aktywność",
"DataUtworzenia": 1536883200,
"DataUtworzeniaTekst": "2018-09-14",
"DataModyfikacji": 1536883200,
"DataModyfikacjiTekst": "2018-09-14",
"IdPracownikD": 1,
"IdPracownikM": 1
},
{
"Id": 1001,
"Pozycja": 3,
"PrzedmiotPozycja": 8,
"IdPrzedmiot": 300,
"IdKategoria": 26,
"Wpis": "4",
"Wartosc": 4,
"WagaModyfikatora": null,
"WagaOceny": 5,
"Licznik": null,
"Mianownik": null,
"Komentarz": null,
"Waga": "5,00",
"Opis": "Aktywność",
"DataUtworzenia": 1538179200,
"DataUtworzeniaTekst": "2018-09-29",
"DataModyfikacji": 1538179200,
"DataModyfikacjiTekst": "2018-09-29",
"IdPracownikD": 1,
"IdPracownikM": 1
}
]
}

View file

@ -1,68 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1680906858,
"TimeValue": "Fri, 07 Apr 2023 22:34:17 GMT",
"RequestId": "e749eca7-65e7-4998-98d2-c2de3e7e6fc5",
"DayOfWeek": 5,
"AppVersion": "17.09.0009.26859",
"Data": {
"OcenyPrzewidywane": [
{
"IdPrzedmiot": 300,
"Wpis": "4"
},
{
"IdPrzedmiot": 301,
"Wpis": "3"
},
{
"IdPrzedmiot": 302,
"Wpis": "4"
},
{
"IdPrzedmiot": 303,
"Wpis": "4"
}
],
"OcenyKlasyfikacyjne": [
{
"IdPrzedmiot": 300,
"Wpis": "4+"
},
{
"IdPrzedmiot": 301,
"Wpis": "5"
},
{
"IdPrzedmiot": 302,
"Wpis": "2+"
},
{
"IdPrzedmiot": 303,
"Wpis": "3"
}
],
"SrednieOcen": [
{
"IdPrzedmiot": 300,
"SredniaOcen": "4,13",
"SumaPunktow": "123/200 (61,5%)"
},
{
"IdPrzedmiot": 301,
"SredniaOcen": "4,1",
"SumaPunktow": "234/300 (78%)"
},
{
"IdPrzedmiot": 302,
"SredniaOcen": "1,99",
"SumaPunktow": "345/400 (86,25%)"
},
{
"IdPrzedmiot": 303,
"SredniaOcen": "4",
"SumaPunktow": "456/500 (91,2%)"
}
]
}
}

View file

@ -1,32 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>UONET+ dla urządzeń mobilnych</title>
<link href="https://lekcjaplus.vulcan.net.pl/Content/mobile.css?v=5" rel="stylesheet" type="text/css" />
</head>
<body>
<a href="http://lekcjaplus.vulcan.net.pl/mobile/mobile/" class="pageHeader">
<div>Witamy w systemie UONET+ dla urządzeń mobilnych</div>
</a>
<div class="pageBlock">
<script type="text/mobile-api-data" id="AppVersion">19.11.0002.35804</script>
<div class="block">
<div class="blockInner">
<div style="font-weight: bold;">Podany symbol grupujący jest nieprawidłowy</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,41 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579185018,
"TimeValue": "Thu, 16 Jan 2020 14:30:18 GMT",
"RequestId": "1799be6b-7a60-4665-b75c-1bca504e8ebd",
"DayOfWeek": 4,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"IdOkresKlasyfikacyjny": 12,
"OkresPoziom": 4,
"OkresNumer": 1,
"OkresDataOd": 1567296000,
"OkresDataDo": 1580256000,
"OkresDataOdTekst": "2019-09-01",
"OkresDataDoTekst": "2020-01-29",
"IdJednostkaSprawozdawcza": 6,
"JednostkaSprawozdawczaSkrot": "Fake123456",
"JednostkaSprawozdawczaNazwa": "Fakelog public diary nr 1",
"JednostkaSprawozdawczaSymbol": "123456",
"IdJednostka": 0,
"JednostkaNazwa": "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf",
"JednostkaSkrot": "Fake123456",
"OddzialSymbol": "A",
"OddzialKod": "4A",
"UzytkownikRola": "uczeń",
"UzytkownikLogin": "jan@fakelog.cf",
"UzytkownikLoginId": 1,
"UzytkownikNazwa": "Jan Kowalski",
"Id": 1,
"IdOddzial": 1,
"Imie": "Jan",
"Imie2": "Marek",
"Nazwisko": "Kowalski",
"Pseudonim": "",
"UczenPlec": 1,
"Pozycja": 0,
"LoginId": null
}
]
}

View file

@ -1,72 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579185018,
"TimeValue": "Thu, 16 Jan 2020 14:30:18 GMT",
"RequestId": "1799be6b-7a60-4665-b75c-1bca504e8ebd",
"DayOfWeek": 4,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"IdOkresKlasyfikacyjny": 12,
"OkresPoziom": 4,
"OkresNumer": 2,
"OkresDataOd": 1580342400,
"OkresDataDo": 1598832000,
"OkresDataOdTekst": "2020-01-30",
"OkresDataDoTekst": "2020-08-31",
"IdJednostkaSprawozdawcza": 6,
"JednostkaSprawozdawczaSkrot": "Fake123456",
"JednostkaSprawozdawczaNazwa": "Fakelog public diary nr 1",
"JednostkaSprawozdawczaSymbol": "123456",
"IdJednostka": 0,
"JednostkaNazwa": "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf",
"JednostkaSkrot": "Fake123456",
"OddzialSymbol": "A",
"OddzialKod": "4A",
"UzytkownikRola": "uczeń",
"UzytkownikLogin": "jan@fakelog.cf",
"UzytkownikLoginId": 2,
"UzytkownikNazwa": "Joanna Czerwińska",
"Id": 2,
"IdOddzial": 2,
"Imie": "Joanna",
"Imie2": "Maria",
"Nazwisko": "Czerwińska",
"Pseudonim": "",
"UczenPlec": 0,
"Pozycja": 0,
"LoginId": null
},
{
"IdOkresKlasyfikacyjny": 12,
"OkresPoziom": 4,
"OkresNumer": 2,
"OkresDataOd": 1580342400,
"OkresDataDo": 1598832000,
"OkresDataOdTekst": "2020-01-30",
"OkresDataDoTekst": "2020-08-31",
"IdJednostkaSprawozdawcza": 6,
"JednostkaSprawozdawczaSkrot": "Fake123456",
"JednostkaSprawozdawczaNazwa": "Fakelog public diary nr 1",
"JednostkaSprawozdawczaSymbol": "123456",
"IdJednostka": 0,
"JednostkaNazwa": "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf",
"JednostkaSkrot": "Fake123456",
"OddzialSymbol": "A",
"OddzialKod": "4A",
"UzytkownikRola": "uczeń",
"UzytkownikLogin": "jan@fakelog.cf",
"UzytkownikLoginId": 1,
"UzytkownikNazwa": "Jan Kowalski",
"Id": 1,
"IdOddzial": 1,
"Imie": "Jan",
"Imie2": "Marek",
"Nazwisko": "Kowalski",
"Pseudonim": "",
"UczenPlec": 1,
"Pozycja": 0,
"LoginId": null
}
]
}

View file

@ -1,14 +0,0 @@
3S1,https://lekcjaplus.vulcan.net.pl
TA1,https://uonetplus-komunikacja.umt.tarnow.pl
OP1,https://uonetplus-komunikacja.eszkola.opolskie.pl
RZ1,https://uonetplus-komunikacja.resman.pl
GD1,https://uonetplus-komunikacja.edu.gdansk.pl
KA1,https://uonetplus-komunikacja.mcuw.katowice.eu
KA2,https://uonetplus-komunikacja-test.mcuw.katowice.eu
LU1,https://uonetplus-komunikacja.edu.lublin.eu
LU2,https://test-uonetplus-komunikacja.edu.lublin.eu
P03,https://efeb-komunikacja-pro-efebmobile.pro.vulcan.pl
P01,http://efeb-komunikacja.pro-hudson.win.vulcan.pl
P02,http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl
P90,http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl
KO1,https://uonetplus-komunikacja.eduportal.koszalin.pl

View file

@ -1,105 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1581205518,
"TimeValue": "Sat, 08 Feb 2020 23:45:17 GMT",
"RequestId": "8f8b7d7f-cd4b-4fa5-b662-c5be2a82af54",
"DayOfWeek": 6,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 1,
"IdPoraLekcji": 76,
"IdPrzedmiot": 308,
"PrzedmiotNazwa": "Fizyka",
"PodzialSkrot": null,
"Sala": "213",
"IdPracownik": 1,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": null,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 23,
"AdnotacjaOZmianie": "",
"PrzekreslonaNazwa": false,
"PogrubionaNazwa": false,
"PlanUcznia": true
},
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 2,
"IdPoraLekcji": 77,
"IdPrzedmiot": 300,
"PrzedmiotNazwa": "Sieci komputerowe",
"PodzialSkrot": "t.infor",
"Sala": "G1",
"IdPracownik": 4,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": null,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 4,
"AdnotacjaOZmianie": "(przeniesiona z lekcji 1, 10.02.2020)",
"PrzekreslonaNazwa": false,
"PogrubionaNazwa": true,
"PlanUcznia": true
},
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 2,
"IdPoraLekcji": 77,
"IdPrzedmiot": 499,
"PrzedmiotNazwa": "Wychowanie fizyczne",
"PodzialSkrot": "wf_grupa_2",
"Sala": "S4",
"IdPracownik": 7,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": 5,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 46,
"AdnotacjaOZmianie": "(zastępstwo: Anon Gałecki, sala S4)",
"PrzekreslonaNazwa": true,
"PogrubionaNazwa": false,
"PlanUcznia": true
},
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 3,
"IdPoraLekcji": 78,
"IdPrzedmiot": 499,
"PrzedmiotNazwa": "Wychowanie fizyczne",
"PodzialSkrot": "wf_grupa_2",
"Sala": "S4",
"IdPracownik": 7,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": 5,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 47,
"AdnotacjaOZmianie": "(zastępstwo: Anon Gałecki, sala S4)",
"PrzekreslonaNazwa": false,
"PogrubionaNazwa": false,
"PlanUcznia": true
},
{
"Dzien": 1582239600,
"DzienTekst": "2020-02-03",
"NumerLekcji": 4,
"IdPoraLekcji": 79,
"IdPrzedmiot": 311,
"PrzedmiotNazwa": "Geografia",
"PodzialSkrot": null,
"Sala": "A215",
"IdPracownik": 10,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": 5,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 42,
"AdnotacjaOZmianie": "(nieobecny oddział - Zwiedzanie Muzeum II Wojny Światowej w Gdańsku.)",
"PrzekreslonaNazwa": true,
"PogrubionaNazwa": false,
"PlanUcznia": true
}
]
}

View file

@ -13,7 +13,7 @@ open class BaseTest {
return LocalDateTime.of(year, month, day, hour, minute, second)
}
fun getDate(year: Int, month: Int, day: Int, hour: Int = 0, minute: Int = 0, second: Int = 0, mili: Int = 0): LocalDateTime {
fun getDate(year: Int, month: Int, day: Int, hour: Int = 0, minute: Int = 0, second: Int = 0): LocalDateTime {
return LocalDateTime.of(year, month, day, hour, minute, second)
}
}

View file

@ -4,17 +4,5 @@ plugins {
}
dependencies {
implementation project(":sdk-mobile")
implementation project(":sdk-scrapper")
testImplementation files(this.project(':sdk-mobile').sourceSets.test.output)
testImplementation files(this.project(':sdk-mobile').sourceSets.test.runtimeClasspath)
}
sourceSets {
test {
resources {
srcDir '../sdk-mobile/src/test/resources'
}
}
}

View file

@ -1,6 +1,5 @@
package io.github.wulkanowy.sdk
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
import io.github.wulkanowy.sdk.mapper.mapAttendance
import io.github.wulkanowy.sdk.mapper.mapAttendanceSummary
import io.github.wulkanowy.sdk.mapper.mapCompletedLessons
@ -8,13 +7,10 @@ import io.github.wulkanowy.sdk.mapper.mapConferences
import io.github.wulkanowy.sdk.mapper.mapDevices
import io.github.wulkanowy.sdk.mapper.mapDirectorInformation
import io.github.wulkanowy.sdk.mapper.mapExams
import io.github.wulkanowy.sdk.mapper.mapFromRecipientsToMobile
import io.github.wulkanowy.sdk.mapper.mapGradePointsStatistics
import io.github.wulkanowy.sdk.mapper.mapGradeStatistics
import io.github.wulkanowy.sdk.mapper.mapGrades
import io.github.wulkanowy.sdk.mapper.mapGradesDetails
import io.github.wulkanowy.sdk.mapper.mapGradesSemesterStatistics
import io.github.wulkanowy.sdk.mapper.mapGradesSummary
import io.github.wulkanowy.sdk.mapper.mapHomework
import io.github.wulkanowy.sdk.mapper.mapLuckyNumbers
import io.github.wulkanowy.sdk.mapper.mapMailboxes
@ -33,7 +29,6 @@ import io.github.wulkanowy.sdk.mapper.mapTimetableFull
import io.github.wulkanowy.sdk.mapper.mapToScrapperAbsent
import io.github.wulkanowy.sdk.mapper.mapToUnits
import io.github.wulkanowy.sdk.mapper.mapToken
import io.github.wulkanowy.sdk.mobile.Mobile
import io.github.wulkanowy.sdk.pojo.Absent
import io.github.wulkanowy.sdk.pojo.Attendance
import io.github.wulkanowy.sdk.pojo.AttendanceSummary
@ -73,13 +68,11 @@ import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import org.slf4j.LoggerFactory
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
class Sdk {
enum class Mode {
API,
SCRAPPER,
HYBRID,
}
@ -94,32 +87,12 @@ class Sdk {
ADFSLightCufs,
}
private val mobile = Mobile()
private val scrapper = Scrapper()
private val registerTimeZone = ZoneId.of("Europe/Warsaw")
var mode = Mode.HYBRID
var mobileBaseUrl = ""
set(value) {
field = value
mobile.baseUrl = value
}
var certKey = ""
set(value) {
field = value
mobile.certKey = value
}
var privateKey = ""
set(value) {
field = value
mobile.privateKey = privateKey
}
var scrapperBaseUrl = ""
set(value) {
field = value
@ -142,27 +115,18 @@ class Sdk {
set(value) {
field = value
scrapper.schoolSymbol = value
mobile.schoolSymbol = value
}
var classId = 0
set(value) {
field = value
scrapper.classId = value
mobile.classId = value
}
var studentId = 0
set(value) {
field = value
scrapper.studentId = value
mobile.studentId = value
}
var loginId = 0
set(value) {
field = value
mobile.loginId = value
}
var diaryId = 0
@ -199,7 +163,6 @@ class Sdk {
set(value) {
field = value
scrapper.logLevel = value
mobile.logLevel = value
}
var userAgentTemplate = ""
@ -243,7 +206,6 @@ class Sdk {
fun addInterceptor(interceptor: Interceptor, network: Boolean = false) {
scrapper.addInterceptor(interceptor, network)
mobile.setInterceptor(interceptor, network)
interceptors.add(interceptor to network)
}
@ -263,10 +225,6 @@ class Sdk {
scrapper.sendPasswordResetRequest(registerBaseUrl, symbol, email, captchaCode)
}
suspend fun getStudentsFromMobileApi(token: String, pin: String, symbol: String, firebaseToken: String, apiKey: String = ""): List<Student> = withContext(Dispatchers.IO) {
mobile.getStudents(mobile.getCertificate(token, pin, symbol, buildTag, androidVersion, firebaseToken), apiKey).mapStudents(symbol)
}
suspend fun getStudentsFromScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String = "Default"): List<Student> = withContext(Dispatchers.IO) {
scrapper.let {
it.baseUrl = scrapperBaseUrl
@ -287,197 +245,135 @@ class Sdk {
}
}
suspend fun getStudentsHybrid(
email: String,
password: String,
scrapperBaseUrl: String,
firebaseToken: String,
startSymbol: String = "Default",
apiKey: String = "",
) = withContext(Dispatchers.IO) {
getStudentsFromScrapper(email, password, scrapperBaseUrl, startSymbol)
.distinctBy { it.symbol }
.map { scrapperStudent ->
scrapper.let {
it.symbol = scrapperStudent.symbol
it.schoolSymbol = scrapperStudent.schoolSymbol
it.studentId = scrapperStudent.studentId
it.diaryId = -1
it.classId = scrapperStudent.classId
it.loginType = Scrapper.LoginType.valueOf(scrapperStudent.loginType.name)
}
val token = scrapper.getToken()
getStudentsFromMobileApi(token.token, token.pin, token.symbol, firebaseToken, apiKey).map { student ->
student.copy(
loginMode = Mode.HYBRID,
loginType = scrapperStudent.loginType,
scrapperBaseUrl = scrapperStudent.scrapperBaseUrl,
)
}
}.toList().flatten()
}
suspend fun getSemesters(): List<Semester> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSemesters().mapSemesters()
Mode.API -> mobile.getStudents().mapSemesters(studentId)
}
}
suspend fun getAttendance(startDate: LocalDate, endDate: LocalDate, semesterId: Int): List<Attendance> = withContext(Dispatchers.IO) {
suspend fun getAttendance(startDate: LocalDate, endDate: LocalDate): List<Attendance> = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.getAttendance(startDate, endDate).mapAttendance()
Mode.HYBRID, Mode.API -> mobile.getAttendance(startDate, endDate, semesterId).mapAttendance(mobile.getDictionaries())
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getAttendance(startDate, endDate).mapAttendance()
}
}
suspend fun getAttendanceSummary(subjectId: Int? = -1): List<AttendanceSummary> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getAttendanceSummary(subjectId).mapAttendanceSummary()
Mode.API -> throw FeatureNotAvailableException("Attendance summary is not available in API mode")
}
}
suspend fun excuseForAbsence(absents: List<Absent>, content: String? = null): Boolean = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.excuseForAbsence(absents.mapToScrapperAbsent(), content)
Mode.API -> throw FeatureNotAvailableException("Absence excusing is not available in API mode")
}
}
suspend fun getSubjects(): List<Subject> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSubjects().mapSubjects()
Mode.API -> mobile.getDictionaries().subjects.mapSubjects()
}
}
suspend fun getExams(start: LocalDate, end: LocalDate, semesterId: Int): List<Exam> = withContext(Dispatchers.IO) {
suspend fun getExams(start: LocalDate, end: LocalDate): List<Exam> = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.getExams(start, end).mapExams()
Mode.HYBRID, Mode.API -> mobile.getExams(start, end, semesterId).mapExams(mobile.getDictionaries())
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getExams(start, end).mapExams()
}
}
suspend fun getGrades(semesterId: Int): Grades = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGrades(semesterId).mapGrades()
Mode.API -> mobile.getGrades(semesterId).let { (grades, summaries) ->
val dict = mobile.getDictionaries()
Grades(
details = grades.mapGradesDetails(dict),
summary = summaries.mapGradesSummary(dict),
isAverage = false,
isPoints = false,
isForAdults = false,
type = 0,
)
}
}
}
suspend fun getGradesSemesterStatistics(semesterId: Int): List<GradeStatisticsSemester> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGradesSemesterStatistics(semesterId).mapGradesSemesterStatistics()
Mode.API -> throw FeatureNotAvailableException("Class grades annual statistics is not available in API mode")
}
}
suspend fun getGradesPartialStatistics(semesterId: Int): List<GradeStatisticsSubject> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGradesPartialStatistics(semesterId).mapGradeStatistics()
Mode.API -> throw FeatureNotAvailableException("Class grades partial statistics is not available in API mode")
}
}
suspend fun getGradesPointsStatistics(semesterId: Int): List<GradePointsStatistics> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getGradesPointsStatistics(semesterId).mapGradePointsStatistics()
Mode.API -> throw FeatureNotAvailableException("Class grades points statistics is not available in API mode")
}
}
suspend fun getHomework(start: LocalDate, end: LocalDate, semesterId: Int = 0): List<Homework> = withContext(Dispatchers.IO) {
suspend fun getHomework(start: LocalDate, end: LocalDate): List<Homework> = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.getHomework(start, end).mapHomework()
Mode.HYBRID, Mode.API -> mobile.getHomework(start, end, semesterId).mapHomework(mobile.getDictionaries())
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getHomework(start, end).mapHomework()
}
}
suspend fun getNotes(semesterId: Int): List<Note> = withContext(Dispatchers.IO) {
suspend fun getNotes(): List<Note> = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.getNotes().mapNotes()
Mode.HYBRID, Mode.API -> mobile.getNotes(semesterId).mapNotes(mobile.getDictionaries())
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getNotes().mapNotes()
}
}
suspend fun getConferences(): List<Conference> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getConferences().mapConferences(registerTimeZone)
Mode.API -> throw FeatureNotAvailableException("Conferences is not available in API mode")
}
}
suspend fun getRegisteredDevices(): List<Device> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getRegisteredDevices().mapDevices(registerTimeZone)
Mode.API -> throw FeatureNotAvailableException("Devices management is not available in API mode")
}
}
suspend fun getToken(): Token = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getToken().mapToken()
Mode.API -> throw FeatureNotAvailableException("Devices management is not available in API mode")
}
}
suspend fun unregisterDevice(id: Int): Boolean = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.unregisterDevice(id)
Mode.API -> throw FeatureNotAvailableException("Devices management is not available in API mode")
}
}
suspend fun getTeachers(semesterId: Int): List<Teacher> = withContext(Dispatchers.IO) {
suspend fun getTeachers(): List<Teacher> = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.getTeachers().mapTeachers()
Mode.HYBRID, Mode.API -> mobile.getTeachers(studentId, semesterId).mapTeachers(mobile.getDictionaries())
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getTeachers().mapTeachers()
}
}
suspend fun getSchool(): School = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSchool().mapSchool()
Mode.API -> throw FeatureNotAvailableException("School info is not available in API mode")
}
}
suspend fun getStudentInfo(): StudentInfo = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentInfo().mapStudent()
Mode.API -> throw FeatureNotAvailableException("Student info is not available in API mode")
}
}
suspend fun getStudentPhoto(): StudentPhoto = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentPhoto().mapPhoto()
Mode.API -> throw FeatureNotAvailableException("Student photo is not available in API mode")
}
}
suspend fun getMailboxes(): List<Mailbox> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getMailboxes().mapMailboxes()
Mode.API -> TODO()
}
}
suspend fun getRecipients(mailboxKey: String): List<Recipient> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getRecipients(mailboxKey).mapRecipients()
Mode.API -> mobile.getDictionaries().teachers.mapRecipients(-1)
}
}
@ -492,68 +388,54 @@ class Sdk {
suspend fun getReceivedMessages(mailboxKey: String? = null): List<Message> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getReceivedMessages(mailboxKey).mapMessages(registerTimeZone, Folder.RECEIVED)
Mode.API -> mobile.getMessages(LocalDateTime.now(), LocalDateTime.now()).mapMessages(registerTimeZone)
}
}
suspend fun getSentMessages(mailboxKey: String? = null): List<Message> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSentMessages(mailboxKey).mapMessages(registerTimeZone, Folder.SENT)
Mode.API -> mobile.getMessagesSent(LocalDateTime.now(), LocalDateTime.now()).mapMessages(registerTimeZone)
}
}
suspend fun getDeletedMessages(mailboxKey: String? = null): List<Message> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getDeletedMessages(mailboxKey).mapMessages(registerTimeZone, Folder.TRASHED)
Mode.API -> mobile.getMessagesDeleted(LocalDateTime.now(), LocalDateTime.now()).mapMessages(registerTimeZone)
}
}
suspend fun getMessageReplayDetails(messageKey: String): MessageReplayDetails = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getMessageReplayDetails(messageKey).mapScrapperMessage()
Mode.API -> TODO()
}
}
suspend fun getMessageDetails(messageKey: String, markAsRead: Boolean = true): MessageDetails = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getMessageDetails(messageKey, markAsRead).mapScrapperMessage()
Mode.API -> {
mobile.changeMessageStatus(messageKey, "", "Widoczna")
TODO()
}
}
}
suspend fun sendMessage(subject: String, content: String, recipients: List<Recipient>, mailboxId: String) = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.sendMessage(subject, content, recipients.map { it.mailboxGlobalKey }, mailboxId)
Mode.API -> mobile.sendMessage(subject, content, recipients.mapFromRecipientsToMobile())
}
}
suspend fun deleteMessages(messages: List<String>, removeForever: Boolean = false) = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.deleteMessages(messages, removeForever)
Mode.HYBRID, Mode.API -> messages.map { messageId ->
mobile.changeMessageStatus(messageId, "", "Usunieta")
}
Mode.HYBRID, Mode.SCRAPPER -> scrapper.deleteMessages(messages, removeForever)
}
}
suspend fun getTimetable(start: LocalDate, end: LocalDate): Timetable = withContext(Dispatchers.IO) {
when (mode) {
Mode.SCRAPPER -> scrapper.getTimetable(start, end).mapTimetableFull(registerTimeZone)
Mode.HYBRID, Mode.API -> mobile.getTimetable(start, end, 0).mapTimetableFull(mobile.getDictionaries(), registerTimeZone)
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getTimetable(start, end).mapTimetableFull(registerTimeZone)
}
}
suspend fun getCompletedLessons(start: LocalDate, end: LocalDate? = null, subjectId: Int = -1): List<CompletedLesson> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getCompletedLessons(start, end, subjectId).mapCompletedLessons()
Mode.API -> throw FeatureNotAvailableException("Completed lessons are not available in API mode")
}
}
@ -582,77 +464,66 @@ class Sdk {
suspend fun getDirectorInformation(): List<DirectorInformation> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getDirectorInformation().mapDirectorInformation()
Mode.API -> throw FeatureNotAvailableException("Director information is not available in API mode")
}
}
suspend fun getSelfGovernments(): List<GovernmentUnit> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getSelfGovernments().mapToUnits()
Mode.API -> throw FeatureNotAvailableException("Self governments is not available in API mode")
}
}
suspend fun getStudentThreats(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentThreats()
Mode.API -> throw FeatureNotAvailableException("Student threats are not available in API mode")
}
}
suspend fun getStudentsTrips(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getStudentsTrips()
Mode.API -> throw FeatureNotAvailableException("Students trips is not available in API mode")
}
}
suspend fun getLastGrades(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastGrades()
Mode.API -> throw FeatureNotAvailableException("Last grades is not available in API mode")
}
}
suspend fun getFreeDays(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getFreeDays()
Mode.API -> throw FeatureNotAvailableException("Free days is not available in API mode")
}
}
suspend fun getKidsLuckyNumbers(): List<LuckyNumber> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getKidsLuckyNumbers().mapLuckyNumbers()
Mode.API -> throw FeatureNotAvailableException("Kids Lucky number is not available in API mode")
}
}
suspend fun getKidsTimetable(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getKidsLessonPlan()
Mode.API -> throw FeatureNotAvailableException("Kids timetable is not available in API mode")
}
}
suspend fun getLastHomework(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastHomework()
Mode.API -> throw FeatureNotAvailableException("Last homework is not available in API mode")
}
}
suspend fun getLastExams(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastTests()
Mode.API -> throw FeatureNotAvailableException("Last exams is not available in API mode")
}
}
suspend fun getLastStudentLessons(): List<String> = withContext(Dispatchers.IO) {
when (mode) {
Mode.HYBRID, Mode.SCRAPPER -> scrapper.getLastStudentLessons()
Mode.API -> throw FeatureNotAvailableException("Last student lesson is not available in API mode")
}
}
}

View file

@ -1,6 +1,5 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.pojo.Absent
import io.github.wulkanowy.sdk.pojo.Attendance
import io.github.wulkanowy.sdk.pojo.AttendanceSummary
@ -11,34 +10,10 @@ import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory.EXCUSED_LA
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory.EXEMPTION
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory.PRESENCE
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory.UNEXCUSED_LATENESS
import io.github.wulkanowy.sdk.scrapper.capitalise
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.sdk.mobile.attendance.Attendance as ApiAttendance
import io.github.wulkanowy.sdk.scrapper.attendance.Absent as ScrapperAbsent
import io.github.wulkanowy.sdk.scrapper.attendance.Attendance as ScrapperAttendance
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceSummary as ScrapperAttendanceSummary
fun List<ApiAttendance>.mapAttendance(dictionaries: Dictionaries) = map {
val category = dictionaries.attendanceCategories.singleOrNull { cat -> cat.id == it.categoryId }
Attendance(
number = it.number,
name = category?.name?.capitalise() ?: "Nieznany",
subject = it.subjectName,
date = it.date.toLocalDate(),
timeId = -1,
absence = category?.absence ?: false,
categoryId = it.categoryId,
presence = category?.presence ?: false,
lateness = category?.lateness ?: false,
exemption = category?.exemption ?: false,
excused = category?.excused ?: false,
excusable = false, //
deleted = category?.deleted ?: false,
excuseStatus = null,
)
}
fun List<ScrapperAttendance>.mapAttendance() = map {
Attendance(
number = it.number,

View file

@ -1,28 +1,8 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.pojo.Exam
import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.sdk.mobile.exams.Exam as ApiExam
import io.github.wulkanowy.sdk.scrapper.exams.Exam as ScrapperExam
fun List<ApiExam>.mapExams(dict: Dictionaries) = map { exam ->
Exam(
date = exam.date.toLocalDate(),
entryDate = exam.date.toLocalDate(),
description = exam.description,
teacher = dict.teachers.singleOrNull { it.id == exam.employeeId }?.run { "$name $surname" }.orEmpty(),
subject = dict.subjects.singleOrNull { it.id == exam.subjectId }?.name.orEmpty(),
teacherSymbol = dict.teachers.singleOrNull { it.id == exam.employeeId }?.code.orEmpty(),
type = when (exam.typeNumber) {
1 -> "Sprawdzian"
2 -> "Kartkówka"
3 -> "Praca klasowa"
else -> "Nieznany"
},
)
}
fun List<ScrapperExam>.mapExams() = map {
Exam(
date = it.date.toLocalDate(),

View file

@ -1,34 +1,12 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.pojo.Grade
import io.github.wulkanowy.sdk.pojo.GradeSummary
import io.github.wulkanowy.sdk.pojo.Grades
import io.github.wulkanowy.sdk.scrapper.grades.isGradeValid
import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.sdk.mobile.grades.Grade as ApiGrade
import io.github.wulkanowy.sdk.scrapper.grades.Grade as ScrapperGrade
import io.github.wulkanowy.sdk.scrapper.grades.GradeSummary as ScrapperGradeSummary
import io.github.wulkanowy.sdk.scrapper.grades.Grades as ScrapperGrades
fun List<ApiGrade>.mapGradesDetails(dict: Dictionaries) = map { grade ->
Grade(
subject = dict.subjects.singleOrNull { it.id == grade.subjectId }?.name.orEmpty(),
description = grade.description,
symbol = dict.gradeCategories.singleOrNull { it.id == grade.categoryId }?.code.orEmpty(),
comment = grade.comment.orEmpty(),
date = grade.creationDate.toLocalDate(),
teacher = dict.teachers.singleOrNull { it.id == grade.employeeIdD }?.let { "${it.name} ${it.surname}" }.orEmpty(),
entry = grade.entry.ifBlank { "..." },
weightValue = if (isGradeValid(grade.entry)) grade.gradeWeight else .0,
modifier = grade.modificationWeight ?: .0,
value = grade.value,
weight = grade.weight,
color = "0",
)
}
fun List<ScrapperGrade>.mapGradesDetails() = map {
Grade(
subject = it.subject,
@ -46,21 +24,6 @@ fun List<ScrapperGrade>.mapGradesDetails() = map {
)
}
fun GradesSummaryResponse.mapGradesSummary(dict: Dictionaries) = average
.union(predicted)
.union(evaluative)
.map { it.subjectId }.distinct().sorted().map { subjectId ->
GradeSummary(
name = dict.subjects.singleOrNull { it.id == subjectId }?.name.orEmpty(),
predicted = predicted.singleOrNull { it.subjectId == subjectId }?.entry.orEmpty(),
final = evaluative.singleOrNull { it.subjectId == subjectId }?.entry.orEmpty(),
average = (average.singleOrNull { it.subjectId == subjectId }?.average ?: "0").replace(",", ".").takeIf { it.isNotBlank() }?.toDouble() ?: 0.0,
pointsSum = average.singleOrNull { it.subjectId == subjectId }?.pointsSum.orEmpty(),
proposedPoints = "",
finalPoints = "",
)
}
fun List<ScrapperGradeSummary>.mapGradesSummary() = map {
GradeSummary(
name = it.name,
@ -81,7 +44,3 @@ fun ScrapperGrades.mapGrades() = Grades(
isForAdults = isForAdults,
type = type,
)
fun Pair<List<ScrapperGrade>, List<ScrapperGradeSummary>>.mapGrades() = first.mapGradesDetails() to second.mapGradesSummary()
fun Pair<List<ApiGrade>, GradesSummaryResponse>.mapGrades(dict: Dictionaries) = first.mapGradesDetails(dict) to second.mapGradesSummary(dict)

View file

@ -1,26 +1,9 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.pojo.Homework
import io.github.wulkanowy.sdk.pojo.HomeworkAttachment
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.sdk.mobile.homework.Homework as ApiHomework
import io.github.wulkanowy.sdk.scrapper.homework.Homework as ScrapperHomework
fun List<ApiHomework>.mapHomework(dictionaries: Dictionaries) = map {
val employee = dictionaries.employees.singleOrNull { employee -> employee.id == it.employeeId }
Homework(
date = it.date.toLocalDate(),
entryDate = it.date.toLocalDate(),
subject = dictionaries.subjects.singleOrNull { subject -> subject.id == it.subjectId }?.name.orEmpty(),
content = it.content,
teacherSymbol = employee?.code.orEmpty(),
teacher = employee?.run { "$name $surname" }.orEmpty(),
attachments = emptyList(),
)
}
fun List<ScrapperHomework>.mapHomework() = map {
Homework(
date = it.date.toLocalDate(),

View file

@ -1,41 +1,15 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.normalizeRecipient
import io.github.wulkanowy.sdk.pojo.Folder
import io.github.wulkanowy.sdk.pojo.Message
import io.github.wulkanowy.sdk.pojo.MessageAttachment
import io.github.wulkanowy.sdk.pojo.MessageDetails
import io.github.wulkanowy.sdk.pojo.MessageReplayDetails
import io.github.wulkanowy.sdk.toLocalDateTime
import java.time.ZoneId
import io.github.wulkanowy.sdk.mobile.messages.Message as ApiMessage
import io.github.wulkanowy.sdk.scrapper.messages.MessageDetails as ScrapperDetailsMessage
import io.github.wulkanowy.sdk.scrapper.messages.MessageMeta as ScrapperMessageMeta
import io.github.wulkanowy.sdk.scrapper.messages.MessageReplayDetails as ScrapperReplayDetailsMessage
@JvmName("mapApiMessages")
fun List<ApiMessage>.mapMessages(zoneId: ZoneId) = map {
Message(
globalKey = it.messageId.toString(),
id = it.messageId,
readBy = it.read?.toInt(),
unreadBy = it.unread?.toInt(),
unread = it.folder == "Odebrane" && it.readDateTime == null,
recipients = it.recipients?.map { recipient -> recipient.copy(name = recipient.name.normalizeRecipient()) }?.mapFromMobileToRecipients().orEmpty(),
correspondents = "",
mailbox = "",
folderId = when (it.folder) {
"Odebrane" -> 1
"Wyslane" -> 2
else -> 1
},
content = it.content,
date = it.sentDateTime.toLocalDateTime().atZone(zoneId),
subject = it.subject,
hasAttachments = false,
)
}
fun List<ScrapperMessageMeta>.mapMessages(zoneId: ZoneId, folderId: Folder) = map {
Message(
globalKey = it.apiGlobalKey,

View file

@ -1,26 +1,9 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.pojo.Note
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.sdk.mobile.notes.Note as ApiNote
import io.github.wulkanowy.sdk.scrapper.notes.Note as ScrapperNote
fun List<ApiNote>.mapNotes(dictionaries: Dictionaries) = map {
Note(
date = it.entryDate.toLocalDate(),
content = it.content,
teacherSymbol = dictionaries.teachers.singleOrNull { teacher -> teacher.id == it.employeeId }?.code.orEmpty(),
teacher = "${it.employeeName} ${it.employeeSurname}",
category = dictionaries.noteCategories.singleOrNull { cat -> cat.id == it.noteCategoryId }?.name.orEmpty(),
categoryType = NoteCategory.UNKNOWN,
showPoints = false,
points = 0,
)
}
fun List<ScrapperNote>.mapNotes() = map {
Note(
date = it.date.toLocalDate(),

View file

@ -1,9 +1,7 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Teacher
import io.github.wulkanowy.sdk.pojo.MailboxType
import io.github.wulkanowy.sdk.pojo.Recipient
import io.github.wulkanowy.sdk.mobile.messages.Recipient as MobileRecipient
import io.github.wulkanowy.sdk.scrapper.messages.Recipient as ScrapperRecipient
fun List<ScrapperRecipient>.mapRecipients() = map {
@ -18,32 +16,3 @@ fun ScrapperRecipient.mapToRecipient() = Recipient(
schoolNameShort = schoolNameShort,
type = MailboxType.fromLetter(type.letter),
)
fun List<Recipient>.mapFromRecipientsToMobile() = map {
MobileRecipient(
loginId = it.mailboxGlobalKey.toInt(),
name = it.userName,
)
}
fun List<MobileRecipient>.mapFromMobileToRecipients() = map {
Recipient(
mailboxGlobalKey = it.loginId.toString(),
fullName = it.name,
userName = it.name,
studentName = "",
schoolNameShort = "",
type = MailboxType.UNKNOWN,
)
}
fun List<Teacher>.mapRecipients(reportingUnitId: Int) = map {
Recipient(
mailboxGlobalKey = reportingUnitId.toString(),
fullName = "${it.name} ${it.surname}",
userName = "${it.name} ${it.surname}",
studentName = "",
schoolNameShort = "",
type = MailboxType.UNKNOWN,
)
}

View file

@ -1,11 +1,6 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.exception.VulcanException
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.pojo.Semester
import io.github.wulkanowy.sdk.toLocalDate
import java.time.LocalDate.of
import java.time.Month
import io.github.wulkanowy.sdk.scrapper.register.Semester as ScrapperSemester
@JvmName("mapScrapperSemesters")
@ -23,30 +18,3 @@ fun List<ScrapperSemester>.mapSemesters() = map {
unitId = it.unitId,
)
}
fun List<Student>.mapSemesters(studentId: Int) = filter { it.id == studentId }.map {
Semester(
diaryId = 0,
kindergartenDiaryId = 0,
diaryName = it.classSymbol,
schoolYear = it.periodDateFrom.toLocalDate().let { start -> if (start.month == Month.SEPTEMBER) start.year else start.year - 1 },
semesterId = it.classificationPeriodId,
semesterNumber = it.periodNumber,
start = it.periodDateFrom.toLocalDate(),
end = it.periodDateTo.toLocalDate(),
classId = it.classId,
unitId = it.reportingUnitId,
)
}.mockSecondSemester()
private fun List<Semester>.mockSecondSemester(): List<Semester> {
if (size != 1) throw VulcanException("Expected semester list size 1, get $size")
val semester = single()
val secondSemester = semester.copy(
semesterNumber = if (semester.semesterNumber == 1) 2 else 1,
semesterId = if (semester.semesterNumber == 1) semester.semesterId + 1 else semester.semesterId - 1,
start = if (semester.semesterNumber == 1) semester.end.plusDays(1) else of(semester.schoolYear, 9, 1),
end = if (semester.semesterNumber == 1) of(semester.schoolYear + 1, 8, 31) else semester.start.minusDays(1),
)
return (this + secondSemester)
}

View file

@ -4,7 +4,6 @@ import io.github.wulkanowy.sdk.pojo.StudentGender
import io.github.wulkanowy.sdk.pojo.StudentGuardian
import io.github.wulkanowy.sdk.pojo.StudentInfo
import io.github.wulkanowy.sdk.pojo.StudentPhoto
import io.github.wulkanowy.sdk.scrapper.toLocalDate
import io.github.wulkanowy.sdk.scrapper.student.StudentGuardian as ScrapperStudentGuardian
import io.github.wulkanowy.sdk.scrapper.student.StudentInfo as ScrapperStudentInfo
import io.github.wulkanowy.sdk.scrapper.student.StudentPhoto as ScrapperStudentPhoto

View file

@ -2,35 +2,8 @@ package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Student
import io.github.wulkanowy.sdk.mobile.register.Student as ApiStudent
import io.github.wulkanowy.sdk.scrapper.register.Student as ScrapperStudent
fun List<ApiStudent>.mapStudents(symbol: String) = map {
Student(
email = it.userLogin,
userName = it.userName,
userLogin = it.userLogin,
userLoginId = it.userLoginId,
isParent = it.userRole != "uczeń",
symbol = symbol,
studentId = it.id,
classId = it.classId,
className = it.classCode.orEmpty(),
studentName = it.name,
studentSurname = it.surname,
schoolSymbol = it.reportingUnitSymbol,
schoolShortName = it.reportingUnitShortcut,
schoolName = it.reportingUnitName,
loginType = Sdk.ScrapperLoginType.STANDARD,
loginMode = Sdk.Mode.API,
scrapperBaseUrl = "",
mobileBaseUrl = it.mobileBaseUrl,
privateKey = it.privateKey,
certificateKey = it.certificateKey,
semesters = mapSemesters(it.id),
)
}
fun List<ScrapperStudent>.mapStudents() = map {
Student(
email = it.email,

View file

@ -1,17 +1,8 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.pojo.Subject
import io.github.wulkanowy.sdk.mobile.dictionaries.Subject as ApiSubject
import io.github.wulkanowy.sdk.scrapper.attendance.Subject as ScrapperSubject
@JvmName("mapApiSubjects")
fun List<ApiSubject>.mapSubjects() = listOf(Subject(-1, "Wszystkie")) + filter { it.active }.map {
Subject(
id = it.id,
name = it.name,
)
}
fun List<ScrapperSubject>.mapSubjects() = map {
Subject(
id = it.value,

View file

@ -1,20 +1,8 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.pojo.Teacher
import io.github.wulkanowy.sdk.mobile.school.Teacher as ApiTeacher
import io.github.wulkanowy.sdk.scrapper.school.Teacher as ScrapperTeacher
fun List<ApiTeacher>.mapTeachers(dictionaries: Dictionaries) = mapNotNull { teacher ->
val item = dictionaries.employees.singleOrNull { it.id == teacher.employeeId }
if (item?.name == null) return@mapNotNull null
Teacher(
name = "${item.name} ${item.surname}",
short = item.code,
subject = dictionaries.subjects.singleOrNull { it.id == teacher.subjectId }?.name ?: teacher.role,
)
}
fun List<ScrapperTeacher>.mapTeachers() = map {
Teacher(
name = it.name,

View file

@ -1,61 +1,16 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.pojo.CompletedLesson
import io.github.wulkanowy.sdk.pojo.Lesson
import io.github.wulkanowy.sdk.pojo.LessonAdditional
import io.github.wulkanowy.sdk.pojo.TimetableDayHeader
import io.github.wulkanowy.sdk.pojo.Timetable
import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.sdk.toLocalDateTime
import io.github.wulkanowy.sdk.pojo.TimetableDayHeader
import java.time.ZoneId
import io.github.wulkanowy.sdk.mobile.timetable.Lesson as ApiTimetable
import io.github.wulkanowy.sdk.scrapper.timetable.CompletedLesson as ScrapperCompletedLesson
import io.github.wulkanowy.sdk.scrapper.timetable.Lesson as ScrapperTimetable
import io.github.wulkanowy.sdk.scrapper.timetable.LessonAdditional as ScrapperTimetableAdditional
import io.github.wulkanowy.sdk.scrapper.timetable.TimetableDayHeader as ScrapperTimetableDayHeader
import io.github.wulkanowy.sdk.scrapper.timetable.Timetable as ScrapperTimetableFull
fun List<ApiTimetable>.mapTimetableFull(dictionaries: Dictionaries, zoneId: ZoneId) = Timetable(
headers = emptyList(),
lessons = mapTimetable(dictionaries, zoneId),
additional = emptyList(),
)
fun List<ApiTimetable>.mapTimetable(dictionaries: Dictionaries, zoneId: ZoneId) = map {
val teacher = dictionaries.employees.singleOrNull { employee -> employee.id == it.employeeId }
val teacherOld = dictionaries.employees.singleOrNull { employee -> employee.id == it.employeeOldId }
val time = dictionaries.lessonTimes.single { time -> time.id == it.lessonTimeId }
val startDateTime = "${it.dayText} ${time.startText}".toLocalDateTime("yyyy-MM-dd HH:mm")
val endDateTime = "${it.dayText} ${time.endText}".toLocalDateTime("yyyy-MM-dd HH:mm")
Lesson(
canceled = it.overriddenName,
changes = it.boldName || (!it.annotationAboutChange.isNullOrBlank() && !it.overriddenName),
date = it.day.toLocalDate(),
start = startDateTime.atZone(zoneId),
end = endDateTime.atZone(zoneId),
group = it.divisionShort.orEmpty(),
info = it.annotationAboutChange?.substringAfter("(")?.substringBefore(")").orEmpty(),
number = it.lessonNumber,
room = it.room.orEmpty(),
roomOld = "",
subject = it.subjectName,
subjectOld = "",
studentPlan = it.studentPlan,
teacher = teacher?.run { "$name $surname" }.orEmpty(),
teacherOld = teacherOld?.run { "$name $surname" }.orEmpty(),
)
}.groupBy { Triple(it.date, it.number, it.studentPlan) }.map { (_, lessons) ->
if (lessons.size > 1 && lessons.any { !it.canceled } && lessons.any { it.canceled }) {
val canceled = lessons.first { it.canceled }
val lesson = lessons.first { !it.canceled }.copy(
subjectOld = canceled.subject,
teacherOld = canceled.teacher,
roomOld = canceled.room,
)
listOf(lesson)
} else lessons
}.flatten()
import io.github.wulkanowy.sdk.scrapper.timetable.TimetableDayHeader as ScrapperTimetableDayHeader
fun ScrapperTimetableFull.mapTimetableFull(zoneId: ZoneId) = Timetable(
headers = headers.mapTimetableDayHeaders(),

View file

@ -1,13 +1,11 @@
package io.github.wulkanowy.sdk
import io.github.wulkanowy.sdk.pojo.Folder
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test
import java.time.LocalDate.of
@Ignore
@OptIn(ExperimentalCoroutinesApi::class)
@ -22,14 +20,6 @@ class SdkRemoteTest {
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCbF5Tt176EpB4cX5U+PZE0XytjJ9ABDZFaBFDkaexbkuNeuLOaARjQEOlUoBmpZQXxAF8HlYqeTvPiTcnSfQIS6EdqpICuQNdwvy6CHFAe2imkbbB0aHPsGep6zH8ZxHbssazkTCnGy0j2ZtGT2/iy1GEvc/p2bOkCVcR1H1GqFp+/XpfaMwi2SRCwc67K8Fu8TjSDKNvcRT9nuenGoPA1CWoOiOCxhQA6gnB8LULPel6TVDxeBVdYor/z2GxFe/m0pa7XAKzveuUDhH8k8NlNG65MjvZhgy9iFs+eBUq7lCZ0nuIsDzjnUrLSl4ciYKj9d94qrUyF8L8D9Rl+0WlAgMBAAECggEAQ6jg3rNmyxIg0rl0ZG/LjEF26RKR7P5KQLcpouESga3HfzHvsjMCq+OWZvciFhazRd4BQkdwZxGPnfa7ieGzmhtvs1pDu8zU/hE4UClV+EG6NpVpC2Q/sn5KZRijaZoY3eMGQUFatBzCBcLZxYspfbyR3ucLbu9DE+foNB1Fh4u9RCDj3bClTsqPcNBIaLMpYr3f/bM1fFbS9LrJ7AXZQtGg/2MH58WsvV67SiYAQqGCzld/Jp74gmod4Ii0w2XWZ7OeixdF2xr1j7TK0dUUlrrOrb1cgOWSOEXyy3RX/iF7R8uuLXiRfo1URh6VNPoOtrC6fHCrCp1iRBo08qOk4QKBgQDxqLrWA7gKcTr2yQeGfETXOAYi0xqbNj5A9eVC0XngxnFuwWc5zyg3Ps3c0UK2qTSSFv4SoeEHQM+U0+9LjYzIRSUH7zy4zBrBlLtTQCysSuuZ9QfgO55b3/QEYkyx6Hz/z/gg53jKHjsUKIftGMwJ6C1M2svbBNYCsWrUuYcsbQKBgQDN9gkVDABIeWUtKDHyB5HGcVbsg7Ji7GhMjdFA0GB+9kR0doKNctrzxKn65BI2uTWg+mxaw5V+UeJOIaeFsv2uClYJYn1F55VT7NIx3CLFv6zFRSiMSKz2W+NkwGjQqR7D3DeEyalpjeQeMdpHZg27LMbdVkzy/cK8EM9ZQlRLGQKBgQCpB2wn5dIE+85Sb6pj1ugP4Y/pK9+gUQCaT2RcqEingCY3Ye/h75QhkDxOB9CyEwhCZvKv9aqAeES5xMPMBOZD7plIQ34lhB3y6SVdxbV5ja3dshYgMZNCkBMOPfOHPSaxh7X2zfEe7qZEI1Vv8bhF9bA54ZBVUbyfhZlD0cFKwQKBgQC9BnXHb0BDQ8br7twH+ZJ8wkC4yRXLXJVMzUujZJtrarHhAXNIRoVU/MXUkcV1m/3wRGV119M4IAbHFnQdbO0N8kaMTmwS4DxYzh0LzbHMM+JpGtPgDENRx3unWD/aYZzuvQnnQP3O9n7Kh46BwNQRWUMamL3+tY8n83WZwhqC4QKBgBTUzHy0sEEZ3hYgwU2ygbzC0vPladw2KqtKy+0LdHtx5pqE4/pvhVMpRRTNBDiAvb5lZmMB/B3CzoiMQOwczuus8Xsx7bEci28DzQ+g2zt0/bC2Xl+992Ass5PP5NtOrP/9QiTNgoFSCrVnZnNzQqpjCrFsjfOD2fiuFLCD6zi6"
}
@Test
fun getStudents_api() {
val sdk = Sdk()
sdk.setSimpleHttpLogger { println(it) }
val students = runBlocking { sdk.getStudentsFromMobileApi(token = "FK100000", pin = "999999", symbol = "powiatwulkanowy", apiKey = API_KEY, firebaseToken = "") }
assertEquals(2, students.size)
}
@Test
fun getStudents_scrapper() {
val sdk = Sdk().apply {
@ -41,68 +31,9 @@ class SdkRemoteTest {
assertEquals(6, students.size)
}
@Test
fun getStudents_hybrid() {
val sdk = Sdk().apply {
// mode = Sdk.Mode.HYBRID
}
val students = runBlocking {
sdk.getStudentsHybrid(
email = "jan@fakelog.cf",
password = "jan123",
apiKey = API_KEY,
scrapperBaseUrl = "http://fakelog.cf",
startSymbol = "powiatwulkanowy",
firebaseToken = "",
)
}
assertEquals(6, students.size)
}
@Test
fun getSemesters_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 1
classId = 14
}
val semesters = runBlocking { sdk.getSemesters() }
assertEquals(2, semesters.size)
}
@Test
fun getGrades_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val grades = runBlocking { sdk.getGrades(1).details }
assertEquals(22, grades.size)
}
@Test
fun getGrades_scrapper() = runTest {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
userAgentTemplate = "custom UA %1\$s%2\$s%3\$s%4\$s"
mode = Sdk.Mode.SCRAPPER
symbol = "powiatwulkanowy"
@ -124,201 +55,4 @@ class SdkRemoteTest {
assertEquals(22, grades.size)
assertEquals(22, grades2.details.size)
}
@Test
fun getGradesSummary_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val grades = runBlocking { sdk.getGrades(1).summary }
assertEquals(4, grades.size)
}
@Test
fun getAttendance_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val attendance = runBlocking { sdk.getAttendance(of(2018, 1, 1), of(2018, 1, 2), 1) }
assertEquals(24, attendance.size)
}
@Test
fun getSubjects_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val subjects = runBlocking { sdk.getSubjects() }
assertEquals(14, subjects.size)
}
@Test
fun getNotes_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val notes = runBlocking { sdk.getNotes(1) }
assertEquals(5, notes.size)
}
@Test
fun getTeachers_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val teachers = runBlocking { sdk.getTeachers(1) }
assertEquals(9, teachers.size)
}
@Test
fun getHomework_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val homework = runBlocking { sdk.getHomework(of(2018, 1, 1), of(2018, 1, 2)) }
assertEquals(4, homework.size)
}
@Test
fun getTimetable_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val (timetable) = runBlocking { sdk.getTimetable(of(2018, 1, 1), of(2018, 1, 2)) }
assertEquals(24, timetable.size)
}
@Test
fun getMessages_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
studentId = 15
classId = 14
}
val messages = runBlocking { sdk.getMessages(Folder.RECEIVED) }
assertEquals(2, messages.size)
val messagesSent = runBlocking { sdk.getMessages(Folder.SENT) }
assertEquals(1, messagesSent.size)
val messagesTrashed = runBlocking { sdk.getMessages(Folder.TRASHED) }
assertEquals(1, messagesTrashed.size)
}
@Test
fun readMessage_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
loginId = 16
studentId = 15
classId = 14
}
val message = runBlocking { sdk.getMessageDetails("asdf") }
assertEquals("Zmiana statusu wiadomości.", message.content)
}
@Test
fun deleteMessage_api() {
val sdk = Sdk().apply {
privateKey = PRIVATE_KEY
certKey = CERT_KEY
mobileBaseUrl = "https://api.fakelog.cf/powiatwulkanowy"
mode = Sdk.Mode.API
symbol = "powiatwulkanowy"
schoolSymbol = "123456"
loginId = 16
studentId = 15
classId = 14
}
runBlocking { sdk.deleteMessages(listOf()) }
}
}

View file

@ -1,118 +0,0 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.scrapper.attendance.Attendance
import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import java.time.LocalDateTime
class AttendanceMapperTest : BaseLocalTest() {
@Test
fun getAttendance_presence() {
createAttendance(AttendanceCategory.PRESENCE).mapAttendance()[0].run {
assertTrue(presence)
assertFalse(excused)
assertFalse(absence)
assertFalse(exemption)
assertFalse(lateness)
}
}
@Test
fun getAttendance_absence() {
createAttendance(AttendanceCategory.ABSENCE_UNEXCUSED).mapAttendance()[0].run {
assertTrue(absence)
assertFalse(excused)
assertFalse(exemption)
assertFalse(presence)
assertFalse(lateness)
}
}
@Test
fun getAttendance_absenceExcused() {
createAttendance(AttendanceCategory.ABSENCE_EXCUSED).mapAttendance()[0].run {
assertTrue(absence)
assertTrue(excused)
assertFalse(exemption)
assertFalse(presence)
assertFalse(lateness)
}
}
@Test
fun getAttendance_lateness() {
createAttendance(AttendanceCategory.UNEXCUSED_LATENESS).mapAttendance()[0].run {
assertTrue(lateness)
assertFalse(excused)
assertFalse(exemption)
assertFalse(presence)
assertFalse(absence)
}
}
@Test
fun getAttendance_latenessExcused() {
createAttendance(AttendanceCategory.EXCUSED_LATENESS).mapAttendance()[0].run {
assertTrue(lateness)
assertTrue(excused)
assertFalse(exemption)
assertFalse(presence)
assertFalse(absence)
}
}
@Test
fun getAttendance_absenceForSchoolReason() {
createAttendance(AttendanceCategory.ABSENCE_FOR_SCHOOL_REASONS).mapAttendance()[0].run {
assertTrue(presence)
assertFalse(excused)
assertFalse(lateness)
assertFalse(exemption)
assertFalse(absence)
}
}
@Test
fun getAttendance_exemption() {
createAttendance(AttendanceCategory.EXEMPTION).mapAttendance()[0].run {
assertTrue(exemption)
assertFalse(excused)
assertFalse(lateness)
assertFalse(presence)
assertFalse(absence)
}
}
@Test
fun getAttendance_unknown() {
createAttendance(AttendanceCategory.UNKNOWN).mapAttendance()[0].run {
assertFalse(exemption)
assertFalse(excused)
assertFalse(lateness)
assertFalse(presence)
assertFalse(absence)
}
}
private fun createAttendance(cat: AttendanceCategory): List<Attendance> {
val item = Attendance(1, LocalDateTime.now(), "").apply {
number = 0
category = cat
excusable = false
excuseStatus = null
}
return listOf(item)
}
}

View file

@ -1,32 +0,0 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.exams.ExamsTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import java.time.LocalDate.now
class ExamsMapperTest : BaseLocalTest() {
private val mobile by lazy {
Sdk().apply {
mode = Sdk.Mode.API
mobileBaseUrl = server.url("/").toString()
}
}
@Test
fun getApiExams() {
server.enqueueAndStart("Sprawdziany.json", ExamsTest::class.java)
server.enqueue("Slowniki.json", BaseLocalTest::class.java)
val exams = runBlocking { mobile.getExams(now(), now(), 1) }
assertEquals(3, exams.size)
assertEquals("Sprawdzian", exams[0].type)
assertEquals("Kartkówka", exams[1].type)
assertEquals("Praca klasowa", exams[2].type)
}
}

View file

@ -1,34 +0,0 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.grades.GradesTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
class GradesMapperTest : BaseLocalTest() {
private val mobile by lazy {
Sdk().apply {
mode = Sdk.Mode.API
mobileBaseUrl = server.url("/").toString()
}
}
@Test
fun getApiGrades() {
server.enqueueAndStart("Oceny.json", GradesTest::class.java)
server.enqueue("OcenyPodsumowanie.json", GradesTest::class.java)
server.enqueue("Slowniki.json", BaseLocalTest::class.java)
val grades = runBlocking { mobile.getGrades(0).details }
assertEquals(2, grades.size)
with(grades[0]) {
assertEquals("3", entry)
assertEquals("Akt", symbol)
assertEquals("Aktywność", description)
}
}
}

View file

@ -1,66 +0,0 @@
package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.timetable.TimetableTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import java.time.LocalDate.of
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
class LessonMapperTest : BaseLocalTest() {
private val mobile by lazy {
Sdk().apply {
mode = Sdk.Mode.API
mobileBaseUrl = server.url("/").toString()
}
}
@Test
fun getApiTimetable() {
server.enqueueAndStart("PlanLekcji.json", TimetableTest::class.java)
server.enqueue("Slowniki.json", BaseLocalTest::class.java)
val (_, lessons, _) = runBlocking { mobile.getTimetable(of(2020, 2, 3), of(2020, 2, 4)) }
assertEquals(4, lessons.size)
with(lessons[1]) {
assertEquals(2, number)
assertEquals(ZonedDateTime.of(LocalDateTime.of(2020, 2, 3, 8, 55, 0), ZoneId.of("Europe/Warsaw")), start)
assertEquals(ZonedDateTime.of(LocalDateTime.of(2020, 2, 3, 9, 40, 0), ZoneId.of("Europe/Warsaw")), end)
assertEquals("Sieci komputerowe", subject)
assertEquals("t.infor", group)
assertEquals("Stanisław Krupa", teacher)
assertEquals("G1", room)
assertEquals("przeniesiona z lekcji 1, 10.02.2020", info)
assertEquals("Wychowanie fizyczne", subjectOld)
assertEquals("Mateusz Kowal", teacherOld)
assertEquals("S4", roomOld)
assertEquals(false, canceled)
assertEquals(true, changes)
}
}
@Test
fun getApiTimetable_canceledWithInfoAboutChange() {
server.enqueueAndStart("PlanLekcji.json", TimetableTest::class.java)
server.enqueue("Slowniki.json", BaseLocalTest::class.java)
val (_, lessons, _) = runBlocking { mobile.getTimetable(of(2020, 2, 3), of(2020, 2, 4)) }
with(lessons[3]) {
assertEquals(4, number)
assertEquals("nieobecny oddział - Zwiedzanie Muzeum II Wojny Światowej w Gdańsku.", info)
assertEquals(true, canceled)
assertEquals(false, changes)
}
}
}

Some files were not shown because too many files have changed in this diff Show more