diff --git a/app/build.gradle b/app/build.gradle index 7ee81956..880d6f0f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -183,7 +183,6 @@ dependencies { //implementation "org.redundent:kotlin-xml-builder:1.5.3" - implementation "io.github.wulkanowy:signer-android:0.1.1" implementation 'com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31' implementation "androidx.work:work-runtime-ktx:${versions.work}" @@ -211,7 +210,7 @@ dependencies { implementation 'com.qifan.powerpermission:powerpermission:1.3.0' implementation 'com.qifan.powerpermission:powerpermission-coroutines:1.3.0' - implementation 'com.github.kuba2k2.FSLogin:lib:master-SNAPSHOT' + implementation 'com.github.kuba2k2.FSLogin:lib:2.0.0' implementation 'pl.droidsonroids:jspoon:1.3.2' implementation "com.squareup.retrofit2:converter-scalars:2.8.1" implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2" diff --git a/app/proguard/app.pro b/app/proguard/app.pro index 8b3e3e2b..4d84d11d 100644 --- a/app/proguard/app.pro +++ b/app/proguard/app.pro @@ -67,3 +67,6 @@ -keepclassmembers class pl.szczodrzynski.edziennik.data.api.szkolny.request.** { *; } -keepclassmembers class pl.szczodrzynski.edziennik.data.api.szkolny.response.** { *; } -keepclassmembernames class pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo$Platform { *; } + +-keepclassmembernames class pl.szczodrzynski.fslogin.realm.RealmData { *; } +-keepclassmembernames class pl.szczodrzynski.fslogin.realm.RealmData$Type { *; } diff --git a/app/src/main/assets/pl-changelog.html b/app/src/main/assets/pl-changelog.html index f22c959b..1db852ec 100644 --- a/app/src/main/assets/pl-changelog.html +++ b/app/src/main/assets/pl-changelog.html @@ -1,7 +1,12 @@ -

Wersja 4.5, 2021-02-21

+

Wersja 4.6, 2021-02-26



diff --git a/app/src/main/cpp/szkolny-signing.cpp b/app/src/main/cpp/szkolny-signing.cpp index 0176acf6..474d9ba5 100644 --- a/app/src/main/cpp/szkolny-signing.cpp +++ b/app/src/main/cpp/szkolny-signing.cpp @@ -9,7 +9,7 @@ /*secret password - removed for source code publication*/ static toys AES_IV[16] = { - 0x4f, 0x43, 0x04, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + 0x9f, 0xff, 0x0f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index d4c6a2e0..71febada 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -43,10 +43,9 @@ import androidx.viewpager.widget.ViewPager import com.google.android.gms.security.ProviderInstaller import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.google.gson.* import com.google.gson.JsonArray -import com.google.gson.JsonElement import com.google.gson.JsonObject -import com.google.gson.JsonParser import im.wangchao.mhttp.Response import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -538,6 +537,12 @@ fun String.md5(): String { return BigInteger(1, md.digest(toByteArray())).toString(16).padStart(32, '0') } +fun String.sha1Hex(): String { + val md = MessageDigest.getInstance("SHA-1") + md.update(toByteArray()) + return md.digest().joinToString("") { "%02x".format(it) } +} + fun String.sha256(): ByteArray { val md = MessageDigest.getInstance("SHA-256") md.update(toByteArray()) @@ -697,6 +702,21 @@ fun JsonObject(vararg properties: Pair): JsonObject { } } +fun JsonObject.toBundle(): Bundle { + return Bundle().also { + for ((key, value) in this.entrySet()) { + when (value) { + is JsonObject -> it.putBundle(key, value.toBundle()) + is JsonPrimitive -> when { + value.isString -> it.putString(key, value.asString) + value.isBoolean -> it.putBoolean(key, value.asBoolean) + value.isNumber -> it.putInt(key, value.asInt) + } + } + } + } +} + fun JsonArray(vararg properties: Any?): JsonArray { return JsonArray().apply { for (property in properties) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index d5a1adde..1e73e267 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -751,6 +751,11 @@ class MainActivity : AppCompatActivity(), CoroutineScope { @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) { EventBus.getDefault().removeStickyEvent(event) + if (event.error.errorCode == ERROR_VULCAN_API_DEPRECATED) { + if (event.error.profileId != App.profileId) + return + ErrorDetailsDialog(this, listOf(event.error)) + } navView.toolbar.apply { subtitleFormat = R.string.toolbar_subtitle subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread @@ -758,9 +763,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope { } mainSnackbar.dismiss() errorSnackbar.addError(event.error).show() - if (event.error.errorCode == ERROR_VULCAN_API_DEPRECATED) { - ErrorDetailsDialog(this, listOf(event.error)) - } } @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt index 98240be5..5cdf30bc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt @@ -105,6 +105,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig { get() { mWidgetConfigs = mWidgetConfigs ?: values.get("widgetConfigs", JsonObject()); return mWidgetConfigs ?: JsonObject() } set(value) { set("widgetConfigs", value); mWidgetConfigs = value } + private var mArchiverEnabled: Boolean? = null + var archiverEnabled: Boolean + get() { mArchiverEnabled = mArchiverEnabled ?: values.get("archiverEnabled", true); return mArchiverEnabled ?: true } + set(value) { set("archiverEnabled", value); mArchiverEnabled = value } + private var rawEntries: List = db.configDao().getAllNow() private val profileConfigs: HashMap = hashMapOf() init { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt index 614d5f3a..f06ef354 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt @@ -90,11 +90,6 @@ const val IDZIENNIK_API_MESSAGES_SENT = "Wiadomosci/Wyslane" val MOBIDZIENNIK_USER_AGENT = SYSTEM_USER_AGENT -const val VULCAN_API_USER_AGENT = "MobileUserAgent" -const val VULCAN_API_APP_NAME = "VULCAN-Android-ModulUcznia" -const val VULCAN_API_APP_VERSION = "20.5.1.470" -const val VULCAN_API_PASSWORD = "CE75EA598C7743AD9B0B7328DED85B06" -const val VULCAN_API_PASSWORD_FAKELOG = "012345678901234567890123456789AB" const val VULCAN_HEBE_USER_AGENT = "Dart/2.10 (dart:io)" const val VULCAN_HEBE_APP_NAME = "DzienniczekPlus 2.0" const val VULCAN_HEBE_APP_VERSION = "21.02.09 (G)" @@ -106,36 +101,24 @@ val VULCAN_API_DEVICE_NAME by lazy { base.take(baseMaxLength) + VULCAN_API_DEVICE_NAME_SUFFIX } -const val VULCAN_API_ENDPOINT_CERTIFICATE = "mobile-api/Uczen.v3.UczenStart/Certyfikat" -const val VULCAN_API_ENDPOINT_STUDENT_LIST = "mobile-api/Uczen.v3.UczenStart/ListaUczniow" -const val VULCAN_API_ENDPOINT_DICTIONARIES = "mobile-api/Uczen.v3.Uczen/Slowniki" -const val VULCAN_API_ENDPOINT_TIMETABLE = "mobile-api/Uczen.v3.Uczen/PlanLekcjiZeZmianami" -const val VULCAN_API_ENDPOINT_GRADES = "mobile-api/Uczen.v3.Uczen/Oceny" -const val VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS = "mobile-api/Uczen.v3.Uczen/OcenyPodsumowanie" -const val VULCAN_API_ENDPOINT_EVENTS = "mobile-api/Uczen.v3.Uczen/Sprawdziany" -const val VULCAN_API_ENDPOINT_HOMEWORK = "mobile-api/Uczen.v3.Uczen/ZadaniaDomowe" -const val VULCAN_API_ENDPOINT_NOTICES = "mobile-api/Uczen.v3.Uczen/UwagiUcznia" -const val VULCAN_API_ENDPOINT_ATTENDANCE = "mobile-api/Uczen.v3.Uczen/Frekwencje" -const val VULCAN_API_ENDPOINT_MESSAGES_RECEIVED = "mobile-api/Uczen.v3.Uczen/WiadomosciOdebrane" -const val VULCAN_API_ENDPOINT_MESSAGES_SENT = "mobile-api/Uczen.v3.Uczen/WiadomosciWyslane" -const val VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS = "mobile-api/Uczen.v3.Uczen/ZmienStatusWiadomosci" -const val VULCAN_API_ENDPOINT_MESSAGES_ADD = "mobile-api/Uczen.v3.Uczen/DodajWiadomosc" -const val VULCAN_API_ENDPOINT_PUSH = "mobile-api/Uczen.v3.Uczen/UstawPushToken" -const val VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/WiadomosciZalacznik" -const val VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/ZadaniaDomoweZalacznik" const val VULCAN_WEB_ENDPOINT_LUCKY_NUMBER = "Start.mvc/GetKidsLuckyNumbers" const val VULCAN_WEB_ENDPOINT_REGISTER_DEVICE = "RejestracjaUrzadzeniaToken.mvc/Get" const val VULCAN_HEBE_ENDPOINT_REGISTER_NEW = "api/mobile/register/new" const val VULCAN_HEBE_ENDPOINT_MAIN = "api/mobile/register/hebe" +const val VULCAN_HEBE_ENDPOINT_PUSH_ALL = "api/mobile/push/all" const val VULCAN_HEBE_ENDPOINT_TIMETABLE = "api/mobile/schedule" const val VULCAN_HEBE_ENDPOINT_TIMETABLE_CHANGES = "api/mobile/schedule/changes" const val VULCAN_HEBE_ENDPOINT_ADDRESSBOOK = "api/mobile/addressbook" const val VULCAN_HEBE_ENDPOINT_EXAMS = "api/mobile/exam" const val VULCAN_HEBE_ENDPOINT_GRADES = "api/mobile/grade" +const val VULCAN_HEBE_ENDPOINT_GRADE_SUMMARY = "api/mobile/grade/summary" const val VULCAN_HEBE_ENDPOINT_HOMEWORK = "api/mobile/homework" +const val VULCAN_HEBE_ENDPOINT_NOTICES = "api/mobile/note" const val VULCAN_HEBE_ENDPOINT_ATTENDANCE = "api/mobile/lesson" const val VULCAN_HEBE_ENDPOINT_MESSAGES = "api/mobile/message" const val VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS = "api/mobile/message/status" +const val VULCAN_HEBE_ENDPOINT_MESSAGES_SEND = "api/mobile/message" +const val VULCAN_HEBE_ENDPOINT_LUCKY_NUMBER = "api/mobile/school/lucky" const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt index 6809ed2e..153c30c2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt @@ -148,17 +148,11 @@ const val ERROR_MOBIDZIENNIK_WEB_SERVER_PROBLEM = 218 const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301 const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302 -const val ERROR_LOGIN_VULCAN_INVALID_PIN = 309 const val ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING = 310 const val ERROR_LOGIN_VULCAN_INVALID_PIN_1_REMAINING = 311 const val ERROR_LOGIN_VULCAN_INVALID_PIN_2_REMAINING = 312 const val ERROR_LOGIN_VULCAN_EXPIRED_TOKEN = 321 -const val ERROR_LOGIN_VULCAN_OTHER = 322 -const val ERROR_LOGIN_VULCAN_ONLY_KINDERGARTEN = 330 const val ERROR_LOGIN_VULCAN_NO_PUPILS = 331 -const val ERROR_VULCAN_API_MAINTENANCE = 340 -const val ERROR_VULCAN_API_BAD_REQUEST = 341 -const val ERROR_VULCAN_API_OTHER = 342 const val ERROR_VULCAN_ATTACHMENT_DOWNLOAD = 343 const val ERROR_VULCAN_WEB_DATA_MISSING = 344 const val ERROR_VULCAN_WEB_429 = 345 @@ -171,30 +165,14 @@ const val ERROR_VULCAN_WEB_CERTIFICATE_POST_FAILED = 351 const val ERROR_VULCAN_WEB_GRADUATE_ACCOUNT = 352 const val ERROR_VULCAN_WEB_NO_SCHOOLS = 353 const val ERROR_VULCAN_HEBE_OTHER = 354 +const val ERROR_VULCAN_HEBE_SIGNATURE_ERROR = 360 +const val ERROR_VULCAN_HEBE_INVALID_PAYLOAD = 361 +const val ERROR_VULCAN_HEBE_FIREBASE_ERROR = 362 +const val ERROR_VULCAN_HEBE_CERTIFICATE_GONE = 363 +const val ERROR_VULCAN_HEBE_SERVER_ERROR = 364 +const val ERROR_VULCAN_HEBE_ENTITY_NOT_FOUND = 365 const val ERROR_VULCAN_API_DEPRECATED = 390 -const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN = 401 -const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME = 402 -const val ERROR_LOGIN_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED = 403 -const val ERROR_LOGIN_IDZIENNIK_WEB_MAINTENANCE = 404 -const val ERROR_LOGIN_IDZIENNIK_WEB_SERVER_ERROR = 405 -const val ERROR_LOGIN_IDZIENNIK_WEB_OTHER = 410 -const val ERROR_LOGIN_IDZIENNIK_WEB_API_NO_ACCESS = 411 /* {"d":{"__type":"mds.Web.mod_komunikator.WS_mod_wiadomosci+detailWiadomosci","Wiadomosc":{"_recordId":0,"DataNadania":null,"DataOdczytania":null,"Nadawca":null,"ListaOdbiorcow":[],"Tytul":null,"Text":null,"ListaZal":[]},"Bledy":{"__type":"mds.Module.Globalne+sBledy","CzyJestBlad":true,"ListaBledow":["Nie masz dostępu do tych zasobów!"],"ListaKodowBledow":[]},"czyJestWiecej":false}} */ -const val ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION = 420 -const val ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH = 421 -const val ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER = 422 -const val ERROR_IDZIENNIK_WEB_ACCESS_DENIED = 430 -const val ERROR_IDZIENNIK_WEB_OTHER = 431 -const val ERROR_IDZIENNIK_WEB_MAINTENANCE = 432 -const val ERROR_IDZIENNIK_WEB_SERVER_ERROR = 433 -const val ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED = 434 -const val ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR = 440 -const val ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA = 441 -const val ERROR_IDZIENNIK_API_ACCESS_DENIED = 450 -const val ERROR_IDZIENNIK_API_OTHER = 451 -const val ERROR_IDZIENNIK_API_NO_REGISTER = 452 -const val ERROR_IDZIENNIK_WEB_RECIPIENT_LIST_NO_PERMISSION = 453 - const val ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN = 501 const val ERROR_LOGIN_EDUDZIENNIK_WEB_OTHER = 510 const val ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID = 511 @@ -217,14 +195,10 @@ const val EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903 const val EXCEPTION_LIBRUS_API_REQUEST = 904 const val EXCEPTION_LIBRUS_SYNERGIA_REQUEST = 905 const val EXCEPTION_MOBIDZIENNIK_WEB_REQUEST = 906 -const val EXCEPTION_VULCAN_API_REQUEST = 907 const val EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST = 908 const val EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST = 909 const val EXCEPTION_NOTIFY = 910 const val EXCEPTION_LIBRUS_MESSAGES_REQUEST = 911 -const val EXCEPTION_IDZIENNIK_WEB_REQUEST = 912 -const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913 -const val EXCEPTION_IDZIENNIK_API_REQUEST = 914 const val EXCEPTION_EDUDZIENNIK_WEB_REQUEST = 920 const val EXCEPTION_EDUDZIENNIK_FILE_REQUEST = 921 const val ERROR_ONEDRIVE_DOWNLOAD = 930 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt index d70dd54e..b3db9f71 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt @@ -5,8 +5,6 @@ package pl.szczodrzynski.edziennik.data.api import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLoginWeb -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginApi -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginWeb import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginMessages import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPortal @@ -16,14 +14,13 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.Mobidzie import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLoginApi import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginApi import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginHebe import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain import pl.szczodrzynski.edziennik.data.api.models.LoginMethod // librus // mobidziennik -// idziennik +// idziennik [*] // vulcan // mobireg @@ -35,14 +32,10 @@ const val LOGIN_TYPE_IDZIENNIK = 3 const val LOGIN_TYPE_TEMPLATE = 21 // LOGIN MODES -const val LOGIN_MODE_IDZIENNIK_WEB = 0 - const val LOGIN_MODE_TEMPLATE_WEB = 0 // LOGIN METHODS const val LOGIN_METHOD_NOT_NEEDED = -1 -const val LOGIN_METHOD_IDZIENNIK_WEB = 100 -const val LOGIN_METHOD_IDZIENNIK_API = 200 const val LOGIN_METHOD_TEMPLATE_WEB = 100 const val LOGIN_METHOD_TEMPLATE_API = 200 @@ -104,7 +97,6 @@ const val LOGIN_METHOD_VULCAN_WEB_MAIN = 100 const val LOGIN_METHOD_VULCAN_WEB_NEW = 200 const val LOGIN_METHOD_VULCAN_WEB_OLD = 300 const val LOGIN_METHOD_VULCAN_WEB_MESSAGES = 400 -const val LOGIN_METHOD_VULCAN_API = 500 const val LOGIN_METHOD_VULCAN_HEBE = 600 val vulcanLoginMethods = listOf( LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_MAIN, VulcanLoginWebMain::class.java) @@ -119,31 +111,11 @@ val vulcanLoginMethods = listOf( .withIsPossible { _, _ -> false } .withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },*/ - LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_API, VulcanLoginApi::class.java) - .withIsPossible { _, loginStore -> - loginStore.mode != LOGIN_MODE_VULCAN_HEBE - } - .withRequiredLoginMethod { _, loginStore -> - if (loginStore.mode == LOGIN_MODE_VULCAN_WEB) LOGIN_METHOD_VULCAN_WEB_MAIN else LOGIN_METHOD_NOT_NEEDED - }, - LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_HEBE, VulcanLoginHebe::class.java) .withIsPossible { _, loginStore -> loginStore.mode != LOGIN_MODE_VULCAN_API } - .withRequiredLoginMethod { _, loginStore -> - if (loginStore.mode == LOGIN_MODE_VULCAN_WEB) LOGIN_METHOD_VULCAN_WEB_MAIN else LOGIN_METHOD_NOT_NEEDED - } -) - -val idziennikLoginMethods = listOf( - LoginMethod(LOGIN_TYPE_IDZIENNIK, LOGIN_METHOD_IDZIENNIK_WEB, IdziennikLoginWeb::class.java) - .withIsPossible { _, _ -> true } - .withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }, - - LoginMethod(LOGIN_TYPE_IDZIENNIK, LOGIN_METHOD_IDZIENNIK_API, IdziennikLoginApi::class.java) - .withIsPossible { _, _ -> true } - .withRequiredLoginMethod { _, _ -> LOGIN_METHOD_IDZIENNIK_WEB } + .withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED } ) const val LOGIN_TYPE_EDUDZIENNIK = 5 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt index 919131f0..5d847e3f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt @@ -156,7 +156,7 @@ object Regexes { """\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex() } val VULCAN_WEB_PERMISSIONS by lazy { - """permissions: '([A-z0-9/=+\-_]+?)'""".toRegex() + """permissions: '([A-z0-9/=+\-_|]+?)'""".toRegex() } val VULCAN_WEB_SYMBOL_VALIDATE by lazy { """[A-z0-9]+""".toRegex(IGNORE_CASE) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt index c6938f7a..7a578356 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt @@ -9,7 +9,6 @@ import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.Edudziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.Idziennik import pl.szczodrzynski.edziennik.data.api.edziennik.librus.Librus import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.Mobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.Podlasie @@ -123,7 +122,6 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa LOGIN_TYPE_LIBRUS -> Librus(app, profile, loginStore, taskCallback) LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback) LOGIN_TYPE_VULCAN -> Vulcan(app, profile, loginStore, taskCallback) - LOGIN_TYPE_IDZIENNIK -> Idziennik(app, profile, loginStore, taskCallback) LOGIN_TYPE_EDUDZIENNIK -> Edudziennik(app, profile, loginStore, taskCallback) LOGIN_TYPE_PODLASIE -> Podlasie(app, profile, loginStore, taskCallback) LOGIN_TYPE_TEMPLATE -> Template(app, profile, loginStore, taskCallback) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt deleted file mode 100644 index 3e974539..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-25. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik - -import androidx.core.util.set -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_API -import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_WEB -import pl.szczodrzynski.edziennik.data.api.models.Data -import pl.szczodrzynski.edziennik.data.db.entity.LoginStore -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.data.db.entity.Subject -import pl.szczodrzynski.edziennik.data.db.entity.Teacher - -class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) { - - fun isWebLoginValid() = loginExpiryTime-30 > currentTimeUnix() && webSessionId.isNotNullNorEmpty() && webAuth.isNotNullNorEmpty() - fun isApiLoginValid() = apiExpiryTime-30 > currentTimeUnix() && apiBearer.isNotNullNorEmpty() - - override fun satisfyLoginMethods() { - loginMethods.clear() - if (isWebLoginValid()) { - loginMethods += LOGIN_METHOD_IDZIENNIK_WEB - app.cookieJar.set("iuczniowie.progman.pl", "ASP.NET_SessionId_iDziennik", webSessionId) - app.cookieJar.set("iuczniowie.progman.pl", ".ASPXAUTH", webAuth) - } - if (isApiLoginValid()) - loginMethods += LOGIN_METHOD_IDZIENNIK_API - } - - override fun generateUserCode() = "$webSchoolName:$webUsername:$registerId" - - private var mLoginExpiryTime: Long? = null - var loginExpiryTime: Long - get() { mLoginExpiryTime = mLoginExpiryTime ?: loginStore.getLoginData("loginExpiryTime", 0L); return mLoginExpiryTime ?: 0L } - set(value) { loginStore.putLoginData("loginExpiryTime", value); mLoginExpiryTime = value } - - private var mApiExpiryTime: Long? = null - var apiExpiryTime: Long - get() { mApiExpiryTime = mApiExpiryTime ?: loginStore.getLoginData("apiExpiryTime", 0L); return mApiExpiryTime ?: 0L } - set(value) { loginStore.putLoginData("apiExpiryTime", value); mApiExpiryTime = value } - - /* __ __ _ - \ \ / / | | - \ \ /\ / /__| |__ - \ \/ \/ / _ \ '_ \ - \ /\ / __/ |_) | - \/ \/ \___|_._*/ - private var mWebSchoolName: String? = null - var webSchoolName: String? - get() { mWebSchoolName = mWebSchoolName ?: loginStore.getLoginData("schoolName", null); return mWebSchoolName } - set(value) { loginStore.putLoginData("schoolName", value); mWebSchoolName = value } - private var mWebUsername: String? = null - var webUsername: String? - get() { mWebUsername = mWebUsername ?: loginStore.getLoginData("username", null); return mWebUsername } - set(value) { loginStore.putLoginData("username", value); mWebUsername = value } - private var mWebPassword: String? = null - var webPassword: String? - get() { mWebPassword = mWebPassword ?: loginStore.getLoginData("password", null); return mWebPassword } - set(value) { loginStore.putLoginData("password", value); mWebPassword = value } - - private var mWebSessionId: String? = null - var webSessionId: String? - get() { mWebSessionId = mWebSessionId ?: loginStore.getLoginData("webSessionId", null); return mWebSessionId } - set(value) { loginStore.putLoginData("webSessionId", value); mWebSessionId = value } - private var mWebAuth: String? = null - var webAuth: String? - get() { mWebAuth = mWebAuth ?: loginStore.getLoginData("webAuth", null); return mWebAuth } - set(value) { loginStore.putLoginData("webAuth", value); mWebAuth = value } - - private var mWebSelectedRegister: Int? = null - var webSelectedRegister: Int - get() { mWebSelectedRegister = mWebSelectedRegister ?: loginStore.getLoginData("webSelectedRegister", 0); return mWebSelectedRegister ?: 0 } - set(value) { loginStore.putLoginData("webSelectedRegister", value); mWebSelectedRegister = value } - - /* _ - /\ (_) - / \ _ __ _ - / /\ \ | '_ \| | - / ____ \| |_) | | - /_/ \_\ .__/|_| - | | - |*/ - private var mApiBearer: String? = null - var apiBearer: String? - get() { mApiBearer = mApiBearer ?: loginStore.getLoginData("apiBearer", null); return mApiBearer } - set(value) { loginStore.putLoginData("apiBearer", value); mApiBearer = value } - - /* ____ _ _ - / __ \| | | | - | | | | |_| |__ ___ _ __ - | | | | __| '_ \ / _ \ '__| - | |__| | |_| | | | __/ | - \____/ \__|_| |_|\___|*/ - private var mStudentId: String? = null - var studentId: String? - get() { mStudentId = mStudentId ?: profile?.getStudentData("studentId", null); return mStudentId } - set(value) { profile?.putStudentData("studentId", value) ?: return; mStudentId = value } - - private var mRegisterId: Int? = null - var registerId: Int - get() { mRegisterId = mRegisterId ?: profile?.getStudentData("registerId", 0); return mRegisterId ?: 0 } - set(value) { profile?.putStudentData("registerId", value) ?: return; mRegisterId = value } - - private var mSchoolYearId: Int? = null - var schoolYearId: Int - get() { mSchoolYearId = mSchoolYearId ?: profile?.getStudentData("schoolYearId", 0); return mSchoolYearId ?: 0 } - set(value) { profile?.putStudentData("schoolYearId", value) ?: return; mSchoolYearId = value } - - - - /* _ _ _ _ _ - | | | | | (_) | - | | | | |_ _| |___ - | | | | __| | / __| - | |__| | |_| | \__ \ - \____/ \__|_|_|__*/ - fun getSubject(name: String, id: Long?, shortName: String): Subject { - var subject = if (id == null) - subjectList.singleOrNull { it.longName == name } - else - subjectList.singleOrNull { it.id == id } - - if (subject == null) { - subject = Subject(profileId, id - ?: name.crc16().toLong(), name, shortName) - subjectList[subject.id] = subject - } - return subject - } - - fun getTeacher(firstName: String, lastName: String): Teacher { - val teacher = teacherList.singleOrNull { it.fullName == "$firstName $lastName" } - return validateTeacher(teacher, firstName, lastName) - } - - fun getTeacher(firstNameChar: Char, lastName: String): Teacher { - val teacher = teacherList.singleOrNull { it.shortName == "$firstNameChar.$lastName" } - return validateTeacher(teacher, firstNameChar.toString(), lastName) - } - - fun getTeacherByLastFirst(nameLastFirst: String): Teacher { - val nameParts = nameLastFirst.split(" ") - return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[1], nameParts[0]) - } - - fun getTeacherByFirstLast(nameFirstLast: String): Teacher { - val nameParts = nameFirstLast.split(" ") - return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[0], nameParts[1]) - } - - fun getTeacherByFDotLast(nameFDotLast: String): Teacher { - val nameParts = nameFDotLast.split(".") - return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[0][0], nameParts[1]) - } - - fun getTeacherByFDotSpaceLast(nameFDotSpaceLast: String): Teacher { - val nameParts = nameFDotSpaceLast.split(".") - return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[0][0], nameParts[1]) - } - - private fun validateTeacher(teacher: Teacher?, firstName: String, lastName: String): Teacher { - (teacher ?: Teacher(profileId, -1, firstName, lastName).apply { - id = shortName.crc16().toLong() - teacherList[id] = this - }).apply { - if (firstName.length > 1) - name = firstName - surname = lastName - return this - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/Idziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/Idziennik.kt deleted file mode 100644 index e1550632..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/Idziennik.kt +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-25. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik - -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikData -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.* -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin.IdziennikFirstLogin -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLogin -import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback -import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull -import pl.szczodrzynski.edziennik.data.db.full.EventFull -import pl.szczodrzynski.edziennik.data.db.full.MessageFull -import pl.szczodrzynski.edziennik.utils.Utils.d - -class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface { - companion object { - private const val TAG = "Idziennik" - } - - val internalErrorList = mutableListOf() - val data: DataIdziennik - private var afterLogin: (() -> Unit)? = null - - init { - data = DataIdziennik(app, profile, loginStore).apply { - callback = wrapCallback(this@Idziennik.callback) - satisfyLoginMethods() - } - } - - private fun completed() { - data.saveData() - callback.onCompleted() - } - - /* _______ _ _ _ _ _ - |__ __| | /\ | | (_) | | | - | | | |__ ___ / \ | | __ _ ___ _ __ _| |_| |__ _ __ ___ - | | | '_ \ / _ \ / /\ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \ - | | | | | | __/ / ____ \| | (_| | (_) | | | | |_| | | | | | | | | - |_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_| - __/ | - |__*/ - override fun sync(featureIds: List, viewId: Int?, onlyEndpoints: List?, arguments: JsonObject?) { - data.arguments = arguments - data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId, onlyEndpoints) - login() - } - - private fun login(loginMethodId: Int? = null, afterLogin: (() -> Unit)? = null) { - d(TAG, "Trying to login with ${data.targetLoginMethodIds}") - if (internalErrorList.isNotEmpty()) { - d(TAG, " - Internal errors:") - internalErrorList.forEach { d(TAG, " - code $it") } - } - loginMethodId?.let { data.prepareFor(idziennikLoginMethods, it) } - afterLogin?.let { this.afterLogin = it } - IdziennikLogin(data) { - data() - } - } - - private fun data() { - d(TAG, "Endpoint IDs: ${data.targetEndpointIds}") - if (internalErrorList.isNotEmpty()) { - d(TAG, " - Internal errors:") - internalErrorList.forEach { d(TAG, " - code $it") } - } - afterLogin?.invoke() ?: IdziennikData(data) { - completed() - } - } - - override fun getMessage(message: MessageFull) { - login(LOGIN_METHOD_IDZIENNIK_WEB) { - IdziennikWebGetMessage(data, message) { - completed() - } - } - } - - override fun sendMessage(recipients: List, subject: String, text: String) { - login(LOGIN_METHOD_IDZIENNIK_API) { - IdziennikWebSendMessage(data, recipients, subject, text) { - completed() - } - } - } - - override fun markAllAnnouncementsAsRead() {} - override fun getAnnouncement(announcement: AnnouncementFull) {} - - override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) { - login(LOGIN_METHOD_IDZIENNIK_WEB) { - if (owner is Message) { - IdziennikWebGetAttachment(data, owner, attachmentId, attachmentName) { - completed() - } - } - else if (owner is Event) { - IdziennikWebGetHomeworkAttachment(data, owner, attachmentId, attachmentName) { - completed() - } - } - } - } - - override fun getRecipientList() { - login(LOGIN_METHOD_IDZIENNIK_WEB) { - IdziennikWebGetRecipientList(data) { - completed() - } - } - } - - override fun getEvent(eventFull: EventFull) { - login(LOGIN_METHOD_IDZIENNIK_WEB) { - IdziennikWebGetHomework(data, eventFull) { - completed() - } - } - } - - override fun firstLogin() { IdziennikFirstLogin(data) { completed() } } - override fun cancel() { - d(TAG, "Cancelled") - data.cancel() - } - - private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback { - return object : EdziennikCallback { - override fun onCompleted() { callback.onCompleted() } - override fun onProgress(step: Float) { callback.onProgress(step) } - override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) } - override fun onError(apiError: ApiError) { - if (apiError.errorCode in internalErrorList) { - // finish immediately if the same error occurs twice during the same sync - callback.onError(apiError) - return - } - internalErrorList.add(apiError.errorCode) - when (apiError.errorCode) { - ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION, - ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH, - ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER, - ERROR_IDZIENNIK_WEB_ACCESS_DENIED, - ERROR_IDZIENNIK_API_ACCESS_DENIED -> { - data.loginMethods.remove(LOGIN_METHOD_IDZIENNIK_WEB) - data.prepareFor(idziennikLoginMethods, LOGIN_METHOD_IDZIENNIK_WEB) - data.loginExpiryTime = 0 - login() - } - ERROR_IDZIENNIK_API_NO_REGISTER -> { - data() - } - else -> callback.onError(apiError) - } - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/IdziennikFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/IdziennikFeatures.kt deleted file mode 100644 index 02aaabb2..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/IdziennikFeatures.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-25. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik - -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.models.Feature - -const val ENDPOINT_IDZIENNIK_WEB_TIMETABLE = 1030 -const val ENDPOINT_IDZIENNIK_WEB_GRADES = 1040 -const val ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES = 1050 -const val ENDPOINT_IDZIENNIK_WEB_EXAMS = 1060 -const val ENDPOINT_IDZIENNIK_WEB_HOMEWORK = 1061 -const val ENDPOINT_IDZIENNIK_WEB_NOTICES = 1070 -const val ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS = 1080 -const val ENDPOINT_IDZIENNIK_WEB_ATTENDANCE = 1090 -const val ENDPOINT_IDZIENNIK_WEB_MESSAGES_INBOX = 1110 -const val ENDPOINT_IDZIENNIK_WEB_MESSAGES_SENT = 1120 -const val ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER = 2010 -const val ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX = 2110 -const val ENDPOINT_IDZIENNIK_API_MESSAGES_SENT = 2120 - -val IdziennikFeatures = listOf( - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_TIMETABLE, listOf( - ENDPOINT_IDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_GRADES, listOf( - ENDPOINT_IDZIENNIK_WEB_GRADES to LOGIN_METHOD_IDZIENNIK_WEB, - ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_AGENDA, listOf( - ENDPOINT_IDZIENNIK_WEB_EXAMS to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_HOMEWORK, listOf( - ENDPOINT_IDZIENNIK_WEB_HOMEWORK to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_BEHAVIOUR, listOf( - ENDPOINT_IDZIENNIK_WEB_NOTICES to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_ATTENDANCE, listOf( - ENDPOINT_IDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_ANNOUNCEMENTS, listOf( - ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)), - - /*Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_INBOX, listOf( - ENDPOINT_IDZIENNIK_WEB_MESSAGES_INBOX to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)).withPriority(2), - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_SENT, listOf( - ENDPOINT_IDZIENNIK_WEB_MESSAGES_SENT to LOGIN_METHOD_IDZIENNIK_WEB - ), listOf(LOGIN_METHOD_IDZIENNIK_WEB)).withPriority(2),*/ - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_INBOX, listOf( - ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX to LOGIN_METHOD_IDZIENNIK_API - ), listOf(LOGIN_METHOD_IDZIENNIK_API)), - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_SENT, listOf( - ENDPOINT_IDZIENNIK_API_MESSAGES_SENT to LOGIN_METHOD_IDZIENNIK_API - ), listOf(LOGIN_METHOD_IDZIENNIK_API)), - - Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_LUCKY_NUMBER, listOf( - ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER to LOGIN_METHOD_IDZIENNIK_API - ), listOf(LOGIN_METHOD_IDZIENNIK_API)) -) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikApi.kt deleted file mode 100644 index 8da75603..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikApi.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-29. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data - -import com.google.gson.JsonArray -import com.google.gson.JsonElement -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import im.wangchao.mhttp.Request -import im.wangchao.mhttp.Response -import im.wangchao.mhttp.callback.TextCallbackHandler -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.Utils -import java.net.HttpURLConnection - -open class IdziennikApi(open val data: DataIdziennik, open val lastSync: Long?) { - companion object { - const val TAG = "IdziennikApi" - } - - val profileId - get() = data.profile?.id ?: -1 - - val profile - get() = data.profile - - fun apiGet(tag: String, endpointTemplate: String, method: Int = GET, parameters: Map = emptyMap(), onSuccess: (json: JsonElement) -> Unit) { - val endpoint = endpointTemplate.replace("\$STUDENT_ID", data.studentId ?: "") - Utils.d(tag, "Request: Idziennik/API - $IDZIENNIK_API_URL/$endpoint") - - val callback = object : TextCallbackHandler() { - override fun onSuccess(text: String?, response: Response?) { - if (text == null) { - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - val json = try { - JsonParser().parse(text) - } catch (_: Exception) { null } - - var error: String? = null - if (json == null) { - error = text - } - else if (json is JsonObject) { - error = if (response?.code() == 200) null else - json.getString("message") ?: json.toString() - } - error?.let { code -> - when (code) { - "Uczeń nie posiada aktywnej pozycji w dzienniku" -> ERROR_IDZIENNIK_API_NO_REGISTER - "Authorization has been denied for this request." -> ERROR_IDZIENNIK_API_ACCESS_DENIED - else -> ERROR_IDZIENNIK_API_OTHER - }.let { errorCode -> - data.error(ApiError(tag, errorCode) - .withApiResponse(text) - .withResponse(response)) - return - } - } - - try { - onSuccess(json!!) - } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_IDZIENNIK_API_REQUEST) - .withResponse(response) - .withThrowable(e) - .withApiResponse(text)) - } - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(tag, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - Request.builder() - .url("$IDZIENNIK_API_URL/$endpoint") - .userAgent(IDZIENNIK_API_USER_AGENT) - .addHeader("Authorization", "Bearer ${data.apiBearer}") - .apply { - when (method) { - GET -> get() - POST -> { - postJson() - val json = JsonObject() - parameters.map { (name, value) -> - when (value) { - is JsonObject -> json.add(name, value) - is JsonArray -> json.add(name, value) - is String -> json.addProperty(name, value) - is Int -> json.addProperty(name, value) - is Long -> json.addProperty(name, value) - is Float -> json.addProperty(name, value) - is Char -> json.addProperty(name, value) - } - } - setJsonBody(json) - } - } - } - .allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST) - .allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED) - .allowErrorCode(HttpURLConnection.HTTP_INTERNAL_ERROR) - .callback(callback) - .build() - .enqueue() - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikData.kt deleted file mode 100644 index 8acb04cb..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikData.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-25. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data - -import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.* -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiCurrentRegister -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiMessagesInbox -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiMessagesSent -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.* -import pl.szczodrzynski.edziennik.utils.Utils - -class IdziennikData(val data: DataIdziennik, val onSuccess: () -> Unit) { - companion object { - private const val TAG = "IdziennikData" - } - - init { - nextEndpoint(onSuccess) - } - - private fun nextEndpoint(onSuccess: () -> Unit) { - if (data.targetEndpointIds.isEmpty()) { - onSuccess() - return - } - if (data.cancelled) { - onSuccess() - return - } - val id = data.targetEndpointIds.firstKey() - val lastSync = data.targetEndpointIds.remove(id) - useEndpoint(id, lastSync) { endpointId -> - data.progress(data.progressStep) - nextEndpoint(onSuccess) - } - } - - private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) { - Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync") - when (endpointId) { - ENDPOINT_IDZIENNIK_WEB_TIMETABLE -> { - data.startProgress(R.string.edziennik_progress_endpoint_timetable) - IdziennikWebTimetable(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_GRADES -> { - data.startProgress(R.string.edziennik_progress_endpoint_grades) - IdziennikWebGrades(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES -> { - data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades) - IdziennikWebProposedGrades(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_EXAMS -> { - data.startProgress(R.string.edziennik_progress_endpoint_exams) - IdziennikWebExams(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_HOMEWORK -> { - data.startProgress(R.string.edziennik_progress_endpoint_homework) - IdziennikWebHomework(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_NOTICES -> { - data.startProgress(R.string.edziennik_progress_endpoint_notices) - IdziennikWebNotices(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS -> { - data.startProgress(R.string.edziennik_progress_endpoint_announcements) - IdziennikWebAnnouncements(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_WEB_ATTENDANCE -> { - data.startProgress(R.string.edziennik_progress_endpoint_attendance) - IdziennikWebAttendance(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER -> { - data.startProgress(R.string.edziennik_progress_endpoint_lucky_number) - IdziennikApiCurrentRegister(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX -> { - data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox) - IdziennikApiMessagesInbox(data, lastSync, onSuccess) - } - ENDPOINT_IDZIENNIK_API_MESSAGES_SENT -> { - data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox) - IdziennikApiMessagesSent(data, lastSync, onSuccess) - } - else -> onSuccess(endpointId) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikWeb.kt deleted file mode 100644 index b871cd37..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikWeb.kt +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-25. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data - -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import im.wangchao.mhttp.Request -import im.wangchao.mhttp.Response -import im.wangchao.mhttp.callback.FileCallbackHandler -import im.wangchao.mhttp.callback.JsonCallbackHandler -import im.wangchao.mhttp.callback.TextCallbackHandler -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebSwitchRegister -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.utils.Utils.d -import java.io.File -import java.net.HttpURLConnection.HTTP_INTERNAL_ERROR -import java.net.HttpURLConnection.HTTP_UNAUTHORIZED - -open class IdziennikWeb(open val data: DataIdziennik, open val lastSync: Long?) { - companion object { - const val TAG = "IdziennikWeb" - } - - val profileId - get() = data.profile?.id ?: -1 - - val profile - get() = data.profile - - fun webApiGet(tag: String, endpoint: String, parameters: Map = emptyMap(), onSuccess: (json: JsonObject) -> Unit) { - d(tag, "Request: Idziennik/Web/API - $IDZIENNIK_WEB_URL/$endpoint") - - val callback = object : JsonCallbackHandler() { - override fun onSuccess(json: JsonObject?, response: Response?) { - if (json == null && response?.parserErrorBody == null) { - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - if (response?.code() == HTTP_INTERNAL_ERROR && endpoint == IDZIENNIK_WEB_GET_RECIPIENT_LIST) { - data.error(ApiError(tag, ERROR_IDZIENNIK_WEB_RECIPIENT_LIST_NO_PERMISSION) - .withResponse(response) - .withApiResponse(json)) - return - } - - if (response?.code() == HTTP_INTERNAL_ERROR && endpoint == IDZIENNIK_WEB_GRADES) { - // special override for accounts where displaying grades - // for another student requires switching it manually - if (data.registerId != data.webSelectedRegister) { - IdziennikWebSwitchRegister(data, data.registerId) { - webApiGet(tag, endpoint, parameters, onSuccess) - } - return - } - } - - when { - response?.code() == HTTP_UNAUTHORIZED -> ERROR_IDZIENNIK_WEB_ACCESS_DENIED - response?.code() == HTTP_INTERNAL_ERROR -> ERROR_IDZIENNIK_WEB_SERVER_ERROR - response?.parserErrorBody != null -> when { - response.parserErrorBody.contains("Identyfikator zgłoszenia") -> ERROR_IDZIENNIK_WEB_SERVER_ERROR - response.parserErrorBody.contains("Hasło dostępu do systemu wygasło") -> ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED - response.parserErrorBody.contains("Trwają prace konserwacyjne") -> ERROR_IDZIENNIK_WEB_MAINTENANCE - else -> ERROR_IDZIENNIK_WEB_OTHER - } - else -> null - }?.let { errorCode -> - data.error(ApiError(TAG, errorCode) - .withApiResponse(json?.toString() ?: response?.parserErrorBody) - .withResponse(response)) - return - } - - if (json == null) { - data.error(ApiError(tag, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - try { - onSuccess(json) - } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_IDZIENNIK_WEB_API_REQUEST) - .withResponse(response) - .withThrowable(e) - .withApiResponse(json)) - } - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(tag, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - Request.builder() - .url("$IDZIENNIK_WEB_URL/$endpoint") - .userAgent(IDZIENNIK_USER_AGENT) - .postJson() - .apply { - val json = JsonObject() - parameters.map { (name, value) -> - when (value) { - is JsonObject -> json.add(name, value) - is JsonArray -> json.add(name, value) - is String -> json.addProperty(name, value) - is Int -> json.addProperty(name, value) - is Long -> json.addProperty(name, value) - is Float -> json.addProperty(name, value) - is Char -> json.addProperty(name, value) - is Boolean -> json.addProperty(name, value) - } - } - setJsonBody(json) - } - .allowErrorCode(HTTP_UNAUTHORIZED) - .allowErrorCode(HTTP_INTERNAL_ERROR) - .callback(callback) - .build() - .enqueue() - } - - fun webGet(tag: String, endpoint: String, parameters: Map = emptyMap(), onSuccess: (text: String) -> Unit) { - d(tag, "Request: Idziennik/Web - $IDZIENNIK_WEB_URL/$endpoint") - - val callback = object : TextCallbackHandler() { - override fun onSuccess(text: String?, response: Response?) { - if (text == null) { - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - if (!text.contains("czyWyswietlicDostepMobilny")) { - when { - text.contains("Identyfikator zgłoszenia") -> ERROR_IDZIENNIK_WEB_SERVER_ERROR - text.contains("Hasło dostępu do systemu wygasło") -> ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED - text.contains("Trwają prace konserwacyjne") -> ERROR_IDZIENNIK_WEB_MAINTENANCE - else -> ERROR_IDZIENNIK_WEB_OTHER - }.let { errorCode -> - data.error(ApiError(TAG, errorCode) - .withApiResponse(text) - .withResponse(response)) - return - } - } - - try { - onSuccess(text) - } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_IDZIENNIK_WEB_REQUEST) - .withResponse(response) - .withThrowable(e) - .withApiResponse(text)) - } - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(tag, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - Request.builder() - .url("$IDZIENNIK_WEB_URL/$endpoint") - .userAgent(IDZIENNIK_USER_AGENT) - .apply { - if (parameters.isEmpty()) get() - else post() - - parameters.map { (name, value) -> - addParameter(name, value) - } - } - .callback(callback) - .build() - .enqueue() - } - - fun webGetFile(tag: String, endpoint: String, targetFile: File, parameters: Map, - onSuccess: (file: File) -> Unit, onProgress: (written: Long, total: Long) -> Unit) { - - d(tag, "Request: Idziennik/Web - $IDZIENNIK_WEB_URL/$endpoint") - - val callback = object : FileCallbackHandler(targetFile) { - override fun onSuccess(file: File?, response: Response?) { - if (file == null) { - data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD) - .withResponse(response)) - return - } - - try { - onSuccess(file) - } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_EDUDZIENNIK_FILE_REQUEST) - .withResponse(response) - .withThrowable(e)) - } - } - - override fun onProgress(bytesWritten: Long, bytesTotal: Long) { - try { - onProgress(bytesWritten, bytesTotal) - } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_EDUDZIENNIK_FILE_REQUEST) - .withThrowable(e)) - } - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(tag, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - Request.builder() - .url("$IDZIENNIK_WEB_URL/$endpoint") - .userAgent(IDZIENNIK_USER_AGENT) - .apply { - parameters.forEach { (k, v) -> addParameter(k, v) } - } - .contentType("application/x-www-form-urlencoded") - .post() - .callback(callback) - .build() - .enqueue() - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt deleted file mode 100644 index d5e59596..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-29. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api - -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.DAY -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_API_CURRENT_REGISTER -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi -import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.getInt -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.models.Date -import pl.szczodrzynski.edziennik.utils.models.Time - -class IdziennikApiCurrentRegister(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikApi(data, lastSync) { - companion object { - private const val TAG = "IdziennikApiCurrentRegister" - } - - init { - apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json -> - if (json !is JsonObject) { - onSuccess(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER) - return@apiGet - } - - var nextSync = System.currentTimeMillis() + 14*DAY*1000 - - val settings = json.getJsonObject("ustawienia")?.apply { - getString("poczatekSemestru1")?.let { profile?.dateSemester1Start = Date.fromY_m_d(it) } - getString("koniecSemestru1")?.let { profile?.dateSemester2Start = Date.fromY_m_d(it).stepForward(0, 0, 1) } - getString("koniecSemestru2")?.let { profile?.dateYearEnd = Date.fromY_m_d(it) } - } - - json.getInt("szczesliwyNumerek")?.let { luckyNumber -> - val luckyNumberDate = Date.getToday() - settings.getString("godzinaPublikacjiSzczesliwegoLosu") - ?.let { Time.fromH_m(it) } - ?.let { publishTime -> - val now = Time.getNow() - if (publishTime.value < 150000 && now.value < publishTime.value) { - nextSync = luckyNumberDate.combineWith(publishTime) - luckyNumberDate.stepForward(0, 0, -1) // the lucky number is still for yesterday - } - else if (publishTime.value >= 150000 && now.value > publishTime.value) { - luckyNumberDate.stepForward(0, 0, 1) // the lucky number is already for tomorrow - nextSync = luckyNumberDate.combineWith(publishTime) - } - else if (publishTime.value < 150000) { - nextSync = luckyNumberDate - .clone() - .stepForward(0, 0, 1) - .combineWith(publishTime) - } - else { - nextSync = luckyNumberDate.combineWith(publishTime) - } - } - - - val luckyNumberObject = LuckyNumber( - profileId = data.profileId, - date = luckyNumberDate, - number = luckyNumber - ) - - data.luckyNumberList.add(luckyNumberObject) - data.metadataList.add( - Metadata( - profileId, - Metadata.TYPE_LUCKY_NUMBER, - luckyNumberObject.date.value.toLong(), - true, - data.profile?.empty ?: false - )) - } - - - data.setSyncNext(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER, syncAt = nextSync) - onSuccess(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt deleted file mode 100644 index 622068e2..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-30. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api - -import com.google.gson.JsonArray -import pl.szczodrzynski.edziennik.asJsonObjectList -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_API_MESSAGES_INBOX -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi -import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.getBoolean -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.Utils.crc32 -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikApiMessagesInbox(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikApi(data, lastSync) { - companion object { - private const val TAG = "IdziennikApiMessagesInbox" - } - - init { - apiGet(TAG, IDZIENNIK_API_MESSAGES_INBOX) { json -> - if (json !is JsonArray) { - onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX) - return@apiGet - } - - json.asJsonObjectList().forEach { jMessage -> - val subject = jMessage.getString("tytul") ?: "" - if (subject.contains("(") && subject.startsWith("iDziennik - ")) - return@forEach - if (subject.startsWith("Uwaga dla ucznia (klasa:")) - return@forEach - - val messageIdStr = jMessage.getString("id") - val messageId = crc32((messageIdStr + "0").toByteArray()) - - var body = "[META:$messageIdStr;-1]" - body += jMessage.getString("tresc")?.replace("\n".toRegex(), "
") - - val readDate = if (jMessage.getBoolean("odczytana") == true) Date.fromIso(jMessage.getString("wersjaRekordu")) else 0 - val sentDate = Date.fromIso(jMessage.getString("dataWyslania")) - - val sender = jMessage.getAsJsonObject("nadawca") - var firstName = sender.getString("imie") - var lastName = sender.getString("nazwisko") - if (firstName.isNullOrEmpty() || lastName.isNullOrEmpty()) { - firstName = "usunięty" - lastName = "użytkownik" - } - val rTeacher = data.getTeacher( - firstName, - lastName - ) - rTeacher.loginId = /*sender.getString("id") + ":" + */sender.getString("usr") - rTeacher.setTeacherType(Teacher.TYPE_OTHER) - - val message = Message( - profileId = profileId, - id = messageId, - type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED, - subject = subject, - body = body, - senderId = rTeacher.id, - addedDate = sentDate - ) - - val messageRecipient = MessageRecipient( - profileId, - -1 /* me */, - -1, - readDate, - /*messageId*/ messageId - ) - - data.messageList.add(message) - data.messageRecipientList.add(messageRecipient) - data.setSeenMetadataList.add(Metadata( - profileId, - Metadata.TYPE_MESSAGE, - message.id, - readDate > 0, - readDate > 0 || profile?.empty ?: false - )) - } - - data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt deleted file mode 100644 index 87b3264d..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-30. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api - -import com.google.gson.JsonArray -import pl.szczodrzynski.edziennik.DAY -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES -import pl.szczodrzynski.edziennik.asJsonObjectList -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_API_MESSAGES_SENT -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_SENT -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi -import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT -import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.utils.Utils.crc32 -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikApiMessagesSent(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikApi(data, lastSync) { - companion object { - private const val TAG = "IdziennikApiMessagesSent" - } - - init { - apiGet(TAG, IDZIENNIK_API_MESSAGES_SENT) { json -> - if (json !is JsonArray) { - onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT) - return@apiGet - } - - json.asJsonObjectList()?.forEach { jMessage -> - val messageIdStr = jMessage.get("id").asString - val messageId = crc32((messageIdStr + "1").toByteArray()) - - val subject = jMessage.get("tytul").asString - - var body = "[META:$messageIdStr;-1]" - body += jMessage.get("tresc").asString.replace("\n".toRegex(), "
") - - val sentDate = Date.fromIso(jMessage.get("dataWyslania").asString) - - val message = Message( - profileId = profileId, - id = messageId, - type = TYPE_SENT, - subject = subject, - body = body, - senderId = null, - addedDate = sentDate - ) - - for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) { - val recipient = recipientEl.asJsonObject - var firstName = recipient.get("imie").asString - var lastName = recipient.get("nazwisko").asString - if (firstName.isEmpty() || lastName.isEmpty()) { - firstName = "usunięty" - lastName = "użytkownik" - } - val rTeacher = data.getTeacher(firstName, lastName) - rTeacher.loginId = /*recipient.get("id").asString + ":" + */recipient.get("usr").asString - - val messageRecipient = MessageRecipient( - profileId, - rTeacher.id, - -1, - -1, - /*messageId*/ messageId - ) - data.messageRecipientIgnoreList.add(messageRecipient) - } - - data.messageList.add(message) - data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true)) - } - - data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES) - onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAnnouncements.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAnnouncements.kt deleted file mode 100644 index 531cbeeb..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAnnouncements.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-28. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_ANNOUNCEMENTS -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.Announcement -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.getLong -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikWebAnnouncements(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebAnnouncements" - } - - init { - val param = JsonObject() - param.add("parametryFiltrow", JsonArray()) - - webApiGet(TAG, IDZIENNIK_WEB_ANNOUNCEMENTS, mapOf( - "uczenId" to (data.studentId ?: ""), - "param" to param - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - for (jAnnouncementEl in json.getAsJsonArray("ListK")) { - val jAnnouncement = jAnnouncementEl.asJsonObject - // jAnnouncement - val announcementId = jAnnouncement.getLong("Id") ?: -1 - - val rTeacher = data.getTeacherByFirstLast(jAnnouncement.getString("Autor") ?: "") - val addedDate = jAnnouncement.getString("DataDodania")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull() ?: System.currentTimeMillis() - val startDate = jAnnouncement.getString("DataWydarzenia")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull()?.let { Date.fromMillis(it) } - - val announcementObject = Announcement( - profileId = profileId, - id = announcementId, - subject = jAnnouncement.get("Temat").asString, - text = jAnnouncement.get("Tresc").asString, - startDate = startDate, - endDate = null, - teacherId = rTeacher.id, - addedDate = addedDate - ) - data.announcementList.add(announcementObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_ANNOUNCEMENT, - announcementObject.id, - profile?.empty ?: false, - profile?.empty ?: false - )) - } - - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt deleted file mode 100644 index e77c9eac..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-28. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import pl.szczodrzynski.edziennik.crc16 -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_ATTENDANCE -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_ATTENDANCE -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.Attendance -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_BELATED -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT_CUSTOM -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.getInt -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.models.Date -import pl.szczodrzynski.edziennik.utils.models.Time - -class IdziennikWebAttendance(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebAttendance" - } - - private var attendanceYear = Date.getToday().year - private var attendanceMonth = Date.getToday().month - private var attendancePrevMonthChecked = false - - init { - getAttendance() - } - - private fun getAttendance() { - webApiGet(TAG, IDZIENNIK_WEB_ATTENDANCE, mapOf( - "idPozDziennika" to data.registerId, - "mc" to attendanceMonth, - "rok" to attendanceYear, - "dataTygodnia" to "" - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - for (jAttendanceEl in json.getAsJsonArray("Obecnosci")) { - val jAttendance = jAttendanceEl.asJsonObject - // jAttendance - val type = jAttendance.get("TypObecnosci").asInt - - // skip "zajęcia nie odbyły się" and "Ferie" - if (type == 5 || type == 7) - continue - - val date = Date.fromY_m_d(jAttendance.get("Data").asString) - val time = Time.fromH_m(jAttendance.get("OdDoGodziny").asString) - if (date.combineWith(time) > System.currentTimeMillis()) - continue - - val id = jAttendance.get("IdLesson").asString.crc16().toLong() - val rSubject = data.getSubject(jAttendance.get("Przedmiot").asString, jAttendance.get("IdPrzedmiot").asLong, "") - val rTeacher = data.getTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").asString) - - var baseType = TYPE_UNKNOWN - var typeName = "nieznany rodzaj" - var typeSymbol: String? = null - var typeColor: Long? = null - - /* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosciUcznia_lmt637231494660000000.js */ - /* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosci_lmt637231494660000000.css */ - when (type) { - 1 -> { - baseType = TYPE_ABSENT_EXCUSED - typeName = "nieobecność usprawiedliwiona" - typeColor = 0xffffe099 - } - 2 -> { - baseType = TYPE_BELATED - typeName = "spóźnienie" - typeColor = 0xffffffaa - } - 3 -> { - baseType = TYPE_ABSENT - typeName = "nieobecność nieusprawiedliwiona" - typeColor = 0xffffad99 - } - 4, 9 -> { - baseType = TYPE_RELEASED - if (type == 4) { - typeName = "zwolnienie" - typeColor = 0xffa8beff - } - if (type == 9) { - typeName = "zwolniony / obecny" - typeSymbol = "zb" - typeColor = 0xffff69b4 - } - } - 8 -> { - baseType = TYPE_PRESENT_CUSTOM - typeName = "wycieczka" - typeSymbol = "w" - typeColor = null - } - 0 -> { - baseType = TYPE_PRESENT - typeName = "obecny" - typeColor = 0xffccffcc - } - } - - val semester = profile?.dateToSemester(date) ?: 1 - - val attendanceObject = Attendance( - profileId = profileId, - id = id, - baseType = baseType, - typeName = typeName, - typeShort = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType), - typeSymbol = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType), - typeColor = typeColor?.toInt(), - date = date, - startTime = time, - semester = semester, - teacherId = rTeacher.id, - subjectId = rSubject.id - ).also { - it.lessonTopic = jAttendance.getString("PrzedmiotTemat") - it.lessonNumber = jAttendance.getInt("Godzina") - } - - data.attendanceList.add(attendanceObject) - if (attendanceObject.baseType != TYPE_PRESENT) { - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_ATTENDANCE, - attendanceObject.id, - profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN, - profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN - )) - } - } - - val attendanceDateValue = attendanceYear * 10000 + attendanceMonth * 100 - if (profile?.empty == true && attendanceDateValue > profile?.getSemesterStart(1)?.value ?: 99999999) { - attendancePrevMonthChecked = true // do not need to check prev month later - attendanceMonth-- - if (attendanceMonth < 1) { - attendanceMonth = 12 - attendanceYear-- - } - getAttendance() - } else if (!attendancePrevMonthChecked /* get also the previous month */) { - attendanceMonth-- - if (attendanceMonth < 1) { - attendanceMonth = 12 - attendanceYear-- - } - attendancePrevMonthChecked = true - getAttendance() - } else { - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_ATTENDANCE) - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebExams.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebExams.kt deleted file mode 100644 index 25c06945..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebExams.kt +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-28. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_EXAMS -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_EXAMS -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Event -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.utils.models.Date -import java.util.* - -class IdziennikWebExams(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebExams" - } - - private var examsYear = Date.getToday().year - private var examsMonth = Date.getToday().month - private var examsMonthsChecked = 0 - private var examsNextMonthChecked = false // TO DO temporary // no more // idk - - init { - getExams() - } - - private fun getExams() { - val param = JsonObject().apply { - addProperty("strona", 1) - addProperty("iloscNaStrone", "99") - addProperty("iloscRekordow", -1) - addProperty("kolumnaSort", "ss.Nazwa,sp.Data_sprawdzianu") - addProperty("kierunekSort", 0) - addProperty("maxIloscZaznaczonych", 0) - addProperty("panelFiltrow", 0) - } - - webApiGet(TAG, IDZIENNIK_WEB_EXAMS, mapOf( - "idP" to data.registerId, - "rok" to examsYear, - "miesiac" to examsMonth, - "param" to param - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { exam -> - val id = exam.getLong("_recordId") ?: return@forEach - val examDate = Date.fromY_m_d(exam.getString("data") ?: return@forEach) - val subjectName = exam.getString("przedmiot") ?: return@forEach - val subjectId = data.getSubject(subjectName, null, subjectName).id - val teacherName = exam.getString("wpisal") ?: return@forEach - val teacherId = data.getTeacherByLastFirst(teacherName).id - val topic = exam.getString("zakres")?.trim() ?: "" - - val lessonList = data.db.timetableDao().getAllForDateNow(profileId, examDate) - val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime - - val eventType = when (exam.getString("rodzaj")?.toLowerCase(Locale.getDefault())) { - "sprawdzian/praca klasowa", - "sprawdzian", - "praca klasowa" -> Event.TYPE_EXAM - "kartkówka" -> Event.TYPE_SHORT_QUIZ - else -> Event.TYPE_EXAM - } - - val eventObject = Event( - profileId = profileId, - id = id, - date = examDate, - time = startTime, - topic = topic, - color = null, - type = eventType, - teacherId = teacherId, - subjectId = subjectId, - teamId = data.teamClass?.id ?: -1 - ) - - data.eventList.add(eventObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_EVENT, - eventObject.id, - profile?.empty ?: false, - profile?.empty ?: false - )) - } - - if (profile?.empty == true && examsMonthsChecked < 3 /* how many months backwards to check? */) { - examsMonthsChecked++ - examsMonth-- - if (examsMonth < 1) { - examsMonth = 12 - examsYear-- - } - getExams() - } else if (!examsNextMonthChecked /* get also one month forward */) { - val showDate = Date.getToday().stepForward(0, 1, 0) - examsYear = showDate.year - examsMonth = showDate.month - examsNextMonthChecked = true - getExams() - } else { - data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK)) - - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_EXAMS, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_EXAMS) - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt deleted file mode 100644 index b7a462f6..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-12-28 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_ATTACHMENT -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.get -import pl.szczodrzynski.edziennik.utils.Utils -import java.io.File - -class IdziennikWebGetAttachment(override val data: DataIdziennik, - val owner: Any, - val attachmentId: Long, - val attachmentName: String, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - const val TAG = "IdziennikWebGetAttachment" - } - - init { - val message = owner as Message - - val messageId = "\\[META:([A-z0-9]+);([0-9-]+)]".toRegex().find(message.body ?: "")?.get(2) ?: -1 - val targetFile = File(Utils.getStorageDir(), attachmentName) - - webGetFile(TAG, IDZIENNIK_WEB_GET_ATTACHMENT, targetFile, mapOf( - "id" to messageId, - "fileName" to attachmentName - ), { file -> - val event = AttachmentGetEvent( - profileId, - owner, - attachmentId, - AttachmentGetEvent.TYPE_FINISHED, - file.absolutePath - ) - - val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}") - Utils.writeStringToFile(attachmentDataFile, event.fileName) - - EventBus.getDefault().postSticky(event) - - onSuccess() - - }) { written, _ -> - val event = AttachmentGetEvent( - profileId, - owner, - attachmentId, - AttachmentGetEvent.TYPE_PROGRESS, - bytesWritten = written - ) - - EventBus.getDefault().postSticky(event) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomework.kt deleted file mode 100644 index 12d804db..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomework.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-4-1. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_HOMEWORK -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.full.EventFull -import pl.szczodrzynski.edziennik.getBoolean -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.getString - -class IdziennikWebGetHomework(override val data: DataIdziennik, - val event: EventFull, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - private const val TAG = "IdziennikWebGetHomework" - } - - init { - webApiGet(TAG, IDZIENNIK_WEB_GET_HOMEWORK, mapOf( - "idP" to data.registerId, - "idPD" to event.id - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - val homework = json.getJsonObject("praca") ?: return@webApiGet - - if (homework.getBoolean("zalacznik", false)) { - event.attachmentIds = mutableListOf(event.id) - event.attachmentNames = mutableListOf("Załącznik do zadania") - } - else { - event.attachmentIds = mutableListOf() - event.attachmentNames = mutableListOf() - } - event.homeworkBody = homework.getString("tresc") - - data.eventList.add(event) - data.eventListReplace = true - - EventBus.getDefault().postSticky(EventGetEvent(event)) - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomeworkAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomeworkAttachment.kt deleted file mode 100644 index f4a60f98..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomeworkAttachment.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-4-1. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import com.google.gson.JsonObject -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT -import pl.szczodrzynski.edziennik.data.api.Regexes -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Event -import pl.szczodrzynski.edziennik.get -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.set -import pl.szczodrzynski.edziennik.utils.Utils -import java.io.File - -class IdziennikWebGetHomeworkAttachment(override val data: DataIdziennik, - val owner: Any, - val attachmentId: Long, - val attachmentName: String, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - const val TAG = "IdziennikWebGetHomeworkAttachment" - } - - init { - val homework = owner as Event - - /*val request = Request.Builder() - .url("") - .build() - data.app.http.newCall(request).enqueue(object : Callback { - override fun onFailure(call: Call, e: IOException) { - data.error(ApiError(TAG, ERROR_REQUEST_FAILURE) - .withThrowable(e)) - } - - override fun onResponse(call: Call, response: Response) { - val filename = response.header("content-disposition")?.substringAfter("\"")?.substringBeforeLast("\"") - - val file: File = File(Utils.getStorageDir(), filename) - val sink = file.sink().buffer() - response.body()?.source()?.let { - sink.writeAll(it) - } - sink.close() - } - })*/ - - webGet(TAG, IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT) { text -> - val hiddenFields = JsonObject() - Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text).forEach { - hiddenFields[it[1]] = it[2] - } - - webGetFile(TAG, IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT, Utils.getStorageDir(), mapOf( - "__VIEWSTATE" to hiddenFields.getString("__VIEWSTATE", ""), - "__VIEWSTATEGENERATOR" to hiddenFields.getString("__VIEWSTATEGENERATOR", ""), - "__EVENTVALIDATION" to hiddenFields.getString("__EVENTVALIDATION", ""), - "__EVENTTARGET" to "ctl00\$cphContent\$bt_pobraniePliku", - "ctl00\$dxComboUczniowie" to data.registerId, - "ctl00\$cphContent\$idPracyDomowej" to attachmentId - ), { file -> - val event = AttachmentGetEvent( - profileId, - owner, - attachmentId, - AttachmentGetEvent.TYPE_FINISHED, - file.absolutePath - ) - - val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}") - Utils.writeStringToFile(attachmentDataFile, event.fileName) - - homework.attachmentNames = mutableListOf(file.name) - data.eventList.add(homework) - data.eventListReplace = true - - EventBus.getDefault().postSticky(event) - onSuccess() - - }) { written, _ -> - val event = AttachmentGetEvent( - profileId, - owner, - attachmentId, - AttachmentGetEvent.TYPE_PROGRESS, - bytesWritten = written - ) - - EventBus.getDefault().postSticky(event) - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt deleted file mode 100644 index bd1808df..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-12-28 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_MESSAGE -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.full.MessageFull -import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikWebGetMessage(override val data: DataIdziennik, - private val message: MessageFull, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - const val TAG = "IdziennikWebGetMessage" - } - - init { data.profile?.also { profile -> - val metaPattern = "\\[META:([A-z0-9]+);([0-9-]+)]".toRegex() - val meta = metaPattern.find(message.body!!) - val messageIdString = meta?.get(1) ?: "" - - webApiGet(TAG, IDZIENNIK_WEB_GET_MESSAGE, parameters = mapOf( - "idWiadomosci" to messageIdString, - "typWiadomosci" to if (message.type == TYPE_SENT) 1 else 0 - )) { json -> - json.getJsonObject("d")?.getJsonObject("Wiadomosc")?.also { - val id = it.getLong("_recordId") - message.body = message.body?.replace(metaPattern, "[META:$messageIdString;$id]") - - message.clearAttachments() - it.getJsonArray("ListaZal")?.asJsonObjectList()?.forEach { attachment -> - message.addAttachment( - attachment.getLong("Id") ?: return@forEach, - attachment.getString("Nazwa") ?: return@forEach, - -1 - ) - } - - message.recipients?.clear() - when (message.type) { - TYPE_RECEIVED -> { - val recipientObject = MessageRecipientFull( - profileId = profileId, - id = -1, - messageId = message.id - ) - - val readDateString = it.getString("DataOdczytania") - recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis() - else Date.fromIso(readDateString) - - recipientObject.fullName = profile.accountName ?: profile.studentNameLong - - data.messageRecipientList.add(recipientObject) - message.addRecipient(recipientObject) - } - - TYPE_SENT -> { - it.getJsonArray("ListaOdbiorcow")?.asJsonObjectList()?.forEach { recipient -> - val recipientName = recipient.getString("NazwaOdbiorcy") ?: return@forEach - val teacher = data.getTeacherByLastFirst(recipientName) - - val recipientObject = MessageRecipientFull( - profileId = profileId, - id = teacher.id, - messageId = message.id - ) - - recipientObject.readDate = recipient.getLong("Status") ?: return@forEach - recipientObject.fullName = teacher.fullName - - data.messageRecipientList.add(recipientObject) - message.addRecipient(recipientObject) - } - } - } - - if (!message.seen) { - message.seen = true - - data.setSeenMetadataList.add(Metadata( - profileId, - Metadata.TYPE_MESSAGE, - message.id, - message.seen, - message.notified - )) - } - - data.messageList.add(message) - data.messageListReplace = true - - EventBus.getDefault().postSticky(MessageGetEvent(message)) - onSuccess() - } - } - } ?: onSuccess() } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetRecipientList.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetRecipientList.kt deleted file mode 100644 index a14efc24..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetRecipientList.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-12-30. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import androidx.room.OnConflictStrategy -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_RECIPIENT_LIST -import pl.szczodrzynski.edziennik.data.api.Regexes -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.events.RecipientListGetEvent -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.Teacher - -class IdziennikWebGetRecipientList(override val data: DataIdziennik, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - private const val TAG = "IdziennikWebGetRecipientList" - } - - init { - webApiGet(TAG, IDZIENNIK_WEB_GET_RECIPIENT_LIST, mapOf( - "idP" to data.registerId - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - json.getJsonArray("ListK_Pracownicy")?.asJsonObjectList()?.forEach { recipient -> - val name = recipient.getString("ImieNazwisko") ?: ": " - val (fullName, subject) = name.split(": ").let { - Pair(it.getOrNull(0), it.getOrNull(1)) - } - val guid = recipient.getString("Id") ?: "" - // get teacher by ID or create it - val teacher = data.getTeacherByFirstLast(fullName ?: " ") - teacher.loginId = guid - teacher.setTeacherType(Teacher.TYPE_TEACHER) - // unset OTHER that is automatically set in IdziennikApiMessages* - teacher.unsetTeacherType(Teacher.TYPE_OTHER) - teacher.typeDescription = subject - } - - json.getJsonArray("ListK_Opiekunowie")?.asJsonObjectList()?.forEach { recipient -> - val name = recipient.getString("ImieNazwisko") ?: ": " - val (fullName, parentOf) = Regexes.IDZIENNIK_MESSAGES_RECIPIENT_PARENT.find(name)?.let { - Pair(it.groupValues.getOrNull(1), it.groupValues.getOrNull(2)) - } ?: Pair(null, null) - val guid = recipient.getString("Id") ?: "" - // get teacher by ID or create it - val teacher = data.getTeacherByFirstLast(fullName ?: " ") - teacher.loginId = guid - teacher.setTeacherType(Teacher.TYPE_PARENT) - // unset OTHER that is automatically set in IdziennikApiMessages* - teacher.unsetTeacherType(Teacher.TYPE_OTHER) - teacher.typeDescription = parentOf - } - - val event = RecipientListGetEvent( - data.profileId, - data.teacherList.filter { it.loginId != null } - ) - - profile?.lastReceiversSync = System.currentTimeMillis() - - data.teacherOnConflictStrategy = OnConflictStrategy.REPLACE - EventBus.getDefault().postSticky(event) - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGrades.kt deleted file mode 100644 index 90e17401..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGrades.kt +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-28. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import android.graphics.Color -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GRADES -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_GRADES -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Grade -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikWebGrades(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebGrades" - } - - init { data.profile?.also { profile -> - webApiGet(TAG, IDZIENNIK_WEB_GRADES, mapOf( - "idPozDziennika" to data.registerId - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - json.getJsonArray("Przedmioty")?.asJsonObjectList()?.onEach { subjectJson -> - val subject = data.getSubject( - subjectJson.getString("Przedmiot") ?: return@onEach, - subjectJson.getLong("IdPrzedmiotu") ?: return@onEach, - subjectJson.getString("Przedmiot") ?: return@onEach - ) - subjectJson.getJsonArray("Oceny")?.asJsonObjectList()?.forEach { grade -> - val id = grade.getLong("idK") ?: return@forEach - val category = grade.getString("Kategoria") ?: "" - val name = grade.getString("Ocena") ?: "?" - val semester = grade.getInt("Semestr") ?: 1 - val teacher = data.getTeacherByLastFirst(grade.getString("Wystawil") ?: return@forEach) - - val countToAverage = grade.getBoolean("DoSredniej") ?: true - var value = grade.getFloat("WartoscDoSred") ?: 0.0f - val weight = if (countToAverage) - grade.getFloat("Waga") ?: 0.0f - else - 0.0f - - val gradeColor = grade.getString("Kolor") ?: "" - var colorInt = 0xff2196f3.toInt() - if (gradeColor.isNotEmpty()) { - colorInt = Color.parseColor("#$gradeColor") - } - - val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis() - - val gradeObject = Grade( - profileId = profileId, - id = id, - name = name, - type = TYPE_NORMAL, - value = value, - weight = weight, - color = colorInt, - category = category, - description = null, - comment = null, - semester = semester, - teacherId = teacher.id, - subjectId = subject.id, - addedDate = addedDate - ) - - when (grade.getInt("Typ")) { - 0 -> { - val history = grade.getJsonArray("Historia")?.asJsonObjectList() - if (history?.isNotEmpty() == true) { - var sum = gradeObject.value * gradeObject.weight - var count = gradeObject.weight - for (historyItem in history) { - val countToTheAverage = historyItem.getBoolean("DoSredniej") ?: false - value = historyItem.get("WartoscDoSred").asFloat - val weight = historyItem.get("Waga").asFloat - - if (value > 0 && countToTheAverage) { - sum += value * weight - count += weight - } - - val historyColor = historyItem.getString("Kolor") ?: "" - colorInt = 0xff2196f3.toInt() - if (historyColor.isNotEmpty()) { - colorInt = Color.parseColor("#$historyColor") - } - - val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis() - - val historyObject = Grade( - profileId = profileId, - id = gradeObject.id * -1, - name = historyItem.getString("Ocena") ?: "", - type = TYPE_NORMAL, - value = value, - weight = if (value > 0f && countToTheAverage) weight * -1f else 0f, - color = colorInt, - category = historyItem.getString("Kategoria"), - description = historyItem.getString("Uzasadnienie"), - comment = null, - semester = historyItem.getInt("Semestr") ?: 1, - teacherId = teacher.id, - subjectId = subject.id, - addedDate = addedDate - ) - historyObject.parentId = gradeObject.id - - data.gradeList.add(historyObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_GRADE, - historyObject.id, - true, - true - )) - } - // update the current grade's value with an average of all historical grades and itself - if (sum > 0 && count > 0) { - gradeObject.value = sum / count - } - gradeObject.isImprovement = true // gradeObject is the improved grade. Originals are historyObjects - } - } - 1 -> { - gradeObject.type = Grade.TYPE_SEMESTER1_FINAL - gradeObject.name = value.toInt().toString() - gradeObject.weight = 0f - } - 2 -> { - gradeObject.type = Grade.TYPE_YEAR_FINAL - gradeObject.name = value.toInt().toString() - gradeObject.weight = 0f - } - } - - data.gradeList.add(gradeObject) - data.metadataList.add( - Metadata( - profileId, - Metadata.TYPE_GRADE, - id, - data.profile.empty, - data.profile.empty - )) - } - } - - data.toRemove.addAll(listOf( - Grade.TYPE_NORMAL, - Grade.TYPE_SEMESTER1_FINAL, - Grade.TYPE_YEAR_FINAL - ).map { - DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it) - }) - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_GRADES, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_GRADES) - } - } ?: onSuccess(ENDPOINT_IDZIENNIK_WEB_GRADES) } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebHomework.kt deleted file mode 100644 index 10b4a0c3..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebHomework.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-11-25 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_HOMEWORK -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_HOMEWORK -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Event -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikWebHomework(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebHomework" - } - - init { - val param = JsonObject().apply { - addProperty("strona", 1) - addProperty("iloscNaStrone", 997) - addProperty("iloscRekordow", -1) - addProperty("kolumnaSort", "DataZadania") - addProperty("kierunekSort", 0) - addProperty("maxIloscZaznaczonych", 0) - addProperty("panelFiltrow", 0) - } - - webApiGet(TAG, IDZIENNIK_WEB_HOMEWORK, mapOf( - "idP" to data.registerId, - "data" to Date.getToday().stringY_m_d, - "wszystkie" to true, - "param" to param - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { homework -> - val id = homework.getLong("_recordId") ?: return@forEach - val eventDate = Date.fromY_m_d(homework.getString("dataO") ?: return@forEach) - val addedDate = Date.fromY_m_d(homework.getString("dataZ") ?: return@forEach) - val subjectName = homework.getString("przed") ?: return@forEach - val subjectId = data.getSubject(subjectName, null, subjectName).id - val teacherName = homework.getString("usr") ?: return@forEach - val teacherId = data.getTeacherByLastFirst(teacherName).id - val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate) - val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime - val topic = homework.getString("tytul")?.trim() ?: "" - - val seen = when (profile?.empty) { - true -> true - else -> eventDate < Date.getToday() - } - - - val eventObject = Event( - profileId = profileId, - id = id, - date = eventDate, - time = startTime, - topic = topic, - color = null, - type = Event.TYPE_HOMEWORK, - teacherId = teacherId, - subjectId = subjectId, - teamId = data.teamClass?.id ?: -1, - addedDate = addedDate.inMillis - ) - - data.eventList.add(eventObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_HOMEWORK, - eventObject.id, - seen, - seen - )) - } - - data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK)) - - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_HOMEWORK) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebNotices.kt deleted file mode 100644 index 64108bfd..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebNotices.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-28. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import pl.szczodrzynski.edziennik.crc16 -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_NOTICES -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_NOTICES -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Notice -import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEGATIVE -import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEUTRAL -import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_POSITIVE -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikWebNotices(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebNotices" - } - - init { - webApiGet(TAG, IDZIENNIK_WEB_NOTICES, mapOf( - "idPozDziennika" to data.registerId - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - for (jNoticeEl in json.getAsJsonArray("SUwaga")) { - val jNotice = jNoticeEl.asJsonObject - // jNotice - val noticeId = jNotice.get("id").asString.crc16().toLong() - - val rTeacher = data.getTeacherByLastFirst(jNotice.get("Nauczyciel").asString) - val addedDate = Date.fromY_m_d(jNotice.get("Data").asString) - - var nType = TYPE_NEUTRAL - val jType = jNotice.get("Typ").asString - if (jType == "n") { - nType = TYPE_NEGATIVE - } else if (jType == "p") { - nType = TYPE_POSITIVE - } - - val noticeObject = Notice( - profileId = profileId, - id = noticeId, - type = nType, - semester = jNotice.get("Semestr").asInt, - text = jNotice.getString("Tresc") ?: "", - category = null, - points = null, - teacherId = rTeacher.id, - addedDate = addedDate.inMillis - ) - - data.noticeList.add(noticeObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_NOTICE, - noticeObject.id, - profile?.empty ?: false, - profile?.empty ?: false - )) - } - - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_NOTICES, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_NOTICES) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebProposedGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebProposedGrades.kt deleted file mode 100644 index b23e9f98..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebProposedGrades.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-28. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import pl.szczodrzynski.edziennik.asJsonObjectList -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_MISSING_GRADES -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Grade -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_DESCRIPTIVE -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_PROPOSED -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.getJsonArray -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.getString - -class IdziennikWebProposedGrades(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebProposedGrades" - } - - init { data.profile?.also { profile -> - webApiGet(TAG, IDZIENNIK_WEB_MISSING_GRADES, mapOf( - "idPozDziennika" to data.registerId - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - val manager = data.app.gradesManager - - json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { subject -> - val subjectName = subject.getString("Przedmiot") ?: return@forEach - val subjectObject = data.getSubject(subjectName, null, subjectName) - - val semester1Proposed = subject.getString("OcenaSem1") ?: "" - val semester1Value = manager.getGradeValue(semester1Proposed) - val semester1Id = subjectObject.id * (-100) - 1 - val semester1Type = - if (semester1Value == 0f) TYPE_DESCRIPTIVE - else TYPE_SEMESTER1_PROPOSED - val semester1Name = when { - semester1Value == 0f -> " " - semester1Value % 1.0f == 0f -> semester1Value.toInt().toString() - else -> semester1Value.toString() - } - val semester1Color = - if (semester1Value == 0f) 0xff536dfe.toInt() - else -1 - - val semester2Proposed = subject.getString("OcenaSem2") ?: "" - val semester2Value = manager.getGradeValue(semester2Proposed) - val semester2Id = subjectObject.id * (-100) - 2 - val semester2Type = - if (semester2Value == 0f) TYPE_DESCRIPTIVE - else TYPE_YEAR_PROPOSED - val semester2Name = when { - semester2Value == 0f -> " " - semester2Value % 1.0f == 0f -> semester2Value.toInt().toString() - else -> semester2Value.toString() - } - val semester2Color = - if (semester2Value == 0f) 0xffff4081.toInt() - else -1 - - if (semester1Proposed != "") { - val addedDate = if (data.profile.empty) - data.profile.dateSemester1Start.inMillis - else - System.currentTimeMillis() - - val gradeObject = Grade( - profileId = profileId, - id = semester1Id, - name = semester1Name, - type = semester1Type, - value = semester1Value, - weight = 0f, - color = semester1Color, - category = if (semester1Value == 0f) "Ocena opisowa semestralna" else null, - description = if (semester1Value == 0f) semester1Proposed else null, - comment = null, - semester = 1, - teacherId = -1, - subjectId = subjectObject.id, - addedDate = addedDate - ) - - data.gradeList.add(gradeObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_GRADE, - gradeObject.id, - profile.empty, - profile.empty - )) - } - - if (semester2Proposed != "") { - val addedDate = if (data.profile.empty) - data.profile.dateSemester2Start.inMillis - else - System.currentTimeMillis() - - val gradeObject = Grade( - profileId = profileId, - id = semester2Id, - name = semester2Name, - type = semester2Type, - value = semester2Value, - weight = 0f, - color = semester2Color, - category = if (semester2Value == 0f) "Ocena opisowa końcoworoczna" else null, - description = if (semester2Value == 0f) semester2Proposed else null, - comment = null, - semester = 2, - teacherId = -1, - subjectId = subjectObject.id, - addedDate = addedDate - ) - - data.gradeList.add(gradeObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_GRADE, - gradeObject.id, - profile.empty, - profile.empty - )) - } - } - - data.toRemove.addAll(listOf(TYPE_SEMESTER1_PROPOSED, TYPE_YEAR_PROPOSED).map { - DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it) - }) - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES) - } - } ?: onSuccess(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES) } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt deleted file mode 100644 index 343ebcac..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-12-30. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_SEND_MESSAGE -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiMessagesSent -import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Teacher -import java.util.* - -class IdziennikWebSendMessage(override val data: DataIdziennik, - val recipients: List, - val subject: String, - val text: String, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - private const val TAG = "IdziennikWebSendMessage" - } - - init { - val recipientsArray = JsonArray() - for (teacher in recipients) { - teacher.loginId?.let { - recipientsArray += it - } - } - - webApiGet(TAG, IDZIENNIK_WEB_SEND_MESSAGE, mapOf( - "Wiadomosc" to JsonObject( - "Tytul" to subject, - "Tresc" to text, - "Confirmation" to false, - "GuidMessage" to UUID.randomUUID().toString().toUpperCase(Locale.ROOT), - "Odbiorcy" to recipientsArray - ) - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - if (json.getBoolean("CzyJestBlad") != false) { - // TODO error - return@webApiGet - } - - IdziennikApiMessagesSent(data, null) { - val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } - val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } - val event = MessageSentEvent(data.profileId, message, message?.addedDate) - - EventBus.getDefault().postSticky(event) - onSuccess() - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSwitchRegister.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSwitchRegister.kt deleted file mode 100644 index f225f177..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSwitchRegister.kt +++ /dev/null @@ -1,36 +0,0 @@ -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_HOME -import pl.szczodrzynski.edziennik.data.api.Regexes -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.get -import pl.szczodrzynski.edziennik.getString - -class IdziennikWebSwitchRegister(override val data: DataIdziennik, - val registerId: Int, - val onSuccess: () -> Unit -) : IdziennikWeb(data, null) { - companion object { - private const val TAG = "IdziennikWebSwitchRegister" - } - - init { - val hiddenFields = data.loginStore.getLoginData("hiddenFields", JsonObject()) - // TODO error checking - - webGet(TAG, IDZIENNIK_WEB_HOME, mapOf( - "__VIEWSTATE" to hiddenFields.getString("__VIEWSTATE", ""), - "__VIEWSTATEGENERATOR" to hiddenFields.getString("__VIEWSTATEGENERATOR", ""), - "__EVENTVALIDATION" to hiddenFields.getString("__EVENTVALIDATION", ""), - "ctl00\$dxComboUczniowie" to registerId - )) { text -> - Regexes.IDZIENNIK_WEB_SELECTED_REGISTER.find(text)?.let { - val registerId = it[1].toIntOrNull() ?: return@let - data.webSelectedRegister = registerId - } - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt deleted file mode 100644 index e7d293c4..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-11-22 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web - -import androidx.core.util.set -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_TIMETABLE -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_TIMETABLE -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Lesson -import pl.szczodrzynski.edziennik.data.db.entity.LessonRange -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.utils.Utils.d -import pl.szczodrzynski.edziennik.utils.models.Date -import pl.szczodrzynski.edziennik.utils.models.Time -import pl.szczodrzynski.edziennik.utils.models.Week - -class IdziennikWebTimetable(override val data: DataIdziennik, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : IdziennikWeb(data, lastSync) { - companion object { - private const val TAG = "IdziennikWebTimetable" - } - - init { data.profile?.also { profile -> - val currentWeekStart = Week.getWeekStart() - - if (Date.getToday().weekDay > 4) { - currentWeekStart.stepForward(0, 0, 7) - } - - val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d - - val weekStart = Date.fromY_m_d(getDate) - val weekEnd = weekStart.clone().stepForward(0, 0, 6) - - webApiGet(TAG, IDZIENNIK_WEB_TIMETABLE, mapOf( - "idPozDziennika" to data.registerId, - "pidRokSzkolny" to data.schoolYearId, - "data" to "${weekStart.stringY_m_d}T10:00:00.000Z" - )) { result -> - val json = result.getJsonObject("d") ?: run { - data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA) - .withApiResponse(result)) - return@webApiGet - } - - json.getJsonArray("GodzinyLekcyjne")?.asJsonObjectList()?.forEachIndexed { index, range -> - val lessonRange = LessonRange( - profileId, - index + 1, - range.getString("Poczatek")?.let { Time.fromH_m(it) } - ?: return@forEachIndexed, - range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEachIndexed - ) - data.lessonRanges[lessonRange.lessonNumber] = lessonRange - } - - val dates = mutableSetOf() - val lessons = mutableListOf() - - json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { lesson -> - val subject = data.getSubject( - lesson.getString("Nazwa") ?: return@forEach, - lesson.getLong("Id"), - lesson.getString("Skrot") ?: "" - ) - val teacher = data.getTeacherByFDotLast(lesson.getString("Nauczyciel") - ?: return@forEach) - - val newSubjectName = lesson.getString("PrzedmiotZastepujacy") - val newSubject = when (newSubjectName.isNullOrBlank()) { - true -> null - else -> data.getSubject(newSubjectName, null, newSubjectName) - } - - val newTeacherName = lesson.getString("NauZastepujacy") - val newTeacher = when (newTeacherName.isNullOrBlank()) { - true -> null - else -> data.getTeacherByFDotLast(newTeacherName) - } - - val weekDay = lesson.getInt("DzienTygodnia")?.minus(1) ?: return@forEach - val lessonRange = data.lessonRanges[lesson.getInt("Godzina")?.plus(1) - ?: return@forEach] - val lessonDate = weekStart.clone().stepForward(0, 0, weekDay) - val classroom = lesson.getString("NazwaSali") - - val type = lesson.getInt("TypZastepstwa") ?: -1 - - val lessonObject = Lesson(profileId, -1) - - when (type) { - 1, 2, 3, 4, 5 -> { - lessonObject.apply { - this.type = Lesson.TYPE_CHANGE - - this.date = lessonDate - this.lessonNumber = lessonRange.lessonNumber - this.startTime = lessonRange.startTime - this.endTime = lessonRange.endTime - this.subjectId = newSubject?.id - this.teacherId = newTeacher?.id - this.teamId = data.teamClass?.id - this.classroom = classroom - - this.oldDate = lessonDate - this.oldLessonNumber = lessonRange.lessonNumber - this.oldStartTime = lessonRange.startTime - this.oldEndTime = lessonRange.endTime - this.oldSubjectId = subject.id - this.oldTeacherId = teacher.id - this.oldTeamId = data.teamClass?.id - this.oldClassroom = classroom - } - } - 0 -> { - lessonObject.apply { - this.type = Lesson.TYPE_CANCELLED - - this.oldDate = lessonDate - this.oldLessonNumber = lessonRange.lessonNumber - this.oldStartTime = lessonRange.startTime - this.oldEndTime = lessonRange.endTime - this.oldSubjectId = subject.id - this.oldTeacherId = teacher.id - this.oldTeamId = data.teamClass?.id - this.oldClassroom = classroom - } - } - else -> { - lessonObject.apply { - this.type = Lesson.TYPE_NORMAL - - this.date = lessonDate - this.lessonNumber = lessonRange.lessonNumber - this.startTime = lessonRange.startTime - this.endTime = lessonRange.endTime - this.subjectId = subject.id - this.teacherId = teacher.id - this.teamId = data.teamClass?.id - this.classroom = classroom - } - } - } - - lessonObject.id = lessonObject.buildId() - - dates.add(lessonDate.value) - lessons.add(lessonObject) - - val seen = profile.empty || lessonDate < Date.getToday() - - if (lessonObject.type != Lesson.TYPE_NORMAL && lessonDate >= Date.getToday()) { - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_LESSON_CHANGE, - lessonObject.id, - seen, - seen - )) - } - } - - val date: Date = weekStart.clone() - while (date <= weekEnd) { - if (!dates.contains(date.value)) { - lessons.add(Lesson(profileId, date.value.toLong()).apply { - this.type = Lesson.TYPE_NO_LESSONS - this.date = date.clone() - }) - } - - date.stepForward(0, 0, 1) - } - - d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate") - - data.lessonList.addAll(lessons) - data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd)) - - data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS) - onSuccess(ENDPOINT_IDZIENNIK_WEB_TIMETABLE) - } - }} -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt deleted file mode 100644 index 1a07c609..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-27. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR -import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_SETTINGS -import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_IDZIENNIK -import pl.szczodrzynski.edziennik.data.api.Regexes -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginWeb -import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.fixName -import pl.szczodrzynski.edziennik.get -import pl.szczodrzynski.edziennik.set -import pl.szczodrzynski.edziennik.swapFirstLastName - -class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { - companion object { - private const val TAG = "IdziennikFirstLogin" - } - - private val web = IdziennikWeb(data, null) - private val profileList = mutableListOf() - - init { - val loginStoreId = data.loginStore.id - val loginStoreType = LOGIN_TYPE_IDZIENNIK - var firstProfileId = loginStoreId - - IdziennikLoginWeb(data) { - web.webGet(TAG, IDZIENNIK_WEB_SETTINGS) { text -> - //val accounts = json.getJsonArray("accounts") - - val isParent = Regexes.IDZIENNIK_LOGIN_FIRST_IS_PARENT.find(text)?.get(1) != "0" - val accountNameLong = if (isParent) - Regexes.IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME.find(text)?.get(1)?.swapFirstLastName()?.fixName() - else null - - var schoolYearStart: Int? = null - var schoolYearEnd: Int? = null - var schoolYearName: String? = null - val schoolYearId = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let { - schoolYearName = it[2]+"/"+it[3] - schoolYearStart = it[2].toIntOrNull() - schoolYearEnd = it[3].toIntOrNull() - it[1].toIntOrNull() - } ?: run { - data.error(ApiError(TAG, ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR) - .withApiResponse(text)) - return@webGet - } - - Regexes.IDZIENNIK_LOGIN_FIRST_STUDENT.findAll(text) - .toMutableList() - .reversed() - .forEach { match -> - val registerId = match[1].toIntOrNull() ?: return@forEach - val studentId = match[2] - val firstName = match[3] - val lastName = match[4] - val className = match[5] + " " + match[6] - - val studentNameLong = "$firstName $lastName".fixName() - val studentNameShort = "$firstName ${lastName[0]}.".fixName() - val accountName = if (accountNameLong == studentNameLong) null else accountNameLong - - val profile = Profile( - firstProfileId++, - loginStoreId, - loginStoreType, - studentNameLong, - data.webUsername, - studentNameLong, - studentNameShort, - accountName - ).apply { - schoolYearStart?.let { studentSchoolYearStart = it } - studentClassName = className - studentData["studentId"] = studentId - studentData["registerId"] = registerId - studentData["schoolYearId"] = schoolYearId - } - profileList.add(profile) - } - - EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore)) - onSuccess() - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLogin.kt deleted file mode 100644 index e1cef5c1..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLogin.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-25. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login - -import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_API -import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_WEB -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.utils.Utils - -class IdziennikLogin(val data: DataIdziennik, val onSuccess: () -> Unit) { - companion object { - private const val TAG = "IdziennikLogin" - } - - private var cancelled = false - - init { - nextLoginMethod(onSuccess) - } - - private fun nextLoginMethod(onSuccess: () -> Unit) { - if (data.targetLoginMethodIds.isEmpty()) { - onSuccess() - return - } - if (cancelled) { - onSuccess() - return - } - useLoginMethod(data.targetLoginMethodIds.removeAt(0)) { usedMethodId -> - data.progress(data.progressStep) - if (usedMethodId != -1) - data.loginMethods.add(usedMethodId) - nextLoginMethod(onSuccess) - } - } - - private fun useLoginMethod(loginMethodId: Int, onSuccess: (usedMethodId: Int) -> Unit) { - // this should never be true - if (data.loginMethods.contains(loginMethodId)) { - onSuccess(-1) - return - } - Utils.d(TAG, "Using login method $loginMethodId") - when (loginMethodId) { - LOGIN_METHOD_IDZIENNIK_WEB -> { - data.startProgress(R.string.edziennik_progress_login_idziennik_web) - IdziennikLoginWeb(data) { onSuccess(loginMethodId) } - } - LOGIN_METHOD_IDZIENNIK_API -> { - data.startProgress(R.string.edziennik_progress_login_idziennik_api) - IdziennikLoginApi(data) { onSuccess(loginMethodId) } - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginApi.kt deleted file mode 100644 index 2afe481d..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginApi.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-27. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login - -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik - -class IdziennikLoginApi(val data: DataIdziennik, val onSuccess: () -> Unit) { - companion object { - private const val TAG = "IdziennikLoginApi" - } - - init { run { - if (data.isApiLoginValid()) { - onSuccess() - } - else { - onSuccess() - } - }} -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginWeb.kt deleted file mode 100644 index a2fd4d03..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginWeb.kt +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-26. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login - -import im.wangchao.mhttp.Request -import im.wangchao.mhttp.Response -import im.wangchao.mhttp.callback.TextCallbackHandler -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.utils.Utils -import pl.szczodrzynski.edziennik.utils.models.Date - -class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) { - companion object { - private const val TAG = "IdziennikLoginWeb" - } - - init { run { - if (data.isWebLoginValid()) { - data.app.cookieJar.set("iuczniowie.progman.pl", "ASP.NET_SessionId_iDziennik", data.webSessionId) - data.app.cookieJar.set("iuczniowie.progman.pl", ".ASPXAUTH", data.webAuth) - onSuccess() - } - else { - data.app.cookieJar.clear("iuczniowie.progman.pl") - if (data.webSchoolName != null && data.webUsername != null && data.webPassword != null) { - loginWithCredentials() - } - else { - data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING)) - } - } - }} - - private fun loginWithCredentials() { - Utils.d(TAG, "Request: Idziennik/Login/Web - $IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN") - - val loginCallback = object : TextCallbackHandler() { - override fun onSuccess(text: String?, response: Response?) { - if (text.isNullOrEmpty()) { - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - // login succeeded: there is a start page - if (text.contains("czyWyswietlicDostepMobilny")) { - val cookies = data.app.cookieJar.getAll("iuczniowie.progman.pl") - run { - data.webSessionId = cookies["ASP.NET_SessionId_iDziennik"] ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION - data.webAuth = cookies[".ASPXAUTH"] ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH - data.apiBearer = cookies["Bearer"]?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER - data.loginExpiryTime = response.getUnixDate() + 30 * MINUTE /* after about 40 minutes the login didn't work already */ - data.apiExpiryTime = response.getUnixDate() + 12 * HOUR /* actually it expires after 24 hours but I'm not sure when does the token refresh. */ - - val hiddenFields = JsonObject() - Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text).forEach { - hiddenFields[it[1]] = it[2] - } - data.loginStore.putLoginData("hiddenFields", hiddenFields) - - Regexes.IDZIENNIK_WEB_SELECTED_REGISTER.find(text)?.let { - val registerId = it[1].toIntOrNull() ?: return@let - data.webSelectedRegister = registerId - } - - // for profiles created after archiving - data.schoolYearId = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let { - it[1].toIntOrNull() - } ?: data.schoolYearId - data.profile?.studentClassName = Regexes.IDZIENNIK_LOGIN_FIRST_STUDENT.findAll(text) - .firstOrNull { it[1].toIntOrNull() == data.registerId } - ?.let { "${it[5]} ${it[6]}" } ?: data.profile?.studentClassName - - data.profile?.let { profile -> - Regexes.IDZIENNIK_WEB_LUCKY_NUMBER.find(text)?.also { - val number = it[1].toIntOrNull() ?: return@also - val luckyNumberObject = LuckyNumber( - profileId = data.profileId, - date = Date.getToday(), - number = number - ) - - data.luckyNumberList.add(luckyNumberObject) - data.metadataList.add( - Metadata( - profile.id, - Metadata.TYPE_LUCKY_NUMBER, - luckyNumberObject.date.value.toLong(), - true, - profile.empty - )) - } - } - - return@run null - }?.let { errorCode -> - data.error(ApiError(TAG, errorCode) - .withApiResponse(text) - .withResponse(response)) - return - } - - onSuccess() - return - } - - val errorText = Regexes.IDZIENNIK_LOGIN_ERROR.find(text)?.get(1) - when { - errorText?.contains("nieprawidłową nazwę szkoły") == true -> ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME - errorText?.contains("nieprawidłowy login lub hasło") == true -> ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN - text.contains("Identyfikator zgłoszenia") -> ERROR_LOGIN_IDZIENNIK_WEB_SERVER_ERROR - text.contains("Hasło dostępu do systemu wygasło") -> ERROR_LOGIN_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED - text.contains("Trwają prace konserwacyjne") -> ERROR_LOGIN_IDZIENNIK_WEB_MAINTENANCE - else -> ERROR_LOGIN_IDZIENNIK_WEB_OTHER - }.let { errorCode -> - data.error(ApiError(TAG, errorCode) - .withApiResponse(text) - .withResponse(response)) - return - } - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(TAG, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - val getCallback = object : TextCallbackHandler() { - override fun onSuccess(text: String?, response: Response?) { - Request.builder() - .url("$IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN") - .userAgent(IDZIENNIK_USER_AGENT) - .addHeader("Origin", "https://iuczniowie.progman.pl") - .addHeader("Referer", "$IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN") - .apply { - Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text ?: return@apply).forEach { - addParameter(it[1], it[2]) - } - } - .addParameter("ctl00\$ContentPlaceHolder\$nazwaPrzegladarki", IDZIENNIK_USER_AGENT) - .addParameter("ctl00\$ContentPlaceHolder\$NazwaSzkoly", data.webSchoolName) - .addParameter("ctl00\$ContentPlaceHolder\$UserName", data.webUsername) - .addParameter("ctl00\$ContentPlaceHolder\$Password", data.webPassword) - .addParameter("ctl00\$ContentPlaceHolder\$captcha", "") - .addParameter("ctl00\$ContentPlaceHolder\$Logowanie", "Zaloguj") - .post() - .allowErrorCode(502) - .callback(loginCallback) - .build() - .enqueue() - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(TAG, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - Request.builder() - .url("$IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN") - .userAgent(IDZIENNIK_USER_AGENT) - .get() - .allowErrorCode(502) - .callback(getCallback) - .build() - .enqueue() - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt index 349c2ea7..f23478b6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt @@ -174,7 +174,7 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik, val topic = lesson[1].substringAfter(" - ", missingDelimiterValue = "").takeIf { it.isNotBlank() } if (topic?.startsWith("Lekcja odwołana: ") == true || entry.isEmpty()) return - val subjectName = lesson[1].substringBefore(" - ") + val subjectName = lesson[1].substringBefore(" - ").trim() //val team = lesson[3] val teacherName = lesson[3].fixName() @@ -188,7 +188,7 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik, } entry = entry.removePrefix(typeSymbol) - var isCounted = true + var isCustom = false val baseType = when (typeSymbol) { "." -> TYPE_PRESENT "|" -> TYPE_ABSENT @@ -196,11 +196,12 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik, "s" -> TYPE_BELATED "z" -> TYPE_RELEASED else -> { - isCounted = false + isCustom = true when (typeSymbol) { "e" -> TYPE_PRESENT_CUSTOM "en" -> TYPE_ABSENT "ep" -> TYPE_PRESENT_CUSTOM + "+ₑ" -> TYPE_ABSENT_EXCUSED else -> TYPE_UNKNOWN } } @@ -210,10 +211,11 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik, "e" -> 0xff673ab7 "en" -> 0xffec407a "ep" -> 0xff4caf50 + "+ₑ" -> 0xff795548 else -> null }?.toInt() - val typeShort = if (isCounted) + val typeShort = if (!isCustom) data.app.attendanceManager.getTypeShort(baseType) else typeSymbol @@ -237,7 +239,6 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik, subjectId = subjectId ).also { it.lessonTopic = topic - it.isCounted = isCounted } data.attendanceList.add(attendanceObject) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt index 105c0943..7282cc2d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt @@ -74,16 +74,16 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik, message.senderId = null content.select("table.spis tr:has(td)")?.forEach { recipientEl -> - val senderEl = recipientEl.select("td:eq(0)").first() + val senderEl = recipientEl.select("td:eq(1)")?.first() ?: return@forEach val senderName = senderEl.text().fixName() val teacher = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName } val receiverId = teacher?.id ?: -1 var readDate = 0L - val isReadEl = recipientEl.select("td:eq(2)").first() - if (isReadEl.ownText() != "NIE") { - val readDateEl = recipientEl.select("td:eq(3) small").first() + val isReadEl = recipientEl.select("td:eq(4)")?.first() ?: return@forEach + if (isReadEl.html().contains("tak")) { + val readDateEl = recipientEl.select("td:eq(5) small")?.first() ?: return@forEach Regexes.MOBIDZIENNIK_MESSAGE_SENT_READ_DATE.find(readDateEl.ownText())?.let { val date = Date( it[3].toIntOrNull() ?: 2019, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt index 9f5fab95..43b67d23 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt @@ -46,7 +46,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik, when (e.tagName()) { "div" -> { Regexes.MOBIDZIENNIK_GRADES_SUBJECT_NAME.find(e.outerHtml())?.let { - subjectName = it[1] + subjectName = it[1].trim() } } "span" -> { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt index 90ba3dd6..55185745 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt @@ -4,28 +4,23 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API +import com.google.gson.JsonObject +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.crc16 +import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_HEBE import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_WEB_MAIN -import pl.szczodrzynski.edziennik.data.api.LOGIN_MODE_VULCAN_API import pl.szczodrzynski.edziennik.data.api.models.Data import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.data.db.entity.Team -import pl.szczodrzynski.edziennik.utils.Utils +import pl.szczodrzynski.edziennik.isNotNullNorEmpty +import pl.szczodrzynski.fslogin.realm.RealmData class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) { - - fun isWebMainLoginValid() = webExpiryTime-30 > currentTimeUnix() - && webAuthCookie.isNotNullNorEmpty() - && webHost.isNotNullNorEmpty() - && webType.isNotNullNorEmpty() - && symbol.isNotNullNorEmpty() - fun isApiLoginValid() = currentSemesterEndDate-30 > currentTimeUnix() - && apiFingerprint[symbol].isNotNullNorEmpty() - && apiPrivateKey[symbol].isNotNullNorEmpty() - && symbol.isNotNullNorEmpty() + fun isWebMainLoginValid() = symbol.isNotNullNorEmpty() + && (webExpiryTime[symbol]?.toLongOrNull() ?: 0) - 30 > currentTimeUnix() + && webAuthCookie[symbol].isNotNullNorEmpty() + && webRealmData != null fun isHebeLoginValid() = hebePublicKey.isNotNullNorEmpty() && hebePrivateKey.isNotNullNorEmpty() && symbol.isNotNullNorEmpty() @@ -35,34 +30,11 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app if (isWebMainLoginValid()) { loginMethods += LOGIN_METHOD_VULCAN_WEB_MAIN } - if (isApiLoginValid()) { - loginMethods += LOGIN_METHOD_VULCAN_API - } if (isHebeLoginValid()) { loginMethods += LOGIN_METHOD_VULCAN_HEBE } } - init { - // during the first sync `profile.studentClassName` is already set - if (loginStore.mode == LOGIN_MODE_VULCAN_API - && teamList.values().none { it.type == Team.TYPE_CLASS }) { - profile?.studentClassName?.also { name -> - val id = Utils.crc16(name.toByteArray()).toLong() - - val teamObject = Team( - profileId, - id, - name, - Team.TYPE_CLASS, - "$schoolCode:$name", - -1 - ) - teamList.put(id, teamObject) - } - } - } - override fun generateUserCode() = "$schoolCode:$studentId" fun buildDeviceId(): String { @@ -224,16 +196,6 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app get() { mApiPin = mApiPin ?: loginStore.getLoginData("apiPin", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiPin ?: mapOf() } set(value) { loginStore.putLoginData("apiPin", app.gson.toJson(value)); mApiPin = value } - private var mApiFingerprint: Map? = null - var apiFingerprint: Map = mapOf() - get() { mApiFingerprint = mApiFingerprint ?: loginStore.getLoginData("apiFingerprint", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiFingerprint ?: mapOf() } - set(value) { loginStore.putLoginData("apiFingerprint", app.gson.toJson(value)); mApiFingerprint = value } - - private var mApiPrivateKey: Map? = null - var apiPrivateKey: Map = mapOf() - get() { mApiPrivateKey = mApiPrivateKey ?: loginStore.getLoginData("apiPrivateKey", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiPrivateKey ?: mapOf() } - set(value) { loginStore.putLoginData("apiPrivateKey", app.gson.toJson(value)); mApiPrivateKey = value } - /* _ _ _ _____ _____ | | | | | | /\ | __ \_ _| | |__| | ___| |__ ___ / \ | |__) || | @@ -297,49 +259,15 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app \/ \/ \___|_.__/ |_| |_____/ |______\___/ \__, |_|_| |_| __/ | |__*/ - /** - * Federation Services login type. - * This might be one of: cufs, adfs, adfslight. - */ - var webType: String? - get() { mWebType = mWebType ?: loginStore.getLoginData("webType", null); return mWebType } - set(value) { loginStore.putLoginData("webType", value); mWebType = value } - private var mWebType: String? = null + var webRealmData: RealmData? + get() { mWebRealmData = mWebRealmData ?: loginStore.getLoginData("webRealmData", JsonObject()).let { + app.gson.fromJson(it, RealmData::class.java) + }; return mWebRealmData } + set(value) { loginStore.putLoginData("webRealmData", app.gson.toJsonTree(value) as JsonObject); mWebRealmData = value } + private var mWebRealmData: RealmData? = null - /** - * Web server providing the federation services login. - * If this is present, WEB_MAIN login is considered as available. - */ - var webHost: String? - get() { mWebHost = mWebHost ?: loginStore.getLoginData("webHost", null); return mWebHost } - set(value) { loginStore.putLoginData("webHost", value); mWebHost = value } - private var mWebHost: String? = null - - /** - * An ID used in ADFS & ADFSLight login types. - */ - var webAdfsId: String? - get() { mWebAdfsId = mWebAdfsId ?: loginStore.getLoginData("webAdfsId", null); return mWebAdfsId } - set(value) { loginStore.putLoginData("webAdfsId", value); mWebAdfsId = value } - private var mWebAdfsId: String? = null - - /** - * A domain override for ADFS Light. - */ - var webAdfsDomain: String? - get() { mWebAdfsDomain = mWebAdfsDomain ?: loginStore.getLoginData("webAdfsDomain", null); return mWebAdfsDomain } - set(value) { loginStore.putLoginData("webAdfsDomain", value); mWebAdfsDomain = value } - private var mWebAdfsDomain: String? = null - - var webIsHttpCufs: Boolean - get() { mWebIsHttpCufs = mWebIsHttpCufs ?: loginStore.getLoginData("webIsHttpCufs", false); return mWebIsHttpCufs ?: false } - set(value) { loginStore.putLoginData("webIsHttpCufs", value); mWebIsHttpCufs = value } - private var mWebIsHttpCufs: Boolean? = null - - var webIsScopedAdfs: Boolean - get() { mWebIsScopedAdfs = mWebIsScopedAdfs ?: loginStore.getLoginData("webIsScopedAdfs", false); return mWebIsScopedAdfs ?: false } - set(value) { loginStore.putLoginData("webIsScopedAdfs", value); mWebIsScopedAdfs = value } - private var mWebIsScopedAdfs: Boolean? = null + val webHost + get() = webRealmData?.host var webEmail: String? get() { mWebEmail = mWebEmail ?: loginStore.getLoginData("webEmail", null); return mWebEmail } @@ -359,24 +287,24 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app * If the time passes, the certificate needs to be POSTed again (if valid) * or re-generated. */ - var webExpiryTime: Long - get() { mWebExpiryTime = mWebExpiryTime ?: profile?.getStudentData("webExpiryTime", 0L); return mWebExpiryTime ?: 0L } - set(value) { profile?.putStudentData("webExpiryTime", value); mWebExpiryTime = value } - private var mWebExpiryTime: Long? = null + var webExpiryTime: Map = mapOf() + get() { mWebExpiryTime = mWebExpiryTime ?: loginStore.getLoginData("webExpiryTime", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mWebExpiryTime ?: mapOf() } + set(value) { loginStore.putLoginData("webExpiryTime", app.gson.toJson(value)); mWebExpiryTime = value } + private var mWebExpiryTime: Map? = null /** * EfebSsoAuthCookie retrieved after posting a certificate */ - var webAuthCookie: String? - get() { mWebAuthCookie = mWebAuthCookie ?: profile?.getStudentData("webAuthCookie", null); return mWebAuthCookie } - set(value) { profile?.putStudentData("webAuthCookie", value); mWebAuthCookie = value } - private var mWebAuthCookie: String? = null + var webAuthCookie: Map = mapOf() + get() { mWebAuthCookie = mWebAuthCookie ?: loginStore.getLoginData("webAuthCookie", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mWebAuthCookie ?: mapOf() } + set(value) { loginStore.putLoginData("webAuthCookie", app.gson.toJson(value)); mWebAuthCookie = value } + private var mWebAuthCookie: Map? = null /** * Permissions needed to get JSONs from home page */ - var webPermissions: String? - get() { mWebPermissions = mWebPermissions ?: profile?.getStudentData("webPermissions", null); return mWebPermissions } - set(value) { profile?.putStudentData("webPermissions", value); mWebPermissions = value } - private var mWebPermissions: String? = null + var webPermissions: Map = mapOf() + get() { mWebPermissions = mWebPermissions ?: loginStore.getLoginData("webPermissions", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mWebPermissions ?: mapOf() } + set(value) { loginStore.putLoginData("webPermissions", app.gson.toJson(value)); mWebPermissions = value } + private var mWebPermissions: Map? = null } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt index 9dfc1572..d066aca0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt @@ -10,10 +10,8 @@ import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.helper.OneDriveDownloadAttachment import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanData -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiAttachments -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiMessagesChangeStatus -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiSendMessage import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.VulcanHebeMessagesChangeStatus +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.VulcanHebeSendMessage import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin.VulcanFirstLogin import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLogin import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent @@ -68,6 +66,11 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va } private fun login(loginMethodId: Int? = null, afterLogin: (() -> Unit)? = null) { + if (data.loginStore.mode == LOGIN_MODE_VULCAN_API) { + data.error(TAG, ERROR_VULCAN_API_DEPRECATED) + return + } + d(TAG, "Trying to login with ${data.targetLoginMethodIds}") if (internalErrorList.isNotEmpty()) { d(TAG, " - Internal errors:") @@ -92,51 +95,21 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va } override fun getMessage(message: MessageFull) { - if (loginStore.mode != LOGIN_MODE_VULCAN_API) { - login(LOGIN_METHOD_VULCAN_HEBE) { - if (message.seen) { - EventBus.getDefault().postSticky(MessageGetEvent(message)) - completed() - return@login - } - VulcanHebeMessagesChangeStatus(data, message) { - completed() - } - } - return - } - - login(LOGIN_METHOD_VULCAN_API) { - if (message.attachmentIds != null) { - VulcanApiMessagesChangeStatus(data, message) { - completed() - } + login(LOGIN_METHOD_VULCAN_HEBE) { + if (message.seen) { + EventBus.getDefault().postSticky(MessageGetEvent(message)) + completed() return@login } - val list = data.app.db.messageDao().getAllNow(data.profileId) - VulcanApiAttachments(data, list, message, MessageFull::class) { _ -> - list.forEach { - if (it.attachmentIds == null) - it.attachmentIds = mutableListOf() - data.messageList.add(it) - } - data.messageListReplace = true - - if (message.seen) { - EventBus.getDefault().postSticky(MessageGetEvent(message)) - completed() - return@VulcanApiAttachments - } - VulcanApiMessagesChangeStatus(data, message) { - completed() - } + VulcanHebeMessagesChangeStatus(data, message) { + completed() } } } override fun sendMessage(recipients: List, subject: String, text: String) { - login(LOGIN_METHOD_VULCAN_API) { - VulcanApiSendMessage(data, recipients, subject, text) { + login(LOGIN_METHOD_VULCAN_HEBE) { + VulcanHebeSendMessage(data, recipients, subject, text) { completed() } } @@ -190,19 +163,10 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va } override fun getEvent(eventFull: EventFull) { - login(LOGIN_METHOD_VULCAN_API) { - val list = data.app.db.eventDao().getAllNow(data.profileId).filter { !it.addedManually } - VulcanApiAttachments(data, list, eventFull, EventFull::class) { _ -> - list.forEach { - it.homeworkBody = "" - data.eventList.add(it) - } - data.eventListReplace = true + eventFull.homeworkBody = "" - EventBus.getDefault().postSticky(EventGetEvent(eventFull)) - completed() - } - } + EventBus.getDefault().postSticky(EventGetEvent(eventFull)) + completed() } override fun firstLogin() { VulcanFirstLogin(data) { completed() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt index 9e247575..2e239a7e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt @@ -7,77 +7,49 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.models.Feature -const val ENDPOINT_VULCAN_API_UPDATE_SEMESTER = 1000 -const val ENDPOINT_VULCAN_API_PUSH_CONFIG = 1005 -const val ENDPOINT_VULCAN_API_DICTIONARIES = 1010 -const val ENDPOINT_VULCAN_API_TIMETABLE = 1020 -const val ENDPOINT_VULCAN_API_EVENTS = 1030 -const val ENDPOINT_VULCAN_API_GRADES = 1040 -const val ENDPOINT_VULCAN_API_GRADES_SUMMARY = 1050 -const val ENDPOINT_VULCAN_API_HOMEWORK = 1060 -const val ENDPOINT_VULCAN_API_NOTICES = 1070 -const val ENDPOINT_VULCAN_API_ATTENDANCE = 1080 -const val ENDPOINT_VULCAN_API_MESSAGES_INBOX = 1090 -const val ENDPOINT_VULCAN_API_MESSAGES_SENT = 1100 const val ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS = 2010 + const val ENDPOINT_VULCAN_HEBE_MAIN = 3000 +const val ENDPOINT_VULCAN_HEBE_PUSH_CONFIG = 3005 const val ENDPOINT_VULCAN_HEBE_ADDRESSBOOK = 3010 const val ENDPOINT_VULCAN_HEBE_TIMETABLE = 3020 const val ENDPOINT_VULCAN_HEBE_EXAMS = 3030 const val ENDPOINT_VULCAN_HEBE_GRADES = 3040 +const val ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY = 3050 const val ENDPOINT_VULCAN_HEBE_HOMEWORK = 3060 +const val ENDPOINT_VULCAN_HEBE_NOTICES = 3070 const val ENDPOINT_VULCAN_HEBE_ATTENDANCE = 3080 const val ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX = 3090 const val ENDPOINT_VULCAN_HEBE_MESSAGES_SENT = 3100 +const val ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER = 3200 val VulcanFeatures = listOf( // timetable - Feature(LOGIN_TYPE_VULCAN, FEATURE_TIMETABLE, listOf( - ENDPOINT_VULCAN_API_TIMETABLE to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), Feature(LOGIN_TYPE_VULCAN, FEATURE_TIMETABLE, listOf( ENDPOINT_VULCAN_HEBE_TIMETABLE to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)), // agenda - Feature(LOGIN_TYPE_VULCAN, FEATURE_AGENDA, listOf( - ENDPOINT_VULCAN_API_EVENTS to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), Feature(LOGIN_TYPE_VULCAN, FEATURE_AGENDA, listOf( ENDPOINT_VULCAN_HEBE_EXAMS to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)), // grades Feature(LOGIN_TYPE_VULCAN, FEATURE_GRADES, listOf( - ENDPOINT_VULCAN_API_GRADES to LOGIN_METHOD_VULCAN_API, - ENDPOINT_VULCAN_API_GRADES_SUMMARY to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_GRADES, listOf( - ENDPOINT_VULCAN_HEBE_GRADES to LOGIN_METHOD_VULCAN_HEBE + ENDPOINT_VULCAN_HEBE_GRADES to LOGIN_METHOD_VULCAN_HEBE, + ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)), // homework - Feature(LOGIN_TYPE_VULCAN, FEATURE_HOMEWORK, listOf( - ENDPOINT_VULCAN_API_HOMEWORK to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), Feature(LOGIN_TYPE_VULCAN, FEATURE_HOMEWORK, listOf( ENDPOINT_VULCAN_HEBE_HOMEWORK to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)), // behaviour Feature(LOGIN_TYPE_VULCAN, FEATURE_BEHAVIOUR, listOf( - ENDPOINT_VULCAN_API_NOTICES to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), + ENDPOINT_VULCAN_HEBE_NOTICES to LOGIN_METHOD_VULCAN_HEBE + ), listOf(LOGIN_METHOD_VULCAN_HEBE)), // attendance - Feature(LOGIN_TYPE_VULCAN, FEATURE_ATTENDANCE, listOf( - ENDPOINT_VULCAN_API_ATTENDANCE to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), Feature(LOGIN_TYPE_VULCAN, FEATURE_ATTENDANCE, listOf( ENDPOINT_VULCAN_HEBE_ATTENDANCE to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)), // messages - Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_INBOX, listOf( - ENDPOINT_VULCAN_API_MESSAGES_INBOX to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_SENT, listOf( - ENDPOINT_VULCAN_API_MESSAGES_SENT to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_INBOX, listOf( ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)), @@ -87,8 +59,8 @@ val VulcanFeatures = listOf( // push config Feature(LOGIN_TYPE_VULCAN, FEATURE_PUSH_CONFIG, listOf( - ENDPOINT_VULCAN_API_PUSH_CONFIG to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)).withShouldSync { data -> + ENDPOINT_VULCAN_HEBE_PUSH_CONFIG to LOGIN_METHOD_VULCAN_HEBE + ), listOf(LOGIN_METHOD_VULCAN_HEBE)).withShouldSync { data -> !data.app.config.sync.tokenVulcanList.contains(data.profileId) }, @@ -97,39 +69,20 @@ val VulcanFeatures = listOf( */ Feature(LOGIN_TYPE_VULCAN, FEATURE_LUCKY_NUMBER, listOf( ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS to LOGIN_METHOD_VULCAN_WEB_MAIN - ), listOf(LOGIN_METHOD_VULCAN_WEB_MAIN)).withShouldSync { data -> data.shouldSyncLuckyNumber() }, + ), listOf(LOGIN_METHOD_VULCAN_WEB_MAIN)) + .withShouldSync { data -> data.shouldSyncLuckyNumber() } + .withPriority(2), + /** + * Lucky number - using Hebe API + */ + Feature(LOGIN_TYPE_VULCAN, FEATURE_LUCKY_NUMBER, listOf( + ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER to LOGIN_METHOD_VULCAN_HEBE + ), listOf(LOGIN_METHOD_VULCAN_HEBE)) + .withShouldSync { data -> data.shouldSyncLuckyNumber() } + .withPriority(1), - Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf( - ENDPOINT_VULCAN_API_UPDATE_SEMESTER to LOGIN_METHOD_VULCAN_API, - ENDPOINT_VULCAN_API_DICTIONARIES to LOGIN_METHOD_VULCAN_API - ), listOf(LOGIN_METHOD_VULCAN_API)), Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf( ENDPOINT_VULCAN_HEBE_MAIN to LOGIN_METHOD_VULCAN_HEBE, ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE ), listOf(LOGIN_METHOD_VULCAN_HEBE)) - /*Feature(LOGIN_TYPE_VULCAN, FEATURE_STUDENT_INFO, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_STUDENT_NUMBER, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_SCHOOL_INFO, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_CLASS_INFO, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_TEAM_INFO, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_TEACHERS, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_SUBJECTS, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)), - Feature(LOGIN_TYPE_VULCAN, FEATURE_CLASSROOMS, listOf( - ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB - ), listOf(LOGIN_METHOD_VULCAN_WEB)),*/ - ) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt deleted file mode 100644 index c500e3e7..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-10-19 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data - -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import im.wangchao.mhttp.Request -import im.wangchao.mhttp.Response -import im.wangchao.mhttp.callback.JsonCallbackHandler -import io.github.wulkanowy.signer.android.signContent -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.utils.Utils.d -import java.net.HttpURLConnection -import java.util.* - -open class VulcanApi(open val data: DataVulcan, open val lastSync: Long?) { - companion object { - const val TAG = "VulcanApi" - } - - val profileId - get() = data.profile?.id ?: -1 - - val profile - get() = data.profile - - fun apiGet( - tag: String, - endpoint: String, - method: Int = POST, - parameters: Map = emptyMap(), - baseUrl: Boolean = false, - onSuccess: (json: JsonObject, response: Response?) -> Unit - ) { - val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint" - - d(tag, "Request: Vulcan/Api - $url") - - val finalPayload = JsonObject() - parameters.map { (name, value) -> - when (value) { - is JsonObject -> finalPayload.add(name, value) - is JsonArray -> finalPayload.add(name, value) - is String -> finalPayload.addProperty(name, value) - is Int -> finalPayload.addProperty(name, value) - is Long -> finalPayload.addProperty(name, value) - is Float -> finalPayload.addProperty(name, value) - is Char -> finalPayload.addProperty(name, value) - is Boolean -> finalPayload.addProperty(name, value) - } - } - finalPayload.addProperty("RemoteMobileTimeKey", System.currentTimeMillis() / 1000) - finalPayload.addProperty("TimeKey", System.currentTimeMillis() / 1000 - 1) - finalPayload.addProperty("RequestId", UUID.randomUUID().toString()) - finalPayload.addProperty("RemoteMobileAppVersion", VULCAN_API_APP_VERSION) - finalPayload.addProperty("RemoteMobileAppName", VULCAN_API_APP_NAME) - - val callback = object : JsonCallbackHandler() { - override fun onSuccess(json: JsonObject?, response: Response?) { - if (json == null && response?.parserErrorBody == null) { - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - if (response?.code() ?: 200 != 200) { - when (response?.code()) { - 503 -> ERROR_VULCAN_API_MAINTENANCE - 400 -> ERROR_VULCAN_API_BAD_REQUEST - else -> ERROR_VULCAN_API_OTHER - }.let { errorCode -> - data.error(ApiError(tag, errorCode) - .withResponse(response) - .withApiResponse(json?.toString() ?: response?.parserErrorBody)) - return - } - } - - if (json == null) { - data.error(ApiError(tag, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - try { - onSuccess(json, response) - } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_VULCAN_API_REQUEST) - .withResponse(response) - .withThrowable(e) - .withApiResponse(json)) - } - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(tag, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - Request.builder() - .url(url) - .userAgent(VULCAN_API_USER_AGENT) - .addHeader("RequestCertificateKey", data.apiFingerprint[data.symbol]) - .addHeader("RequestSignatureValue", - try { - signContent( - data.apiPrivateKey[data.symbol] ?: "", - finalPayload.toString() - ) - } catch (e: Exception) {e.printStackTrace();""}) - .apply { - when (method) { - GET -> get() - POST -> post() - } - } - .setJsonBody(finalPayload) - .allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST) - .allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN) - .allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED) - .allowErrorCode(HttpURLConnection.HTTP_UNAVAILABLE) - .callback(callback) - .build() - .enqueue() - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt index 2fc21190..0724ca46 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt @@ -5,10 +5,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.data.api.ERROR_VULCAN_API_DEPRECATED -import pl.szczodrzynski.edziennik.data.api.LOGIN_MODE_VULCAN_API import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.* -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.* import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web.VulcanWebLuckyNumber import pl.szczodrzynski.edziennik.data.db.entity.Message @@ -22,17 +19,18 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) { private var firstSemesterSync = false private val firstSemesterSyncExclude = listOf( ENDPOINT_VULCAN_HEBE_MAIN, + ENDPOINT_VULCAN_HEBE_PUSH_CONFIG, ENDPOINT_VULCAN_HEBE_ADDRESSBOOK, ENDPOINT_VULCAN_HEBE_TIMETABLE, + ENDPOINT_VULCAN_HEBE_EXAMS, + ENDPOINT_VULCAN_HEBE_HOMEWORK, + ENDPOINT_VULCAN_HEBE_NOTICES, ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX, - ENDPOINT_VULCAN_HEBE_MESSAGES_SENT + ENDPOINT_VULCAN_HEBE_MESSAGES_SENT, + ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER ) - init { run { - if (data.loginStore.mode == LOGIN_MODE_VULCAN_API) { - data.error(TAG, ERROR_VULCAN_API_DEPRECATED) - return@run - } + init { if (data.studentSemesterNumber == 2 && data.profile?.empty != false) { firstSemesterSync = true // set to sync 1st semester first @@ -47,7 +45,7 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) { } onSuccess() } - }} + } private fun nextEndpoint(onSuccess: () -> Unit) { if (data.targetEndpointIds.isEmpty()) { @@ -83,54 +81,6 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) { private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) { Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync") when (endpointId) { - ENDPOINT_VULCAN_API_UPDATE_SEMESTER -> { - data.startProgress(R.string.edziennik_progress_endpoint_student_info) - VulcanApiUpdateSemester(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_PUSH_CONFIG -> { - data.startProgress(R.string.edziennik_progress_endpoint_push_config) - VulcanApiPushConfig(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_DICTIONARIES -> { - data.startProgress(R.string.edziennik_progress_endpoint_dictionaries) - VulcanApiDictionaries(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_GRADES -> { - data.startProgress(R.string.edziennik_progress_endpoint_grades) - VulcanApiGrades(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_GRADES_SUMMARY -> { - data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades) - VulcanApiProposedGrades(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_EVENTS -> { - data.startProgress(R.string.edziennik_progress_endpoint_events) - VulcanApiEvents(data, isHomework = false, lastSync = lastSync, onSuccess = onSuccess) - } - ENDPOINT_VULCAN_API_HOMEWORK -> { - data.startProgress(R.string.edziennik_progress_endpoint_homework) - VulcanApiEvents(data, isHomework = true, lastSync = lastSync, onSuccess = onSuccess) - } - ENDPOINT_VULCAN_API_NOTICES -> { - data.startProgress(R.string.edziennik_progress_endpoint_notices) - VulcanApiNotices(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_ATTENDANCE -> { - data.startProgress(R.string.edziennik_progress_endpoint_attendance) - VulcanApiAttendance(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_TIMETABLE -> { - data.startProgress(R.string.edziennik_progress_endpoint_timetable) - VulcanApiTimetable(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_MESSAGES_INBOX -> { - data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox) - VulcanApiMessagesInbox(data, lastSync, onSuccess) - } - ENDPOINT_VULCAN_API_MESSAGES_SENT -> { - data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox) - VulcanApiMessagesSent(data, lastSync, onSuccess) - } ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS -> { data.startProgress(R.string.edziennik_progress_endpoint_lucky_number) VulcanWebLuckyNumber(data, lastSync, onSuccess) @@ -148,6 +98,10 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) { onSuccess(ENDPOINT_VULCAN_HEBE_MAIN) } } + ENDPOINT_VULCAN_HEBE_PUSH_CONFIG -> { + data.startProgress(R.string.edziennik_progress_endpoint_push_config) + VulcanHebePushConfig(data, lastSync, onSuccess) + } ENDPOINT_VULCAN_HEBE_ADDRESSBOOK -> { data.startProgress(R.string.edziennik_progress_endpoint_teachers) VulcanHebeAddressbook(data, lastSync, onSuccess) @@ -164,10 +118,22 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) { data.startProgress(R.string.edziennik_progress_endpoint_grades) VulcanHebeGrades(data, lastSync, onSuccess) } + ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY -> { + data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades) + VulcanHebeGradeSummary(data, lastSync, onSuccess) + } ENDPOINT_VULCAN_HEBE_HOMEWORK -> { data.startProgress(R.string.edziennik_progress_endpoint_homework) VulcanHebeHomework(data, lastSync, onSuccess) } + ENDPOINT_VULCAN_HEBE_NOTICES -> { + data.startProgress(R.string.edziennik_progress_endpoint_notices) + VulcanHebeNotices(data, lastSync, onSuccess) + } + ENDPOINT_VULCAN_HEBE_ATTENDANCE -> { + data.startProgress(R.string.edziennik_progress_endpoint_attendance) + VulcanHebeAttendance(data, lastSync, onSuccess) + } ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX -> { data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox) VulcanHebeMessages(data, lastSync, onSuccess).getMessages(Message.TYPE_RECEIVED) @@ -176,9 +142,9 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) { data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox) VulcanHebeMessages(data, lastSync, onSuccess).getMessages(Message.TYPE_SENT) } - ENDPOINT_VULCAN_HEBE_ATTENDANCE -> { - data.startProgress(R.string.edziennik_progress_endpoint_attendance) - VulcanHebeAttendance(data, lastSync, onSuccess) + ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER -> { + data.startProgress(R.string.edziennik_progress_endpoint_lucky_number) + VulcanHebeLuckyNumber(data, lastSync, onSuccess) } else -> onSuccess(endpointId) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanHebe.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanHebe.kt index c61140c4..a34e0a1b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanHebe.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanHebe.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-20. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data import android.os.Build @@ -42,7 +46,11 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) { val profile get() = data.profile - fun getDateTime(json: JsonObject?, key: String, default: Long = System.currentTimeMillis()): Long { + fun getDateTime( + json: JsonObject?, + key: String, + default: Long = System.currentTimeMillis() + ): Long { val date = json.getJsonObject(key) return date.getLong("Timestamp") ?: return default } @@ -142,6 +150,18 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) { 2 } + fun isCurrentYear(date: Date): Boolean { + return profile?.let { profile -> + return@let date >= profile.dateSemester1Start + } ?: false + } + + fun isCurrentYear(dateTime: Long): Boolean { + return profile?.let { profile -> + return@let dateTime >= profile.dateSemester1Start.inMillis + } ?: false + } + inline fun apiRequest( tag: String, endpoint: String, @@ -193,27 +213,56 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) { val callback = object : JsonCallbackHandler() { override fun onSuccess(json: JsonObject?, response: Response?) { if (json == null) { - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) + data.error( + ApiError(TAG, ERROR_RESPONSE_EMPTY) .withResponse(response) ) return } val status = json.getJsonObject("Status") - if (status?.getInt("Code") != 0) { - data.error(ApiError(tag, ERROR_VULCAN_HEBE_OTHER) - .withResponse(response) - .withApiResponse(json.toString())) + val statusCode = status?.getInt("Code") ?: 0 + if (statusCode != 0) { + val statusMessage = status?.getString("Message") + val errorCode = when (statusCode) { + -1 -> ERROR_VULCAN_HEBE_SERVER_ERROR + 100 -> ERROR_VULCAN_HEBE_SIGNATURE_ERROR + 101 -> ERROR_VULCAN_HEBE_INVALID_PAYLOAD + 106 -> ERROR_VULCAN_HEBE_FIREBASE_ERROR + 108 -> ERROR_VULCAN_HEBE_CERTIFICATE_GONE + 200 -> when (true) { + statusMessage?.contains("Class") -> ERROR_LOGIN_VULCAN_NO_PUPILS + statusMessage?.contains("Token") -> ERROR_LOGIN_VULCAN_INVALID_TOKEN + else -> ERROR_VULCAN_HEBE_ENTITY_NOT_FOUND + } + 201 -> ERROR_LOGIN_VULCAN_EXPIRED_TOKEN + 203 -> when (json.getJsonObject("Envelope").getInt("AvailableRetries")) { + 2 -> ERROR_LOGIN_VULCAN_INVALID_PIN_2_REMAINING + 1 -> ERROR_LOGIN_VULCAN_INVALID_PIN_1_REMAINING + else -> ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING + } + 204 -> ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING + else -> ERROR_VULCAN_HEBE_OTHER + } + data.error( + ApiError(tag, errorCode) + .withResponse(response) + .withApiResponse(json.toString()) + ) + return } - val envelope = when (T::class.java) { + val envelope = if (json.get("Envelope").isJsonNull && null is T) + null as T + else when (T::class.java) { JsonObject::class.java -> json.getJsonObject("Envelope") as T JsonArray::class.java -> json.getJsonArray("Envelope") as T java.lang.Boolean::class.java -> json.getBoolean("Envelope") as T else -> { - data.error(ApiError(tag, ERROR_RESPONSE_EMPTY) - .withResponse(response) - .withApiResponse(json) + data.error( + ApiError(tag, ERROR_RESPONSE_EMPTY) + .withResponse(response) + .withApiResponse(json) ) return } @@ -222,7 +271,8 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) { try { onSuccess(envelope, response) } catch (e: Exception) { - data.error(ApiError(tag, EXCEPTION_VULCAN_HEBE_REQUEST) + data.error( + ApiError(tag, EXCEPTION_VULCAN_HEBE_REQUEST) .withResponse(response) .withThrowable(e) .withApiResponse(json) @@ -231,7 +281,8 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) { } override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(tag, ERROR_REQUEST_FAILURE) + data.error( + ApiError(tag, ERROR_REQUEST_FAILURE) .withResponse(response) .withThrowable(throwable) ) @@ -347,10 +398,15 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) { if (folder != null) query["folder"] = folder.toString() + val semester1Start = profile?.dateSemester1Start?.inMillis + query["lastId"] = "-2147483648" // don't ask, it's just Vulcan query["pageSize"] = "500" query["lastSyncDate"] = LocalDateTime - .ofInstant(Instant.ofEpochMilli(lastSync ?: 0), ZoneId.systemDefault()) + .ofInstant( + Instant.ofEpochMilli(lastSync ?: semester1Start ?: 0), + ZoneId.systemDefault() + ) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) apiGet(tag, url, query) { json: JsonArray, response -> diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt index 39433657..d32161a6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt @@ -11,12 +11,11 @@ import im.wangchao.mhttp.Request import im.wangchao.mhttp.Response import im.wangchao.mhttp.callback.TextCallbackHandler import pl.droidsonroids.jspoon.Jspoon +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.CufsCertificate import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.get -import pl.szczodrzynski.edziennik.isNotNullNorBlank import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.models.Date import java.io.File @@ -83,10 +82,12 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { onResult(symbol, STATE_NO_REGISTER) return } - if (!validateCallback(text, response, jsonResponse = false)) { + if (!validateCallback(symbol, text, response, jsonResponse = false)) { return } - data.webExpiryTime = Date.fromIso(certificate.expiryDate) / 1000L + data.webExpiryTime = data.webExpiryTime.toMutableMap().also { map -> + map[symbol] = (Date.fromIso(certificate.expiryDate) / 1000L).toString() + } onResult(symbol, STATE_SUCCESS) } @@ -120,7 +121,7 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { fun getStartPage(symbol: String = data.symbol ?: "default", postErrors: Boolean = true, onSuccess: (html: String, schoolSymbols: List) -> Unit) { val callback = object : TextCallbackHandler() { override fun onSuccess(text: String?, response: Response?) { - if (!validateCallback(text, response, jsonResponse = false) || text == null) { + if (!validateCallback(symbol, text, response, jsonResponse = false) || text == null) { return } @@ -136,7 +137,30 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { } } - data.webPermissions = Regexes.VULCAN_WEB_PERMISSIONS.find(text)?.let { it[1] } + data.webPermissions = data.webPermissions.toMutableMap().also { map -> + val permissions = Regexes.VULCAN_WEB_PERMISSIONS.find(text)?.let { it[1] } + if (permissions?.isNotBlank() == true) { + val studentId = permissions.split("|") + .getOrNull(0) + ?.base64DecodeToString() + ?.toJsonObject() + ?.getJsonArray("AuthInfos") + ?.asJsonObjectList() + ?.flatMap { authInfo -> + authInfo.getJsonArray("UczenIds") + ?.map { it.asInt } + ?: listOf() + } + ?.firstOrNull() + ?.toString() + data.app.cookieJar.set( + data.webHost ?: "vulcan.net.pl", + "idBiezacyUczen", + studentId + ) + } + map[symbol] = permissions + } val schoolSymbols = mutableListOf() val clientUrl = "://uonetplus-uczen.${data.webHost}/$symbol/" @@ -144,7 +168,7 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { var count = 0 while (clientIndex != -1 && count < 100) { val startIndex = clientIndex + clientUrl.length - val endIndex = text.indexOf('/', startIndex = startIndex) + val endIndex = text.indexOfAny(charArrayOf('"', '/'), startIndex = startIndex) val schoolSymbol = text.substring(startIndex, endIndex) schoolSymbols += schoolSymbol clientIndex = text.indexOf(clientUrl, startIndex = endIndex) @@ -186,7 +210,7 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { .enqueue() } - private fun validateCallback(text: String?, response: Response?, jsonResponse: Boolean = true): Boolean { + private fun validateCallback(symbol: String, text: String?, response: Response?, jsonResponse: Boolean = true): Boolean { if (text == null) { data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) .withResponse(response)) @@ -207,11 +231,13 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { val cookies = data.app.cookieJar.getAll(data.webHost ?: "vulcan.net.pl") val authCookie = cookies["EfebSsoAuthCookie"] - if ((authCookie == null || authCookie == "null") && data.webAuthCookie != null) { - data.app.cookieJar.set(data.webHost ?: "vulcan.net.pl", "EfebSsoAuthCookie", data.webAuthCookie) + if ((authCookie == null || authCookie == "null") && data.webAuthCookie[symbol] != null) { + data.app.cookieJar.set(data.webHost ?: "vulcan.net.pl", "EfebSsoAuthCookie", data.webAuthCookie[symbol]) } - else if (authCookie.isNotNullNorBlank() && authCookie != "null" && authCookie != data.webAuthCookie) { - data.webAuthCookie = authCookie + else if (authCookie.isNotNullNorBlank() && authCookie != "null" && authCookie != data.webAuthCookie[symbol]) { + data.webAuthCookie = data.webAuthCookie.toMutableMap().also { map -> + map[symbol] = authCookie + } } return true } @@ -250,7 +276,7 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) { val callback = object : TextCallbackHandler() { override fun onSuccess(text: String?, response: Response?) { - if (!validateCallback(text, response)) + if (!validateCallback(data.symbol ?: "default", text, response)) return try { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttachments.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttachments.kt deleted file mode 100644 index a7b2b23b..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttachments.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-4-6. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.asJsonObjectList -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.full.EventFull -import pl.szczodrzynski.edziennik.data.db.full.MessageFull -import pl.szczodrzynski.edziennik.getJsonArray -import pl.szczodrzynski.edziennik.getLong -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.models.Date -import kotlin.reflect.KClass - -class VulcanApiAttachments(override val data: DataVulcan, - val list: List<*>, - val owner: Any?, - val ownerClass: KClass<*>, - val onSuccess: (list: List<*>) -> Unit -) : VulcanApi(data, null) { - companion object { - const val TAG = "VulcanApiAttachments" - } - - init { run { - val endpoint = when (ownerClass) { - MessageFull::class -> VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS - EventFull::class -> VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS - else -> null - } ?: return@run - - val idName = when (ownerClass) { - MessageFull::class -> "IdWiadomosc" - EventFull::class -> "IdZadanieDomowe" - else -> null - } ?: return@run - - val startDate = profile?.getSemesterStart(profile?.currentSemester ?: 1)?.inUnix ?: 0 - val endDate = Date.getToday().stepForward(0, 1, 0).inUnix - - apiGet(TAG, endpoint, parameters = mapOf( - "DataPoczatkowa" to startDate, - "DataKoncowa" to endDate, - "LoginId" to data.studentLoginId, - "IdUczen" to data.studentId - )) { json, _ -> - - json.getJsonArray("Data")?.asJsonObjectList()?.forEach { attachment -> - val id = attachment.getLong("Id") ?: return@forEach - val itemId = attachment.getLong(idName) ?: return@forEach - val url = attachment.getString("Url") ?: return@forEach - val fileName = "${attachment.getString("NazwaPliku")}:$url" - - list.forEach { - if (it is MessageFull - && it.profileId == profileId - && it.id == itemId - && it.attachmentIds?.contains(id) != true) { - if (it.attachmentIds == null) - it.attachmentIds = mutableListOf() - if (it.attachmentNames == null) - it.attachmentNames = mutableListOf() - it.attachmentIds?.add(id) - it.attachmentNames?.add(fileName) - } - - if (it is EventFull - && it.profileId == profileId - && it.id == itemId - && it.attachmentIds?.contains(id) != true) { - if (it.attachmentIds == null) - it.attachmentIds = mutableListOf() - if (it.attachmentNames == null) - it.attachmentNames = mutableListOf() - it.attachmentIds?.add(id) - it.attachmentNames?.add(fileName) - } - - if (owner is MessageFull - && it is MessageFull - && owner.profileId == it.profileId - && owner.id == it.id) { - owner.attachmentIds = it.attachmentIds - owner.attachmentNames = it.attachmentNames - } - - if (owner is EventFull - && it is EventFull - && owner.profileId == it.profileId - && owner.id == it.id) { - owner.attachmentIds = it.attachmentIds - owner.attachmentNames = it.attachmentNames - } - } - } - - /*if (owner is MessageFull) { - list.forEach { - (it as? MessageFull)?.let { message -> - data.messageList.add(message) - } - } - data.messageListReplace = true - } - - if (owner is EventFull) { - list.forEach { - (it as? EventFull)?.let { it1 -> - it1.homeworkBody = "" - data.eventList.add(it1) - } - } - data.eventListReplace = true - }*/ - - onSuccess(list) - } - }} -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt deleted file mode 100644 index 2814a1cf..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt +++ /dev/null @@ -1,110 +0,0 @@ -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import androidx.core.util.isEmpty -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_ATTENDANCE -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_ATTENDANCE -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.Attendance -import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.utils.models.Date - -class VulcanApiAttendance(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiAttendance" - } - - init { data.profile?.also { profile -> - if (data.attendanceTypes.isEmpty()) { - data.db.attendanceTypeDao().getAllNow(profileId).toSparseArray(data.attendanceTypes) { it.id } - } - - val semesterId = data.studentSemesterId - val semesterNumber = data.studentSemesterNumber - if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) { - getAttendance(profile, semesterId - 1, semesterNumber - 1) { - getAttendance(profile, semesterId, semesterNumber) { - finish() - } - } - } - else { - getAttendance(profile, semesterId, semesterNumber) { - finish() - } - } - - } ?: onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE) } - - private fun finish() { - data.setSyncNext(ENDPOINT_VULCAN_API_ATTENDANCE, SYNC_ALWAYS) - onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE) - } - - private fun getAttendance(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) { - val startDate = profile.getSemesterStart(semesterNumber).stringY_m_d - val endDate = profile.getSemesterEnd(semesterNumber).stringY_m_d - - apiGet(TAG, VULCAN_API_ENDPOINT_ATTENDANCE, parameters = mapOf( - "DataPoczatkowa" to startDate, - "DataKoncowa" to endDate, - "IdOddzial" to data.studentClassId, - "IdUczen" to data.studentId, - "IdOkresKlasyfikacyjny" to semesterId - )) { json, _ -> - json.getJsonObject("Data")?.getJsonArray("Frekwencje")?.forEach { attendanceEl -> - val attendance = attendanceEl.asJsonObject - - val type = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach) - ?: return@forEach - - val id = (attendance.getInt("Dzien") ?: 0) + (attendance.getInt("Numer") ?: 0) - - val lessonDateMillis = Date.fromY_m_d(attendance.getString("DzienTekst")).inMillis - val lessonDate = Date.fromMillis(lessonDateMillis) - val startTime = data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime - - val lessonSemester = semesterNumber - - val attendanceObject = Attendance( - profileId = profileId, - id = id.toLong(), - baseType = type.baseType, - typeName = type.typeName, - typeShort = type.typeShort, - typeSymbol = type.typeSymbol, - typeColor = type.typeColor, - date = lessonDate, - startTime = startTime, - semester = lessonSemester, - teacherId = -1, - subjectId = attendance.getLong("IdPrzedmiot") ?: -1, - addedDate = lessonDate.combineWith(startTime) - ).also { - it.lessonNumber = attendance.getInt("Numer") - it.isCounted = it.baseType != Attendance.TYPE_RELEASED - } - - data.attendanceList.add(attendanceObject) - if (type.baseType != TYPE_PRESENT) { - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_ATTENDANCE, - attendanceObject.id, - profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN, - profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN - )) - } - } - - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt deleted file mode 100644 index 2dc9f6bc..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-10-20 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import com.google.gson.JsonObject -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_DICTIONARIES -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_DICTIONARIES -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.utils.models.Time - -class VulcanApiDictionaries(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiDictionaries" - } - - init { - apiGet(TAG, VULCAN_API_ENDPOINT_DICTIONARIES) { json, _ -> - val elements = json.getJsonObject("Data") - - elements?.getJsonArray("Pracownicy")?.forEach { saveTeacher(it.asJsonObject) } - elements?.getJsonArray("Przedmioty")?.forEach { saveSubject(it.asJsonObject) } - elements?.getJsonArray("PoryLekcji")?.forEach { saveLessonRange(it.asJsonObject) } - elements?.getJsonArray("KategorieOcen")?.forEach { saveGradeCategory(it.asJsonObject) } - elements?.getJsonArray("KategorieUwag")?.forEach { saveNoticeType(it.asJsonObject) } - elements?.getJsonArray("KategorieFrekwencji")?.forEach { saveAttendanceType(it.asJsonObject) } - - data.setSyncNext(ENDPOINT_VULCAN_API_DICTIONARIES, 4 * DAY) - onSuccess(ENDPOINT_VULCAN_API_DICTIONARIES) - } - } - - private fun saveTeacher(teacher: JsonObject) { - val id = teacher.getLong("Id") ?: return - val name = teacher.getString("Imie") ?: "" - val surname = teacher.getString("Nazwisko") ?: "" - val loginId = teacher.getString("LoginId") ?: "-1" - - val teacherObject = Teacher( - profileId, - id, - name, - surname, - loginId - ) - - data.teacherList.put(id, teacherObject) - } - - private fun saveSubject(subject: JsonObject) { - val id = subject.getLong("Id") ?: return - val longName = subject.getString("Nazwa") ?: "" - val shortName = subject.getString("Kod") ?: "" - - val subjectObject = Subject( - profileId, - id, - longName, - shortName - ) - - data.subjectList.put(id, subjectObject) - } - - private fun saveLessonRange(lessonRange: JsonObject) { - val lessonNumber = lessonRange.getInt("Numer") ?: return - val startTime = lessonRange.getString("PoczatekTekst")?.let { Time.fromH_m(it) } ?: return - val endTime = lessonRange.getString("KoniecTekst")?.let { Time.fromH_m(it) } ?: return - - val lessonRangeObject = LessonRange( - profileId, - lessonNumber, - startTime, - endTime - ) - - data.lessonRanges.put(lessonNumber, lessonRangeObject) - } - - private fun saveGradeCategory(gradeCategory: JsonObject) { - val id = gradeCategory.getLong("Id") ?: return - val name = gradeCategory.getString("Nazwa") ?: "" - - val gradeCategoryObject = GradeCategory( - profileId, - id, - 0.0f, - -1, - name - ) - - data.gradeCategories.put(id, gradeCategoryObject) - } - - private fun saveNoticeType(noticeType: JsonObject) { - val id = noticeType.getLong("Id") ?: return - val name = noticeType.getString("Nazwa") ?: "" - - val noticeTypeObject = NoticeType( - profileId, - id, - name - ) - - data.noticeTypes.put(id, noticeTypeObject) - } - - private fun saveAttendanceType(attendanceType: JsonObject) { - val id = attendanceType.getLong("Id") ?: return - val typeName = attendanceType.getString("Nazwa") ?: "" - - val absent = attendanceType.getBoolean("Nieobecnosc") ?: false - val excused = attendanceType.getBoolean("Usprawiedliwione") ?: false - val baseType = if (absent) { - if (excused) - Attendance.TYPE_ABSENT_EXCUSED - else - Attendance.TYPE_ABSENT - } else { - val belated = attendanceType.getBoolean("Spoznienie") ?: false - val released = attendanceType.getBoolean("Zwolnienie") ?: false - val present = attendanceType.getBoolean("Obecnosc") ?: true - if (belated) - if (excused) - Attendance.TYPE_BELATED_EXCUSED - else - Attendance.TYPE_BELATED - else if (released) - Attendance.TYPE_RELEASED - else if (present) - Attendance.TYPE_PRESENT - else - Attendance.TYPE_UNKNOWN - } - - val (typeColor, typeSymbol) = when (id.toInt()) { - 1 -> 0xffffffff to "●" // obecność - 2 -> 0xffffa687 to "—" // nieobecność - 3 -> 0xfffcc150 to "u" // nieobecność usprawiedliwiona - 4 -> 0xffede049 to "s" // spóźnienie - 5 -> 0xffbbdd5f to "su" // spóźnienie usprawiedliwione - 6 -> 0xffa9c9fd to "ns" // nieobecny z przyczyn szkolnych - 7 -> 0xffddbbe5 to "z" // zwolniony - 8 -> 0xffffffff to "" // usunięty wpis - else -> null to "?" - } - - val typeShort = when (id.toInt()) { - 6 -> "ns" // nieobecny z przyczyn szkolnych - 8 -> "" // usunięty wpis - else -> data.app.attendanceManager.getTypeShort(baseType) - } - - val attendanceTypeObject = AttendanceType( - profileId, - id, - baseType, - typeName, - typeShort, - typeSymbol, - typeColor?.toInt() - ) - - data.attendanceTypes.put(id, attendanceTypeObject) - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt deleted file mode 100644 index 6f045828..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-10-20 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_EVENTS -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_HOMEWORK -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_EVENTS -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_HOMEWORK -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Event -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.getBoolean -import pl.szczodrzynski.edziennik.getJsonArray -import pl.szczodrzynski.edziennik.getLong -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.utils.models.Date - -class VulcanApiEvents(override val data: DataVulcan, - override val lastSync: Long?, - private val isHomework: Boolean, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiEvents" - } - - init { data.profile?.also { profile -> - - val semesterId = data.studentSemesterId - val semesterNumber = data.studentSemesterNumber - if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) { - getEvents(profile, semesterId - 1, semesterNumber - 1) { - getEvents(profile, semesterId, semesterNumber) { - finish() - } - } - } - else { - getEvents(profile, semesterId, semesterNumber) { - finish() - } - } - - } ?: onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS) } - - private fun finish() { - when (isHomework) { - true -> { - data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK)) - data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS) - } - false -> { - data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK)) - data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS) - } - } - onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS) - } - - private fun getEvents(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) { - val startDate = when (profile.empty) { - true -> profile.getSemesterStart(semesterNumber).stringY_m_d - else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d - } - val endDate = profile.getSemesterEnd(semesterNumber).stringY_m_d - - val endpoint = when (isHomework) { - true -> VULCAN_API_ENDPOINT_HOMEWORK - else -> VULCAN_API_ENDPOINT_EVENTS - } - apiGet(TAG, endpoint, parameters = mapOf( - "DataPoczatkowa" to startDate, - "DataKoncowa" to endDate, - "IdOddzial" to data.studentClassId, - "IdUczen" to data.studentId, - "IdOkresKlasyfikacyjny" to semesterId - )) { json, _ -> - val events = json.getJsonArray("Data") - - events?.forEach { eventEl -> - val event = eventEl.asJsonObject - - val id = event?.getLong("Id") ?: return@forEach - val eventDate = Date.fromY_m_d(event.getString("DataTekst") ?: return@forEach) - val subjectId = event.getLong("IdPrzedmiot") ?: -1 - val teacherId = event.getLong("IdPracownik") ?: -1 - val topic = event.getString("Opis")?.trim() ?: "" - - val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate) - val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime - - val type = when (isHomework) { - true -> Event.TYPE_HOMEWORK - else -> when (event.getBoolean("Rodzaj")) { - false -> Event.TYPE_SHORT_QUIZ - else -> Event.TYPE_EXAM - } - } - val teamId = event.getLong("IdOddzial") ?: data.teamClass?.id ?: -1 - - val eventObject = Event( - profileId = profileId, - id = id, - date = eventDate, - time = startTime, - topic = topic, - color = null, - type = type, - teacherId = teacherId, - subjectId = subjectId, - teamId = teamId - ) - - data.eventList.add(eventObject) - data.metadataList.add(Metadata( - profileId, - if (isHomework) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT, - id, - profile.empty, - profile.empty - )) - } - - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt deleted file mode 100644 index 9a354ea5..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-10-19 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_GRADES -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_GRADES -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.Grade -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import java.text.DecimalFormat -import kotlin.math.roundToInt - -class VulcanApiGrades(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiGrades" - } - - init { data.profile?.also { profile -> - - val semesterId = data.studentSemesterId - val semesterNumber = data.studentSemesterNumber - if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) { - getGrades(profile, semesterId - 1, semesterNumber - 1) { - getGrades(profile, semesterId, semesterNumber) { - finish() - } - } - } - else { - getGrades(profile, semesterId, semesterNumber) { - finish() - } - } - - } ?: onSuccess(ENDPOINT_VULCAN_API_GRADES) } - - private fun finish() { - data.toRemove.add(DataRemoveModel.Grades.semesterWithType(data.studentSemesterNumber, TYPE_NORMAL)) - data.setSyncNext(ENDPOINT_VULCAN_API_GRADES, SYNC_ALWAYS) - onSuccess(ENDPOINT_VULCAN_API_GRADES) - } - - private fun getGrades(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) { - apiGet(TAG, VULCAN_API_ENDPOINT_GRADES, parameters = mapOf( - "IdUczen" to data.studentId, - "IdOkresKlasyfikacyjny" to semesterId - )) { json, _ -> - val grades = json.getJsonArray("Data") - - grades?.forEach { gradeEl -> - val grade = gradeEl.asJsonObject - - val id = grade.getLong("Id") ?: return@forEach - val categoryId = grade.getLong("IdKategoria") ?: -1 - val category = data.gradeCategories.singleOrNull{ it.categoryId == categoryId }?.text - ?: "" - val teacherId = grade.getLong("IdPracownikD") ?: -1 - val subjectId = grade.getLong("IdPrzedmiot") ?: -1 - val description = grade.getString("Opis") - val comment = grade.getString("Komentarz") - var value = grade.getFloat("Wartosc") - var weight = grade.getFloat("WagaOceny") ?: 0.0f - val modificatorValue = grade.getFloat("WagaModyfikatora") - val numerator = grade.getFloat("Licznik") - val denominator = grade.getFloat("Mianownik") - val addedDate = (grade.getLong("DataModyfikacji") ?: return@forEach) * 1000 - - var finalDescription = "" - - var name = when (numerator != null && denominator != null) { - true -> { - value = numerator / denominator - finalDescription += DecimalFormat("#.##").format(numerator) + - "/" + DecimalFormat("#.##").format(denominator) - weight = 0.0f - (value * 100).roundToInt().toString() + "%" - } - else -> { - if (value != null) modificatorValue?.also { value += it } - else weight = 0.0f - - grade.getString("Wpis") ?: "" - } - } - - comment?.also { - if (name == "") name = it - else finalDescription = (if (finalDescription == "") "" else " ") + it - } - - description?.also { - finalDescription = (if (finalDescription == "") "" else " - ") + it - } - - val color = when (name) { - "1-", "1", "1+" -> 0xffd65757 - "2-", "2", "2+" -> 0xff9071b3 - "3-", "3", "3+" -> 0xffd2ab24 - "4-", "4", "4+" -> 0xff50b6d6 - "5-", "5", "5+" -> 0xff2cbd92 - "6-", "6", "6+" -> 0xff91b43c - else -> 0xff3D5F9C - }.toInt() - - val gradeObject = Grade( - profileId = profileId, - id = id, - name = name, - type = TYPE_NORMAL, - value = value ?: 0.0f, - weight = weight, - color = color, - category = category, - description = finalDescription, - comment = null, - semester = semesterNumber, - teacherId = teacherId, - subjectId = subjectId, - addedDate = addedDate - ) - - data.gradeList.add(gradeObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_GRADE, - id, - profile.empty, - profile.empty - )) - } - - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt deleted file mode 100644 index b0b7795d..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-11-12 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT -import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.full.MessageFull - -class VulcanApiMessagesChangeStatus(override val data: DataVulcan, - private val messageObject: MessageFull, - val onSuccess: () -> Unit -) : VulcanApi(data, null) { - companion object { - const val TAG = "VulcanApiMessagesChangeStatus" - } - - init { - apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS, parameters = mapOf( - "WiadomoscId" to messageObject.id, - "FolderWiadomosci" to "Odebrane", - "Status" to "Widoczna", - "LoginId" to data.studentLoginId, - "IdUczen" to data.studentId - )) { _, _ -> - - if (!messageObject.seen) { - data.setSeenMetadataList.add(Metadata( - profileId, - Metadata.TYPE_MESSAGE, - messageObject.id, - true, - true - )) - - messageObject.seen = true - } - - if (messageObject.type != TYPE_SENT) { - val messageRecipientObject = MessageRecipient( - profileId, - -1, - -1, - System.currentTimeMillis(), - messageObject.id - ) - - data.messageRecipientList.add(messageRecipientObject) - } - - EventBus.getDefault().postSticky(MessageGetEvent(messageObject)) - - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt deleted file mode 100644 index dea913c5..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-11-01 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_RECEIVED -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_INBOX -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.utils.Utils -import pl.szczodrzynski.edziennik.utils.models.Date -import kotlin.text.replace - -class VulcanApiMessagesInbox(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiMessagesInbox" - } - - init { - data.profile?.also { profile -> - - val startDate = when (profile.empty) { - true -> profile.getSemesterStart(profile.currentSemester).inUnix - else -> Date.getToday().stepForward(0, -2, 0).inUnix - } - val endDate = Date.getToday().stepForward(0, 1, 0).inUnix - - apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_RECEIVED, parameters = mapOf( - "DataPoczatkowa" to startDate, - "DataKoncowa" to endDate, - "LoginId" to data.studentLoginId, - "IdUczen" to data.studentId - )) { json, _ -> - json.getJsonArray("Data")?.asJsonObjectList()?.forEach { message -> - val id = message.getLong("WiadomoscId") ?: return@forEach - val subject = message.getString("Tytul") ?: "" - val body = message.getString("Tresc") ?: "" - - val senderLoginId = message.getString("NadawcaId") ?: return@forEach - val senderId = data.teacherList.singleOrNull { it.loginId == senderLoginId }?.id ?: { - - val senderName = message.getString("Nadawca") ?: "" - - senderName.splitName()?.let { (senderLastName, senderFirstName) -> - val teacherObject = Teacher( - profileId, - -1 * Utils.crc16(senderName.toByteArray()).toLong(), - senderFirstName, - senderLastName, - senderLoginId - ) - data.teacherList.put(teacherObject.id, teacherObject) - teacherObject.id - } - }.invoke() - - val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } - ?: -1 - val readDate = message.getLong("DataPrzeczytaniaUnixEpoch")?.let { it * 1000 } - ?: -1 - - val messageObject = Message( - profileId = profileId, - id = id, - type = TYPE_RECEIVED, - subject = subject, - body = body.replace("\n", "
"), - senderId = senderId, - addedDate = sentDate - ) - - val messageRecipientObject = MessageRecipient( - profileId, - -1, - -1, - readDate, - id - ) - - data.messageList.add(messageObject) - data.messageRecipientList.add(messageRecipientObject) - data.setSeenMetadataList.add(Metadata( - profileId, - Metadata.TYPE_MESSAGE, - id, - readDate > 0, - readDate > 0 - )) - } - - data.setSyncNext(ENDPOINT_VULCAN_API_MESSAGES_INBOX, SYNC_ALWAYS) - onSuccess(ENDPOINT_VULCAN_API_MESSAGES_INBOX) - } - } ?: onSuccess(ENDPOINT_VULCAN_API_MESSAGES_INBOX) - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt deleted file mode 100644 index 94cfdcba..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-11-5 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_SENT -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_SENT -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT -import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Teacher -import pl.szczodrzynski.edziennik.utils.Utils -import pl.szczodrzynski.edziennik.utils.models.Date -import kotlin.text.replace - -class VulcanApiMessagesSent(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiMessagesSent" - } - - init { - data.profile?.also { profile -> - - val startDate = when (profile.empty) { - true -> profile.getSemesterStart(profile.currentSemester).inUnix - else -> Date.getToday().stepForward(0, -2, 0).inUnix - } - val endDate = Date.getToday().stepForward(0, 1, 0).inUnix - - apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_SENT, parameters = mapOf( - "DataPoczatkowa" to startDate, - "DataKoncowa" to endDate, - "LoginId" to data.studentLoginId, - "IdUczen" to data.studentId - )) { json, _ -> - json.getJsonArray("Data")?.asJsonObjectList()?.forEach { message -> - val id = message.getLong("WiadomoscId") ?: return@forEach - val subject = message.getString("Tytul") ?: "" - val body = message.getString("Tresc") ?: "" - val readBy = message.getInt("Przeczytane") ?: 0 - val unreadBy = message.getInt("Nieprzeczytane") ?: 0 - val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } ?: -1 - - message.getJsonArray("Adresaci")?.asJsonObjectList() - ?.onEach { receiver -> - - val receiverLoginId = receiver.getString("LoginId") - ?: return@onEach - val receiverId = data.teacherList.singleOrNull { it.loginId == receiverLoginId }?.id - ?: { - val receiverName = receiver.getString("Nazwa") ?: "" - - receiverName.splitName()?.let { (receiverLastName, receiverFirstName) -> - val teacherObject = Teacher( - profileId, - -1 * Utils.crc16(receiverName.toByteArray()).toLong(), - receiverFirstName, - receiverLastName, - receiverLoginId - ) - data.teacherList.put(teacherObject.id, teacherObject) - teacherObject.id - } - }.invoke() ?: -1 - - val readDate: Long = when (readBy) { - 0 -> 0 - else -> when (unreadBy) { - 0 -> 1 - else -> -1 - } - } - - val messageRecipientObject = MessageRecipient( - profileId, - receiverId, - -1, - readDate, - id - ) - - data.messageRecipientList.add(messageRecipientObject) - } - - val messageObject = Message( - profileId = profileId, - id = id, - type = TYPE_SENT, - subject = subject, - body = body.replace("\n", "
"), - senderId = null, - addedDate = sentDate - ) - - data.messageList.add(messageObject) - data.setSeenMetadataList.add(Metadata( - profileId, - Metadata.TYPE_MESSAGE, - id, - true, - true - )) - } - - data.setSyncNext(ENDPOINT_VULCAN_API_MESSAGES_SENT, 1 * DAY, DRAWER_ITEM_MESSAGES) - onSuccess(ENDPOINT_VULCAN_API_MESSAGES_SENT) - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt deleted file mode 100644 index 45155a5b..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-10-23 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import androidx.core.util.isEmpty -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_NOTICES -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_NOTICES -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Notice -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS -import pl.szczodrzynski.edziennik.getJsonArray -import pl.szczodrzynski.edziennik.getLong -import pl.szczodrzynski.edziennik.getString -import pl.szczodrzynski.edziennik.toSparseArray - -class VulcanApiNotices(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiNotices" - } - - init { data.profile?.also { profile -> - if (data.noticeTypes.isEmpty()) { - data.db.noticeTypeDao().getAllNow(profileId).toSparseArray(data.noticeTypes) { it.id } - } - - val semesterId = data.studentSemesterId - val semesterNumber = data.studentSemesterNumber - if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) { - getNotices(profile, semesterId - 1, semesterNumber - 1) { - getNotices(profile, semesterId, semesterNumber) { - finish() - } - } - } - else { - getNotices(profile, semesterId, semesterNumber) { - finish() - } - } - - } ?: onSuccess(ENDPOINT_VULCAN_API_NOTICES) } - - private fun finish() { - data.setSyncNext(ENDPOINT_VULCAN_API_NOTICES, SYNC_ALWAYS) - onSuccess(ENDPOINT_VULCAN_API_NOTICES) - } - - private fun getNotices(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) { - apiGet(TAG, VULCAN_API_ENDPOINT_NOTICES, parameters = mapOf( - "IdUczen" to data.studentId, - "IdOkresKlasyfikacyjny" to data.studentSemesterId - )) { json, _ -> - json.getJsonArray("Data")?.forEach { noticeEl -> - val notice = noticeEl.asJsonObject - - val id = notice.getLong("Id") ?: return@forEach - val text = notice.getString("TrescUwagi") ?: return@forEach - val teacherId = notice.getLong("IdPracownik") ?: -1 - val addedDate = notice.getLong("DataModyfikacji")?.times(1000) ?: System.currentTimeMillis() - - val categoryId = notice.getLong("IdKategoriaUwag") ?: -1 - val categoryText = data.noticeTypes[categoryId]?.name ?: "" - - val noticeObject = Notice( - profileId = profileId, - id = id, - type = Notice.TYPE_NEUTRAL, - semester = profile.currentSemester, - text = text, - category = categoryText, - points = null, - teacherId = teacherId, - addedDate = addedDate - ) - - data.noticeList.add(noticeObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_NOTICE, - id, - profile.empty, - profile.empty - )) - } - - onSuccess() - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt deleted file mode 100644 index e897df92..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt +++ /dev/null @@ -1,112 +0,0 @@ -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import com.google.gson.JsonArray -import pl.szczodrzynski.edziennik.HOUR -import pl.szczodrzynski.edziennik.asJsonObjectList -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_GRADES_SUMMARY -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.Grade -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_FINAL -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_PROPOSED -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_FINAL -import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_PROPOSED -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.getJsonArray -import pl.szczodrzynski.edziennik.getJsonObject -import pl.szczodrzynski.edziennik.utils.Utils - -class VulcanApiProposedGrades(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiProposedGrades" - } - - init { data.profile?.also { profile -> - - val semesterId = data.studentSemesterId - val semesterNumber = data.studentSemesterNumber - if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) { - getProposedGrades(profile, semesterId - 1, semesterNumber - 1) { - getProposedGrades(profile, semesterId, semesterNumber) { - finish() - } - } - } - else { - getProposedGrades(profile, semesterId, semesterNumber) { - finish() - } - } - - } ?: onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY) } - - private fun finish() { - data.setSyncNext(ENDPOINT_VULCAN_API_GRADES_SUMMARY, 6*HOUR) - onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY) - } - - private fun getProposedGrades(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) { - apiGet(TAG, VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS, parameters = mapOf( - "IdUczen" to data.studentId, - "IdOkresKlasyfikacyjny" to semesterId - )) { json, _ -> - val grades = json.getJsonObject("Data") - - grades.getJsonArray("OcenyPrzewidywane")?.let { - processGradeList(it, semesterNumber, isFinal = false) - } - - grades.getJsonArray("OcenyKlasyfikacyjne")?.let { - processGradeList(it, semesterNumber, isFinal = true) - } - - onSuccess() - } - } - - private fun processGradeList(grades: JsonArray, semesterNumber: Int, isFinal: Boolean) { - grades.asJsonObjectList().forEach { grade -> - val name = grade.get("Wpis").asString - val value = Utils.getGradeValue(name) - val subjectId = grade.get("IdPrzedmiot").asLong - - val id = subjectId * -100 - semesterNumber - - val color = Utils.getVulcanGradeColor(name) - - val gradeObject = Grade( - profileId = profileId, - id = id, - name = name, - type = if (semesterNumber == 1) { - if (isFinal) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER1_PROPOSED - } else { - if (isFinal) TYPE_SEMESTER2_FINAL else TYPE_SEMESTER2_PROPOSED - }, - value = value, - weight = 0f, - color = color, - category = "", - description = null, - comment = null, - semester = semesterNumber, - teacherId = -1, - subjectId = subjectId - ) - - data.gradeList.add(gradeObject) - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_GRADE, - gradeObject.id, - data.profile?.empty ?: false, - data.profile?.empty ?: false - )) - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiPushConfig.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiPushConfig.kt deleted file mode 100644 index b7e291e2..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiPushConfig.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-2-20. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_PUSH -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_PUSH_CONFIG -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS - -class VulcanApiPushConfig(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiPushConfig" - } - - init { data.app.config.sync.tokenVulcan?.also { tokenVulcan -> - apiGet(TAG, VULCAN_API_ENDPOINT_PUSH, parameters = mapOf( - "Token" to tokenVulcan, - "IdUczen" to data.studentId, - "PushOcena" to true, - "PushFrekwencja" to true, - "PushUwaga" to true, - "PushWiadomosc" to true - )) { _, _ -> - // sync always: this endpoint has .shouldSync set - data.setSyncNext(ENDPOINT_VULCAN_API_PUSH_CONFIG, SYNC_ALWAYS) - data.app.config.sync.tokenVulcanList = - data.app.config.sync.tokenVulcanList + profileId - onSuccess(ENDPOINT_VULCAN_API_PUSH_CONFIG) - } - } ?: onSuccess(ENDPOINT_VULCAN_API_PUSH_CONFIG) } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt deleted file mode 100644 index 8c89b620..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-12-29. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import org.greenrobot.eventbus.EventBus -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_ADD -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Teacher - -class VulcanApiSendMessage(override val data: DataVulcan, - val recipients: List, - val subject: String, - val text: String, - val onSuccess: () -> Unit -) : VulcanApi(data, null) { - companion object { - private const val TAG = "VulcanApiSendMessage" - } - - init { - val recipientsArray = JsonArray() - for (teacher in recipients) { - teacher.loginId?.let { - recipientsArray += JsonObject( - "LoginId" to it, - "Nazwa" to "${teacher.fullNameLastFirst} - pracownik" - ) - } - } - val params = mapOf( - "NadawcaWiadomosci" to (profile?.accountName ?: profile?.studentNameLong ?: ""), - "Tytul" to subject, - "Tresc" to text, - "Adresaci" to recipientsArray, - "LoginId" to data.studentLoginId, - "IdUczen" to data.studentId - ) - - apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_ADD, parameters = params) { json, _ -> - val messageId = json.getJsonObject("Data").getLong("WiadomoscId") - - if (messageId == null) { - // TODO error - return@apiGet - } - - VulcanApiMessagesSent(data, null) { - val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } - val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId } - val event = MessageSentEvent(data.profileId, message, message?.addedDate) - - EventBus.getDefault().postSticky(event) - onSuccess() - } - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTemplate.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTemplate.kt deleted file mode 100644 index 4148be44..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTemplate.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-10-20 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi - -class VulcanApiTemplate(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApi" - } - - init { - /* data.profile?.also { profile -> - apiGet(TAG, VULCAN_API_ENDPOINT_) { json, _ -> - - data.setSyncNext(ENDPOINT_VULCAN_API_, SYNC_ALWAYS) - onSuccess() - } - } */ - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt deleted file mode 100644 index 46b52de5..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2019-11-13 - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import androidx.core.util.set -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.Regexes.VULCAN_SHIFT_ANNOTATION -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_TIMETABLE -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_TIMETABLE -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel -import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.utils.Utils.crc16 -import pl.szczodrzynski.edziennik.utils.Utils.d -import pl.szczodrzynski.edziennik.utils.models.Date -import pl.szczodrzynski.edziennik.utils.models.Week - -class VulcanApiTimetable(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiTimetable" - } - - init { data.profile?.also { profile -> - val currentWeekStart = Week.getWeekStart() - - if (Date.getToday().weekDay > 4) { - currentWeekStart.stepForward(0, 0, 7) - } - - val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d - - val weekStart = Date.fromY_m_d(getDate) - val weekEnd = weekStart.clone().stepForward(0, 0, 6) - - apiGet(TAG, VULCAN_API_ENDPOINT_TIMETABLE, parameters = mapOf( - "DataPoczatkowa" to weekStart.stringY_m_d, - "DataKoncowa" to weekEnd.stringY_m_d, - "IdUczen" to data.studentId, - "IdOddzial" to data.studentClassId, - "IdOkresKlasyfikacyjny" to data.studentSemesterId - )) { json, _ -> - val dates = mutableSetOf() - val lessons = mutableListOf() - - json.getJsonArray("Data")?.asJsonObjectList()?.forEach { lesson -> - if (lesson.getBoolean("PlanUcznia") != true) - return@forEach - val lessonDate = Date.fromY_m_d(lesson.getString("DzienTekst")) - val lessonNumber = lesson.getInt("NumerLekcji") - val lessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber } - val startTime = lessonRange?.startTime - val endTime = lessonRange?.endTime - val teacherId = lesson.getLong("IdPracownik") - val classroom = lesson.getString("Sala") - - val oldTeacherId = lesson.getLong("IdPracownikOld") - - val changeAnnotation = lesson.getString("AdnotacjaOZmianie") ?: "" - val type = when { - changeAnnotation.startsWith("(przeniesiona z") -> Lesson.TYPE_SHIFTED_TARGET - changeAnnotation.startsWith("(przeniesiona na") -> Lesson.TYPE_SHIFTED_SOURCE - changeAnnotation.startsWith("(zastępstwo") -> Lesson.TYPE_CHANGE - lesson.getBoolean("PrzekreslonaNazwa") == true -> Lesson.TYPE_CANCELLED - else -> Lesson.TYPE_NORMAL - } - - val teamId = lesson.getString("PodzialSkrot")?.let { teamName -> - val name = "${data.teamClass?.name} $teamName" - val id = name.crc16().toLong() - var team = data.teamList.singleOrNull { it.name == name } - if (team == null) { - team = Team( - profileId, - id, - name, - Team.TYPE_VIRTUAL, - "${data.schoolCode}:$name", - teacherId ?: oldTeacherId ?: -1 - ) - data.teamList[id] = team - } - team.id - } ?: data.teamClass?.id ?: -1 - - val subjectId = lesson.getLong("IdPrzedmiot").let { id -> - // get the specified subject name - val subjectName = lesson.getString("PrzedmiotNazwa") ?: "" - - val condition = when (id) { - // "special" subject - e.g. one time classes, a trip, etc. - 0L -> { subject: Subject -> subject.longName == subjectName } - // normal subject, check if it exists - else -> { subject: Subject -> subject.id == id } - } - - data.subjectList.singleOrNull(condition)?.id ?: { - /** - * CREATE A NEW SUBJECT IF IT DOESN'T EXIST - */ - - val subjectObject = Subject( - profileId, - if (id == null || id == 0L) - -1 * crc16(subjectName.toByteArray()).toLong() - else - id, - subjectName, - subjectName - ) - data.subjectList.put(subjectObject.id, subjectObject) - subjectObject.id - }() - } - - val lessonObject = Lesson(profileId, -1).apply { - this.type = type - - when (type) { - Lesson.TYPE_NORMAL, Lesson.TYPE_CHANGE, Lesson.TYPE_SHIFTED_TARGET -> { - this.date = lessonDate - this.lessonNumber = lessonNumber - this.startTime = startTime - this.endTime = endTime - this.subjectId = subjectId - this.teacherId = teacherId - this.teamId = teamId - this.classroom = classroom - - this.oldTeacherId = oldTeacherId - } - - Lesson.TYPE_CANCELLED, Lesson.TYPE_SHIFTED_SOURCE -> { - this.oldDate = lessonDate - this.oldLessonNumber = lessonNumber - this.oldStartTime = startTime - this.oldEndTime = endTime - this.oldSubjectId = subjectId - this.oldTeacherId = teacherId - this.oldTeamId = teamId - this.oldClassroom = classroom - } - } - - if (type == Lesson.TYPE_SHIFTED_SOURCE || type == Lesson.TYPE_SHIFTED_TARGET) { - val shift = VULCAN_SHIFT_ANNOTATION.find(changeAnnotation) - val oldLessonNumber = shift?.get(2)?.toInt() - val oldLessonDate = shift?.get(3)?.let { Date.fromd_m_Y(it) } - - val oldLessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == oldLessonNumber } - val oldStartTime = oldLessonRange?.startTime - val oldEndTime = oldLessonRange?.endTime - - when (type) { - Lesson.TYPE_SHIFTED_SOURCE -> { - this.lessonNumber = oldLessonNumber - this.date = oldLessonDate - this.startTime = oldStartTime - this.endTime = oldEndTime - } - - Lesson.TYPE_SHIFTED_TARGET -> { - this.oldLessonNumber = oldLessonNumber - this.oldDate = oldLessonDate - this.oldStartTime = oldStartTime - this.oldEndTime = oldEndTime - } - } - } - - this.id = buildId() - } - - val seen = profile.empty || lessonDate < Date.getToday() - - if (type != Lesson.TYPE_NORMAL) { - data.metadataList.add(Metadata( - profileId, - Metadata.TYPE_LESSON_CHANGE, - lessonObject.id, - seen, - seen - )) - } - - dates.add(lessonDate.value) - lessons.add(lessonObject) - } - - val date: Date = weekStart.clone() - while (date <= weekEnd) { - if (!dates.contains(date.value)) { - lessons.add(Lesson(profileId, date.value.toLong()).apply { - this.type = Lesson.TYPE_NO_LESSONS - this.date = date.clone() - }) - } - - date.stepForward(0, 0, 1) - } - - d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate") - - data.lessonList.addAll(lessons) - data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd)) - - data.setSyncNext(ENDPOINT_VULCAN_API_TIMETABLE, SYNC_ALWAYS) - onSuccess(ENDPOINT_VULCAN_API_TIMETABLE) - } - }} -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt deleted file mode 100644 index 50fb178a..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-2-1. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api - -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.ERROR_NO_STUDENTS_IN_ACCOUNT -import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_STUDENT_LIST -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_UPDATE_SEMESTER -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.utils.models.Date - -class VulcanApiUpdateSemester(override val data: DataVulcan, - override val lastSync: Long?, - val onSuccess: (endpointId: Int) -> Unit -) : VulcanApi(data, lastSync) { - companion object { - const val TAG = "VulcanApiUpdateSemester" - } - - init { data.profile?.also { profile -> - apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, response -> - val students = json.getJsonArray("Data") - - if (students == null || students.isEmpty()) { - data.error(ApiError(TAG, ERROR_NO_STUDENTS_IN_ACCOUNT) - .withResponse(response) - .withApiResponse(json)) - return@apiGet - } - - students.asJsonObjectList().firstOrNull { - it.getInt("Id") == data.studentId - }?.let { student -> - val studentClassId = student.getInt("IdOddzial") ?: return@let - val studentClassName = student.getString("OkresPoziom").toString() + (student.getString("OddzialSymbol") ?: return@let) - val studentSemesterId = student.getInt("IdOkresKlasyfikacyjny") ?: return@let - - val currentSemesterStartDate = student.getLong("OkresDataOd") ?: return@let - val currentSemesterEndDate = (student.getLong("OkresDataDo") ?: return@let) + 86400 - val studentSemesterNumber = student.getInt("OkresNumer") ?: return@let - - var dateSemester1Start: Date? = null - var dateSemester2Start: Date? = null - var dateYearEnd: Date? = null - when (studentSemesterNumber) { - 1 -> { - dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000) - dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000) - } - 2 -> { - dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000) - dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000) - } - } - - data.studentClassId = studentClassId - data.studentSemesterId = studentSemesterId - data.studentSemesterNumber = studentSemesterNumber - data.profile.studentData["semester${studentSemesterNumber}Id"] = studentSemesterId - data.currentSemesterEndDate = currentSemesterEndDate - profile.studentClassName = studentClassName - dateSemester1Start?.let { - profile.dateSemester1Start = it - profile.studentSchoolYearStart = it.year - } - dateSemester2Start?.let { profile.dateSemester2Start = it } - dateYearEnd?.let { profile.dateYearEnd = it } - } - - data.setSyncNext(ENDPOINT_VULCAN_API_UPDATE_SEMESTER, if (data.studentSemesterNumber == 2) 7*DAY else 2*DAY) - onSuccess(ENDPOINT_VULCAN_API_UPDATE_SEMESTER) - } - } ?: onSuccess(ENDPOINT_VULCAN_API_UPDATE_SEMESTER) } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/HebeFilterType.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/HebeFilterType.kt index 6734ab71..a4ea84b1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/HebeFilterType.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/HebeFilterType.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-20. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe enum class HebeFilterType(val endpoint: String) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAddressbook.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAddressbook.kt index c96142aa..5069838e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAddressbook.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAddressbook.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-21. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import androidx.core.util.set diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAttendance.kt index 3d207388..9e41bb6d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeAttendance.kt @@ -85,6 +85,7 @@ class VulcanHebeAttendance( subjectId = subjectId, addedDate = addedDate ).also { + it.lessonTopic = attendance.getString("Topic") it.lessonNumber = lessonNumber it.isCounted = isCounted } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeExams.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeExams.kt index 54388a86..64b52e2b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeExams.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeExams.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-21. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import pl.szczodrzynski.edziennik.* @@ -36,6 +40,8 @@ class VulcanHebeExams( ?: -1 val topic = exam.getString("Content")?.trim() ?: "" + if (!isCurrentYear(eventDate)) return@forEach + val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate) val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGradeSummary.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGradeSummary.kt new file mode 100644 index 00000000..e38ac393 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGradeSummary.kt @@ -0,0 +1,88 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-22. + */ + +package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe + +import pl.szczodrzynski.edziennik.DAY +import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_GRADE_SUMMARY +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe +import pl.szczodrzynski.edziennik.data.db.entity.Grade +import pl.szczodrzynski.edziennik.data.db.entity.Metadata +import pl.szczodrzynski.edziennik.getString +import pl.szczodrzynski.edziennik.utils.Utils + +class VulcanHebeGradeSummary( + override val data: DataVulcan, + override val lastSync: Long?, + val onSuccess: (endpointId: Int) -> Unit +) : VulcanHebe(data, lastSync) { + companion object { + const val TAG = "VulcanHebeGradeSummary" + } + + init { + val entries = mapOf( + "Entry_1" to + if (data.studentSemesterNumber == 1) + Grade.TYPE_SEMESTER1_PROPOSED + else Grade.TYPE_SEMESTER2_PROPOSED, + "Entry_2" to + if (data.studentSemesterNumber == 1) + Grade.TYPE_SEMESTER1_FINAL + else Grade.TYPE_SEMESTER2_FINAL + ) + + apiGetList( + TAG, + VULCAN_HEBE_ENDPOINT_GRADE_SUMMARY, + HebeFilterType.BY_PUPIL, + lastSync = lastSync + ) { list, _ -> + list.forEach { grade -> + val subjectId = getSubjectId(grade, "Subject") ?: return@forEach + val addedDate = getDateTime(grade, "DateModify") + + entries.onEach { (key, type) -> + val id = subjectId * -100 - type + val entry = grade.getString(key) ?: return@onEach + val value = Utils.getGradeValue(entry) + val color = Utils.getVulcanGradeColor(entry) + + val gradeObject = Grade( + profileId = profileId, + id = id, + name = entry, + type = type, + value = value, + weight = 0f, + color = color, + category = "", + description = null, + comment = null, + semester = data.studentSemesterNumber, + teacherId = -1, + subjectId = subjectId, + addedDate = addedDate + ) + + data.gradeList.add(gradeObject) + data.metadataList.add( + Metadata( + profileId, + Metadata.TYPE_GRADE, + id, + profile?.empty ?: true, + profile?.empty ?: true + ) + ) + } + } + + data.setSyncNext(ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY, 1 * DAY) + onSuccess(ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGrades.kt index 11a7fdbc..9c0591de 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGrades.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeGrades.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-20. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import pl.szczodrzynski.edziennik.* diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeHomework.kt index 9ab8ede0..cb792e2c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeHomework.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeHomework.kt @@ -1,5 +1,10 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-21. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe +import pl.szczodrzynski.edziennik.asJsonObjectList import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_HOMEWORK import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_HOMEWORK @@ -7,8 +12,10 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS +import pl.szczodrzynski.edziennik.getJsonArray import pl.szczodrzynski.edziennik.getLong import pl.szczodrzynski.edziennik.getString +import pl.szczodrzynski.edziennik.utils.Utils class VulcanHebeHomework( override val data: DataVulcan, @@ -34,6 +41,8 @@ class VulcanHebeHomework( val teamId = data.teamClass?.id ?: -1 val topic = exam.getString("Content")?.trim() ?: "" + if (!isCurrentYear(eventDate)) return@forEach + val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate) val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime @@ -50,6 +59,22 @@ class VulcanHebeHomework( teamId = teamId ) + val attachments = exam.getJsonArray("Attachments") + ?.asJsonObjectList() + ?: return@forEach + + for (attachment in attachments) { + val fileName = attachment.getString("Name") ?: continue + val url = attachment.getString("Link") ?: continue + val attachmentName = "$fileName:$url" + val attachmentId = Utils.crc32(attachmentName.toByteArray()) + + eventObject.addAttachment( + id = attachmentId, + name = attachmentName + ) + } + data.eventList.add(eventObject) data.metadataList.add( Metadata( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeLuckyNumber.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeLuckyNumber.kt new file mode 100644 index 00000000..8ff1631b --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeLuckyNumber.kt @@ -0,0 +1,72 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-22. + */ + +package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe + +import com.google.gson.JsonObject +import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_LUCKY_NUMBER +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe +import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber +import pl.szczodrzynski.edziennik.data.db.entity.Metadata +import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS +import pl.szczodrzynski.edziennik.getInt +import pl.szczodrzynski.edziennik.getString +import pl.szczodrzynski.edziennik.utils.models.Date +import pl.szczodrzynski.edziennik.utils.models.Time +import pl.szczodrzynski.edziennik.utils.models.Week + +class VulcanHebeLuckyNumber( + override val data: DataVulcan, + override val lastSync: Long?, + val onSuccess: (endpointId: Int) -> Unit +) : VulcanHebe(data, lastSync) { + companion object { + const val TAG = "VulcanHebeLuckyNumber" + } + + init { + apiGet( + TAG, + VULCAN_HEBE_ENDPOINT_LUCKY_NUMBER, + query = mapOf( + "constituentId" to data.studentConstituentId.toString(), + "day" to Date.getToday().stringY_m_d + ) + ) { lucky: JsonObject?, _ -> + // sync tomorrow if lucky number set or is weekend or afternoon + var nextSync = Date.getToday().stepForward(0, 0, 1).inMillis + if (lucky == null) { + if (Date.getToday().weekDay <= Week.FRIDAY && Time.getNow().hour < 12) { + // working days morning, sync always + nextSync = SYNC_ALWAYS + } + } + else { + val luckyNumberDate = Date.fromY_m_d(lucky.getString("Day")) ?: Date.getToday() + val luckyNumber = lucky.getInt("Number") ?: -1 + val luckyNumberObject = LuckyNumber( + profileId = profileId, + date = luckyNumberDate, + number = luckyNumber + ) + + data.luckyNumberList.add(luckyNumberObject) + data.metadataList.add( + Metadata( + profileId, + Metadata.TYPE_LUCKY_NUMBER, + luckyNumberObject.date.value.toLong(), + true, + profile?.empty ?: false + ) + ) + } + + data.setSyncNext(ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER, syncAt = nextSync) + onSuccess(ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMain.kt index b3d88d04..c017e3c9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMain.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMain.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-20. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import com.google.gson.JsonArray diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessages.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessages.kt index 22fb39b7..eb4091e0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessages.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessages.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-21. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import androidx.core.util.set @@ -13,6 +17,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.* import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT +import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.navlib.crc16 import kotlin.text.replace @@ -76,6 +81,8 @@ class VulcanHebeMessages( val sentDate = getDateTime(message, "DateSent") val readDate = getDateTime(message, "DateRead", default = 0) + if (!isCurrentYear(sentDate)) return@forEach + val messageObject = Message( profileId = profileId, id = id, @@ -104,6 +111,23 @@ class VulcanHebeMessages( data.messageRecipientList.add(messageRecipientObject) } + val attachments = message.getJsonArray("Attachments") + ?.asJsonObjectList() + ?: return@forEach + + for (attachment in attachments) { + val fileName = attachment.getString("Name") ?: continue + val url = attachment.getString("Link") ?: continue + val attachmentName = "$fileName:$url" + val attachmentId = Utils.crc32(attachmentName.toByteArray()) + + messageObject.addAttachment( + id = attachmentId, + name = attachmentName, + size = -1 + ) + } + data.messageList.add(messageObject) data.setSeenMetadataList.add( Metadata( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessagesChangeStatus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessagesChangeStatus.kt index 74d3f759..ff5dbe4c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessagesChangeStatus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeMessagesChangeStatus.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-21. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import org.greenrobot.eventbus.EventBus diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeNotices.kt new file mode 100644 index 00000000..5b67b272 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeNotices.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2021-2-22 + */ + +package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe + +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_NOTICES +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_NOTICES +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe +import pl.szczodrzynski.edziennik.data.db.entity.Metadata +import pl.szczodrzynski.edziennik.data.db.entity.Notice +import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS + +class VulcanHebeNotices( + override val data: DataVulcan, + override val lastSync: Long?, + val onSuccess: (endpointId: Int) -> Unit +) : VulcanHebe(data, lastSync) { + + companion object { + const val TAG = "VulcanHebeNotices" + } + + init { + apiGetList( + TAG, + VULCAN_HEBE_ENDPOINT_NOTICES, + HebeFilterType.BY_PUPIL, + lastSync = lastSync + ) { list, _ -> + list.forEach { notice -> + val id = notice.getLong("Id") ?: return@forEach + val type = when (notice.getBoolean("Positive")) { + true -> Notice.TYPE_POSITIVE + else -> Notice.TYPE_NEUTRAL + } + val date = getDate(notice, "DateValid") ?: return@forEach + val semester = profile?.dateToSemester(date) ?: return@forEach + val text = notice.getString("Content") ?: "" + val category = notice.getJsonObject("Category")?.getString("Name") + val points = notice.getFloat("Points") + val teacherId = getTeacherId(notice, "Creator") ?: -1 + val addedDate = getDateTime(notice, "DateModify") + + if (!isCurrentYear(date)) return@forEach + + val noticeObject = Notice( + profileId = profileId, + id = id, + type = type, + semester = semester, + text = text, + category = category, + points = points, + teacherId = teacherId, + addedDate = addedDate + ) + + data.noticeList.add(noticeObject) + data.metadataList.add( + Metadata( + profileId, + Metadata.TYPE_NOTICE, + id, + profile?.empty ?: true, + profile?.empty ?: true + ) + ) + } + + data.setSyncNext(ENDPOINT_VULCAN_HEBE_NOTICES, SYNC_ALWAYS) + onSuccess(ENDPOINT_VULCAN_HEBE_NOTICES) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebePushConfig.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebePushConfig.kt new file mode 100644 index 00000000..fdf81bcb --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebePushConfig.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-22. + */ + +package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe + +import com.google.gson.JsonPrimitive +import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_PUSH_ALL +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_PUSH_CONFIG +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe +import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS + +class VulcanHebePushConfig( + override val data: DataVulcan, + override val lastSync: Long?, + val onSuccess: (endpointId: Int) -> Unit +) : VulcanHebe(data, lastSync) { + companion object { + const val TAG = "VulcanHebePushConfig" + } + + init { + apiPost( + TAG, + VULCAN_HEBE_ENDPOINT_PUSH_ALL, + payload = JsonPrimitive("on") + ) { _: Boolean, _ -> + // sync always: this endpoint has .shouldSync set + data.setSyncNext(ENDPOINT_VULCAN_HEBE_PUSH_CONFIG, SYNC_ALWAYS) + data.app.config.sync.tokenVulcanList = + data.app.config.sync.tokenVulcanList + profileId + onSuccess(ENDPOINT_VULCAN_HEBE_PUSH_CONFIG) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeSendMessage.kt new file mode 100644 index 00000000..8f5f5afa --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeSendMessage.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-22. + */ + +package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe + +import com.google.gson.JsonObject +import org.greenrobot.eventbus.EventBus +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGES_SEND +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan +import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe +import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent +import pl.szczodrzynski.edziennik.data.db.entity.Message +import pl.szczodrzynski.edziennik.data.db.entity.Metadata +import pl.szczodrzynski.edziennik.data.db.entity.Teacher + +class VulcanHebeSendMessage( + override val data: DataVulcan, + val recipients: List, + val subject: String, + val text: String, + val onSuccess: () -> Unit +) : VulcanHebe(data, null) { + companion object { + const val TAG = "VulcanHebeSendMessage" + } + + init { + val recipientsArray = JsonArray() + recipients.forEach { teacher -> + recipientsArray += JsonObject( + "Address" to teacher.fullNameLastFirst, + "LoginId" to (teacher.loginId?.toIntOrNull() ?: return@forEach), + "Initials" to teacher.initialsLastFirst, + "AddressHash" to teacher.fullNameLastFirst.sha1Hex() + ) + } + + val senderName = (profile?.accountName ?: profile?.studentNameLong) + ?.swapFirstLastName() ?: "" + val sender = JsonObject( + "Address" to senderName, + "LoginId" to data.studentLoginId.toString(), + "Initials" to senderName.getNameInitials(), + "AddressHash" to senderName.sha1Hex() + ) + + apiPost( + TAG, + VULCAN_HEBE_ENDPOINT_MESSAGES_SEND, + payload = JsonObject( + "Status" to 1, + "Sender" to sender, + "DateSent" to null, + "DateRead" to null, + "Content" to text, + "Receiver" to recipientsArray, + "Id" to 0, + "Subject" to subject, + "Attachments" to null, + "Self" to null + ) + ) { json: JsonObject, _ -> + val messageId = json.getLong("Id") + + if (messageId == null) { + // TODO error + return@apiPost + } + + VulcanHebeMessages(data, null) { + val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } + val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId } + val event = MessageSentEvent(data.profileId, message, message?.addedDate) + + EventBus.getDefault().postSticky(event) + onSuccess() + }.getMessages(Message.TYPE_SENT) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTimetable.kt index 48d06018..03a28a9e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTimetable.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTimetable.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-21. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe import com.google.gson.JsonObject diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt index 02d8b9bd..2bf633f8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt @@ -8,25 +8,21 @@ import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanWebMain import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.VulcanHebeMain import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.CufsCertificate -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginHebe import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.db.entity.Profile -import pl.szczodrzynski.edziennik.utils.models.Date class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) { companion object { const val TAG = "VulcanFirstLogin" } - private val api = VulcanApi(data, null) private val web = VulcanWebMain(data, null) private val hebe = VulcanHebe(data, null) private val profileList = mutableListOf() @@ -54,12 +50,6 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) { checkSymbol(certificate) } } - else if (data.loginStore.mode == LOGIN_MODE_VULCAN_API) { - registerDevice { - EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore)) - onSuccess() - } - } else { registerDeviceHebe { EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore)) @@ -118,96 +108,6 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) { } } - private fun registerDevice(onSuccess: () -> Unit) { - VulcanLoginApi(data) { - api.apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, _ -> - val students = json.getJsonArray("Data") - - if (students == null || students.isEmpty()) { - EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(), data.loginStore)) - onSuccess() - return@apiGet - } - - students.forEach { studentEl -> - val student = studentEl.asJsonObject - - val schoolSymbol = student.getString("JednostkaSprawozdawczaSymbol") ?: return@forEach - val schoolShort = student.getString("JednostkaSprawozdawczaSkrot") ?: return@forEach - val schoolCode = "${data.symbol}_$schoolSymbol" - val studentId = student.getInt("Id") ?: return@forEach - val studentLoginId = student.getInt("UzytkownikLoginId") ?: return@forEach - val studentClassId = student.getInt("IdOddzial") ?: return@forEach - val studentClassName = student.getString("OkresPoziom").toString() + (student.getString("OddzialSymbol") ?: return@forEach) - val studentSemesterId = student.getInt("IdOkresKlasyfikacyjny") ?: return@forEach - val studentFirstName = student.getString("Imie") ?: "" - val studentLastName = student.getString("Nazwisko") ?: "" - val studentNameLong = "$studentFirstName $studentLastName".fixName() - val studentNameShort = "$studentFirstName ${studentLastName[0]}.".fixName() - - val userLogin = student.getString("UzytkownikLogin") ?: "" - val currentSemesterStartDate = student.getLong("OkresDataOd") ?: return@forEach - val currentSemesterEndDate = (student.getLong("OkresDataDo") ?: return@forEach) + 86400 - val studentSemesterNumber = student.getInt("OkresNumer") ?: return@forEach - - val isParent = student.getString("UzytkownikRola") == "opiekun" - val accountName = if (isParent) - student.getString("UzytkownikNazwa")?.swapFirstLastName()?.fixName() - else null - - var dateSemester1Start: Date? = null - var dateSemester2Start: Date? = null - var dateYearEnd: Date? = null - when (studentSemesterNumber) { - 1 -> { - dateSemester1Start = Date.fromMillis(currentSemesterStartDate * 1000) - dateSemester2Start = Date.fromMillis(currentSemesterEndDate * 1000) - } - 2 -> { - dateSemester2Start = Date.fromMillis(currentSemesterStartDate * 1000) - dateYearEnd = Date.fromMillis(currentSemesterEndDate * 1000) - } - } - - val profile = Profile( - firstProfileId++, - loginStoreId, - LOGIN_TYPE_VULCAN, - studentNameLong, - userLogin, - studentNameLong, - studentNameShort, - accountName - ).apply { - this.studentClassName = studentClassName - studentData["symbol"] = data.symbol - - studentData["studentId"] = studentId - studentData["studentLoginId"] = studentLoginId - studentData["studentClassId"] = studentClassId - studentData["studentSemesterId"] = studentSemesterId - studentData["studentSemesterNumber"] = studentSemesterNumber - studentData["semester${studentSemesterNumber}Id"] = studentSemesterId - studentData["schoolSymbol"] = schoolSymbol - studentData["schoolShort"] = schoolShort - studentData["schoolName"] = schoolCode - studentData["currentSemesterEndDate"] = currentSemesterEndDate - } - dateSemester1Start?.let { - profile.dateSemester1Start = it - profile.studentSchoolYearStart = it.year - } - dateSemester2Start?.let { profile.dateSemester2Start = it } - dateYearEnd?.let { profile.dateYearEnd = it } - - profileList.add(profile) - } - - onSuccess() - } - } - } - private fun registerDeviceHebe(onSuccess: () -> Unit) { VulcanLoginHebe(data) { VulcanHebeMain(data).getStudents( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt index b92dea88..3cbb7ea7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt @@ -5,7 +5,6 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_HEBE import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_WEB_MAIN import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan @@ -51,10 +50,6 @@ class VulcanLogin(val data: DataVulcan, val onSuccess: () -> Unit) { data.startProgress(R.string.edziennik_progress_login_vulcan_web_main) VulcanLoginWebMain(data) { onSuccess(loginMethodId) } } - LOGIN_METHOD_VULCAN_API -> { - data.startProgress(R.string.edziennik_progress_login_vulcan_api) - VulcanLoginApi(data) { onSuccess(loginMethodId) } - } LOGIN_METHOD_VULCAN_HEBE -> { data.startProgress(R.string.edziennik_progress_login_vulcan_api) VulcanLoginHebe(data) { onSuccess(loginMethodId) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt deleted file mode 100644 index def1d7e3..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2019-10-6. - */ - -package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login - -import android.os.Build -import com.google.gson.JsonObject -import im.wangchao.mhttp.Request -import im.wangchao.mhttp.Response -import im.wangchao.mhttp.callback.JsonCallbackHandler -import io.github.wulkanowy.signer.android.getPrivateKeyFromCert -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.* -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiUpdateSemester -import pl.szczodrzynski.edziennik.data.api.models.ApiError -import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi -import pl.szczodrzynski.edziennik.utils.Utils.d -import java.net.HttpURLConnection.HTTP_BAD_REQUEST -import java.util.* -import java.util.regex.Pattern - -class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) { - companion object { - private const val TAG = "VulcanLoginApi" - } - - init { run { - if (data.studentSemesterNumber == 1 && data.semester1Id == 0) - data.semester1Id = data.studentSemesterNumber - if (data.studentSemesterNumber == 2 && data.semester2Id == 0) - data.semester2Id = data.studentSemesterNumber - - copyFromLoginStore() - - if (data.profile != null && data.isApiLoginValid()) { - onSuccess() - } - else { - if (data.apiFingerprint[data.symbol].isNotNullNorEmpty() - && data.apiPrivateKey[data.symbol].isNotNullNorEmpty() - && data.symbol.isNotNullNorEmpty()) { - // (see data.isApiLoginValid()) - // the semester end date is over - VulcanApiUpdateSemester(data, null) { onSuccess() } - return@run - } - - if (data.symbol.isNotNullNorEmpty() && data.apiToken[data.symbol].isNotNullNorEmpty() && data.apiPin[data.symbol].isNotNullNorEmpty()) { - loginWithToken() - } - else { - data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING)) - } - } - }} - - private fun copyFromLoginStore() { - data.loginStore.data.apply { - // < v4.0 - PFX to Private Key migration - if (has("certificatePfx")) { - try { - val privateKey = getPrivateKeyFromCert( - if (data.apiToken[data.symbol]?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD, - getString("certificatePfx") ?: "" - ) - data.apiPrivateKey = mapOf( - data.symbol to privateKey - ) - remove("certificatePfx") - } catch (e: Throwable) { - e.printStackTrace() - } - } - - // 4.0 - new login form - copy user input to profile - if (has("symbol")) { - data.symbol = getString("symbol") - remove("symbol") - } - - // 4.0 - before Vulcan Web impl - migrate from strings to Map of Symbol to String - if (has("deviceSymbol")) { - data.symbol = getString("deviceSymbol") - remove("deviceSymbol") - } - if (has("certificateKey")) { - data.apiFingerprint = data.apiFingerprint.toMutableMap().also { - it[data.symbol] = getString("certificateKey") - } - remove("certificateKey") - } - if (has("certificatePrivate")) { - data.apiPrivateKey = data.apiPrivateKey.toMutableMap().also { - it[data.symbol] = getString("certificatePrivate") - } - remove("certificatePrivate") - } - - // map form inputs to the symbol - if (has("deviceToken")) { - data.apiToken = data.apiToken.toMutableMap().also { - it[data.symbol] = getString("deviceToken") - } - remove("deviceToken") - } - if (has("devicePin")) { - data.apiPin = data.apiPin.toMutableMap().also { - it[data.symbol] = getString("devicePin") - } - remove("devicePin") - } - } - } - - private fun loginWithToken() { - d(TAG, "Request: Vulcan/Login/Api - ${data.apiUrl}/$VULCAN_API_ENDPOINT_CERTIFICATE") - - val callback = object : JsonCallbackHandler() { - override fun onSuccess(json: JsonObject?, response: Response?) { - if (json == null) { - if (response?.code() == HTTP_BAD_REQUEST) { - data.error(TAG, ERROR_LOGIN_VULCAN_INVALID_SYMBOL, response) - return - } - data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) - .withResponse(response)) - return - } - - var tokenStatus = json.getString("TokenStatus") - if (tokenStatus == "Null" || tokenStatus == "CertGenerated") - tokenStatus = null - val error = tokenStatus ?: json.getString("Message") - error?.let { code -> - when (code) { - "TokenNotFound" -> ERROR_LOGIN_VULCAN_INVALID_TOKEN - "TokenDead" -> ERROR_LOGIN_VULCAN_EXPIRED_TOKEN - "WrongPIN" -> { - Pattern.compile("Liczba pozostałych prób: ([0-9])", Pattern.DOTALL).matcher(tokenStatus).let { matcher -> - if (matcher.matches()) - ERROR_LOGIN_VULCAN_INVALID_PIN + 1 + matcher.group(1).toInt() - else - ERROR_LOGIN_VULCAN_INVALID_PIN - } - } - "Broken" -> ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING - "OnlyKindergarten" -> ERROR_LOGIN_VULCAN_ONLY_KINDERGARTEN - "NoPupils" -> ERROR_LOGIN_VULCAN_NO_PUPILS - else -> ERROR_LOGIN_VULCAN_OTHER - }.let { errorCode -> - data.error(ApiError(TAG, errorCode) - .withApiResponse(json) - .withResponse(response)) - return - } - } - - val cert = json.getJsonObject("TokenCert") - if (cert == null) { - data.error(ApiError(TAG, ERROR_LOGIN_VULCAN_OTHER) - .withApiResponse(json) - .withResponse(response)) - return - } - - val privateKey = getPrivateKeyFromCert( - if (data.apiToken[data.symbol]?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD, - cert.getString("CertyfikatPfx") ?: "" - ) - - data.apiFingerprint = data.apiFingerprint.toMutableMap().also { - it[data.symbol] = cert.getString("CertyfikatKlucz") - } - data.apiToken = data.apiToken.toMutableMap().also { - it[data.symbol] = it[data.symbol]?.substring(0, 3) - } - data.apiPrivateKey = data.apiPrivateKey.toMutableMap().also { - it[data.symbol] = privateKey - } - data.loginStore.removeLoginData("certificatePfx") - data.loginStore.removeLoginData("apiPin") - onSuccess() - } - - override fun onFailure(response: Response?, throwable: Throwable?) { - data.error(ApiError(TAG, ERROR_REQUEST_FAILURE) - .withResponse(response) - .withThrowable(throwable)) - } - } - - val szkolnyApi = SzkolnyApi(data.app) - val firebaseToken = szkolnyApi.runCatching({ - getFirebaseToken("vulcan") - }, onError = { - // screw errors - }) ?: data.app.config.sync.tokenVulcan - - Request.builder() - .url("${data.apiUrl}$VULCAN_API_ENDPOINT_CERTIFICATE") - .userAgent(VULCAN_API_USER_AGENT) - .addHeader("RequestMobileType", "RegisterDevice") - .addParameter("PIN", data.apiPin[data.symbol]) - .addParameter("TokenKey", data.apiToken[data.symbol]) - .addParameter("DeviceId", data.buildDeviceId()) - .addParameter("DeviceName", VULCAN_API_DEVICE_NAME) - .addParameter("DeviceNameUser", "") - .addParameter("DeviceDescription", "") - .addParameter("DeviceSystemType", "Android") - .addParameter("DeviceSystemVersion", Build.VERSION.RELEASE) - .addParameter("RemoteMobileTimeKey", currentTimeUnix()) - .addParameter("TimeKey", currentTimeUnix() - 1) - .addParameter("RequestId", UUID.randomUUID().toString()) - .addParameter("AppVersion", VULCAN_API_APP_VERSION) - .addParameter("RemoteMobileAppVersion", VULCAN_API_APP_VERSION) - .addParameter("RemoteMobileAppName", VULCAN_API_APP_NAME) - .addParameter("FirebaseTokenKey", firebaseToken ?: "") - .postJson() - .allowErrorCode(HTTP_BAD_REQUEST) - .callback(callback) - .build() - .enqueue() - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginHebe.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginHebe.kt index 1308f449..ded6e937 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginHebe.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginHebe.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-20. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login import com.google.gson.JsonObject @@ -28,7 +32,7 @@ class VulcanLoginHebe(val data: DataVulcan, val onSuccess: () -> Unit) { copyFromLoginStore() - if (data.profile != null && data.isApiLoginValid()) { + if (data.profile != null && data.isHebeLoginValid()) { onSuccess() } else { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt index 896f64e8..2b62eb14 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt @@ -13,7 +13,7 @@ import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.isNotNullNorEmpty import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.fslogin.FSLogin -import pl.szczodrzynski.fslogin.realm.CufsRealm +import pl.szczodrzynski.fslogin.realm.toRealm class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) { companion object { @@ -30,8 +30,7 @@ class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) { } else { if (data.symbol.isNotNullNorEmpty() - && data.webType.isNotNullNorEmpty() - && data.webHost.isNotNullNorEmpty() + && data.webRealmData != null && (data.webEmail.isNotNullNorEmpty() || data.webUsername.isNotNullNorEmpty()) && data.webPassword.isNotNullNorEmpty()) { try { @@ -56,32 +55,28 @@ class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) { data.symbol = getString("symbol") remove("symbol") } + // 4.6 - form inputs renamed + if (has("email")) { + data.webEmail = getString("email") + remove("email") + } + if (has("username")) { + data.webUsername = getString("username") + remove("username") + } + if (has("password")) { + data.webPassword = getString("password") + remove("password") + } + } + + if (data.symbol == null && data.webRealmData != null) { + data.symbol = data.webRealmData?.symbol } } private fun loginWithCredentials(): Boolean { - val realm = when (data.webType) { - "cufs" -> CufsRealm( - host = data.webHost ?: return false, - symbol = data.symbol ?: "default", - httpCufs = data.webIsHttpCufs - ) - "adfs" -> CufsRealm( - host = data.webHost ?: return false, - symbol = data.symbol ?: "default", - httpCufs = data.webIsHttpCufs - ).toAdfsRealm(id = data.webAdfsId ?: return false) - "adfslight" -> CufsRealm( - host = data.webHost ?: return false, - symbol = data.symbol ?: "default", - httpCufs = data.webIsHttpCufs - ).toAdfsLightRealm( - id = data.webAdfsId ?: return false, - domain = data.webAdfsDomain ?: "adfslight", - isScoped = data.webIsScopedAdfs - ) - else -> return false - } + val realm = data.webRealmData?.toRealm() ?: return false val certificate = web.readCertificate()?.let { web.parseCertificate(it) } if (certificate != null && Date.fromIso(certificate.expiryDate) > System.currentTimeMillis()) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt index 042e63fe..e6d970b8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt @@ -88,11 +88,13 @@ class SzkolnyApi(val app: App) : CoroutineScope { withContext(Dispatchers.Default) { block.invoke(this@SzkolnyApi) } } catch (e: Exception) { - ErrorDetailsDialog( + withContext(coroutineContext) { + ErrorDetailsDialog( activity, listOf(e.toApiError(TAG)), R.string.error_occured - ) + ) + } null } } @@ -348,8 +350,8 @@ class SzkolnyApi(val app: App) : CoroutineScope { } @Throws(Exception::class) - fun getPlatforms(registerName: String): List { - val response = api.appLoginPlatforms(registerName).execute() + fun getRealms(registerName: String): List { + val response = api.fsLoginRealms(registerName).execute() return parseResponse(response) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt index 6046e4da..3fe78910 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt @@ -33,12 +33,12 @@ interface SzkolnyService { @POST("feedbackMessage") fun feedbackMessage(@Body request: FeedbackMessageRequest): Call> - @GET("appLogin/platforms/{registerName}") - fun appLoginPlatforms(@Path("registerName") registerName: String): Call>> - @GET("firebase/token/{registerName}") fun firebaseToken(@Path("registerName") registerName: String): Call> @GET("registerAvailability") fun registerAvailability(): Call>> + + @GET("fsLogin/{registerName}") + fun fsLoginRealms(@Path("registerName") registerName: String): Call>> } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt index c6d7ac07..b67ef993 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt @@ -46,6 +46,6 @@ object Signing { /*fun provideKey(param1: String, param2: Long): ByteArray {*/ fun pleaseStopRightNow(param1: String, param2: Long): ByteArray { - return "$param1.MTIzNDU2Nzg5MD5LwH9bSc===.$param2".sha256() + return "$param1.MTIzNDU2Nzg5MDgzuDTD2K===.$param2".sha256() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt index aee8e3af..e6d7e40e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt @@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.* LibrusLesson::class, TimetableManual::class, Metadata::class -], version = 89) +], version = 91) @TypeConverters( ConverterTime::class, ConverterDate::class, @@ -174,7 +174,9 @@ abstract class AppDb : RoomDatabase() { Migration86(), Migration87(), Migration88(), - Migration89() + Migration89(), + Migration90(), + Migration91() ).allowMainThreadQueries().build() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt index 9d13e883..0dcaa83e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt @@ -93,6 +93,25 @@ open class Event( var attachmentIds: MutableList? = null var attachmentNames: MutableList? = null + /** + * Add an attachment + * @param id attachment ID + * @param name file name incl. extension + * @return a Event to which the attachment has been added + */ + fun addAttachment(id: Long, name: String): Event { + if (attachmentIds == null) attachmentIds = mutableListOf() + if (attachmentNames == null) attachmentNames = mutableListOf() + attachmentIds?.add(id) + attachmentNames?.add(name) + return this + } + + fun clearAttachments() { + attachmentIds = null + attachmentNames = null + } + @Ignore var showAsUnseen: Boolean? = null diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/LoginStore.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/LoginStore.kt index 1ec410b5..192bd1f6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/LoginStore.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/LoginStore.kt @@ -59,6 +59,7 @@ class LoginStore( is Long -> putLoginData(key, o) is Float -> putLoginData(key, o) is Boolean -> putLoginData(key, o) + is Bundle -> putLoginData(key, o.toJsonObject()) } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt index 997e845b..9e52dc81 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt @@ -103,7 +103,9 @@ open class Profile( dateSemester2Start.year -= diff dateYearEnd.year -= diff } - return Date.getToday() >= dateYearEnd && Date.getToday().year > studentSchoolYearStart + return App.config.archiverEnabled + && Date.getToday() >= dateYearEnd + && Date.getToday().year > studentSchoolYearStart } fun isBeforeYear() = false && Date.getToday() < dateSemester1Start diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt index 27431a4f..c41b8a7a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt @@ -11,6 +11,7 @@ import androidx.room.Entity import androidx.room.Ignore import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.fixName +import pl.szczodrzynski.edziennik.getNameInitials import pl.szczodrzynski.edziennik.join import java.util.* @@ -180,6 +181,9 @@ open class Teacher { @delegate:Ignore val fullNameLastFirst by lazy { "$surname $name".fixName() } + @delegate:Ignore + val initialsLastFirst by lazy { fullNameLastFirst.getNameInitials() } + val shortName: String get() = (if (name == null || name?.length == 0) "" else name!![0].toString()) + "." + surname diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration90.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration90.kt new file mode 100644 index 00000000..7b500525 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration90.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-26. + */ + +package pl.szczodrzynski.edziennik.data.db.migration + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration90 : Migration(89, 90) { + override fun migrate(database: SupportSQLiteDatabase) { + // get all profiles using Vulcan/Hebe + database.execSQL("CREATE TABLE _90_ids (id INTEGER NOT NULL);") + database.execSQL("INSERT INTO _90_ids SELECT profileId FROM profiles JOIN loginStores USING(loginStoreId) WHERE loginStores.loginStoreType = 4 AND loginStores.loginStoreMode != 0;") + + // force full sync when updating from <4.6 + database.execSQL("DELETE FROM endpointTimers WHERE profileId IN (SELECT id FROM _90_ids);") + database.execSQL("UPDATE profiles SET empty = 1 WHERE profileId IN (SELECT id FROM _90_ids);") + // remove messages and events to re-download attachments and remove older than current school year + database.execSQL("DELETE FROM messages WHERE profileId IN (SELECT id FROM _90_ids);") + database.execSQL("DELETE FROM events WHERE profileId IN (SELECT id FROM _90_ids) AND eventAddedManually = 0;") + // remove older data + database.execSQL("DELETE FROM notices WHERE profileId IN (SELECT id FROM _90_ids);") + + // fix for v4.5 users who logged in using Vulcan/Web + database.execSQL("UPDATE loginStores SET loginStoreMode = 2 WHERE loginStoreType = 4 AND loginStoreMode = 1;") + + database.execSQL("DROP TABLE _90_ids;") + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration91.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration91.kt new file mode 100644 index 00000000..ffb8b093 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration91.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-26. + */ + +package pl.szczodrzynski.edziennik.data.db.migration + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration91 : Migration(90, 91) { + override fun migrate(database: SupportSQLiteDatabase) { + // get all profiles using Vulcan/Hebe + database.execSQL("CREATE TABLE _91_ids (id INTEGER NOT NULL);") + database.execSQL("INSERT INTO _91_ids SELECT profileId FROM profiles JOIN loginStores USING(loginStoreId) WHERE loginStores.loginStoreType = 1;") + + // force attendance sync - mobidziennik + // after enabling counting the e-attendance to statistics + database.execSQL("DELETE FROM endpointTimers WHERE profileId IN (SELECT id FROM _91_ids) AND endpointId = 2050;") + database.execSQL("UPDATE attendances SET attendanceIsCounted = 1 WHERE profileId IN (SELECT id FROM _91_ids);") + database.execSQL("UPDATE attendances SET attendanceBaseType = 2 WHERE profileId IN (SELECT id FROM _91_ids) AND attendanceTypeSymbol = ?;", + arrayOf("+ₑ")) + + database.execSQL("DROP TABLE _91_ids;") + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyVulcanFirebase.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyVulcanFirebase.kt index b7d3af9e..06c2f171 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyVulcanFirebase.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyVulcanFirebase.kt @@ -29,6 +29,7 @@ class SzkolnyVulcanFirebase(val app: App, val profiles: List, val messa val data = message.data.getString("data")?.toJsonObject() ?: return@run val type = data.getString("table") ?: return@run val studentId = data.getInt("pupilid") + val loginId = data.getInt("loginid") /* pl.vulcan.uonetmobile.auxilary.enums.CDCPushEnum */ val viewIdPair = when (type.toLowerCase(Locale.ROOT)) { @@ -42,8 +43,9 @@ class SzkolnyVulcanFirebase(val app: App, val profiles: List, val messa } val tasks = profiles.filter { - it.loginStoreType == LOGIN_TYPE_VULCAN && - it.getStudentData("studentId", 0) == studentId + it.loginStoreType == LOGIN_TYPE_VULCAN + && (it.getStudentData("studentId", 0) == studentId + || it.getStudentData("studentLoginId", 0) == loginId) }.map { EdziennikTask.syncProfile(it.id, listOf(viewIdPair)) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt index 14321317..1fa16230 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt @@ -17,7 +17,8 @@ import kotlin.coroutines.CoroutineContext class ProfileRemoveDialog( val activity: MainActivity, val profileId: Int, - val profileName: String + val profileName: String, + val noProfileRemoval: Boolean = false ) : CoroutineScope { companion object { private const val TAG = "ProfileRemoveDialog" @@ -52,7 +53,6 @@ class ProfileRemoveDialog( app.db.attendanceDao().clear(profileId) app.db.attendanceTypeDao().clear(profileId) app.db.classroomDao().clear(profileId) - app.db.configDao().clear(profileId) app.db.endpointTimerDao().clear(profileId) app.db.eventDao().clear(profileId) app.db.eventTypeDao().clear(profileId) @@ -65,23 +65,27 @@ class ProfileRemoveDialog( app.db.messageRecipientDao().clear(profileId) app.db.noticeDao().clear(profileId) app.db.noticeTypeDao().clear(profileId) - app.db.noticeTypeDao().clear(profileId) app.db.notificationDao().clear(profileId) app.db.subjectDao().clear(profileId) app.db.teacherAbsenceDao().clear(profileId) - app.db.teacherAbsenceDao().clear(profileId) app.db.teacherAbsenceTypeDao().clear(profileId) app.db.teacherDao().clear(profileId) app.db.teamDao().clear(profileId) app.db.timetableDao().clear(profileId) + app.db.metadataDao().deleteAll(profileId) + + if (noProfileRemoval) + return@async + + app.db.configDao().clear(profileId) + val loginStoreId = profileObject.loginStoreId val profilesUsingLoginStore = app.db.profileDao().getIdsByLoginStoreIdNow(loginStoreId) if (profilesUsingLoginStore.size == 1) { app.db.loginStoreDao().remove(loginStoreId) } app.db.profileDao().remove(profileId) - app.db.metadataDao().deleteAll(profileId) if (App.profileId == profileId) { app.profileLoadLast { } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabJsonAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabJsonAdapter.kt index d1543cfc..a4a332c5 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabJsonAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabJsonAdapter.kt @@ -26,6 +26,7 @@ import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonObject import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonArrayViewHolder import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonElementViewHolder import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonObjectViewHolder +import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonSubObjectViewHolder import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder import kotlin.coroutines.CoroutineContext @@ -35,14 +36,20 @@ class LabJsonAdapter( var onJsonElementClick: ((item: LabJsonElement) -> Unit)? = null ) : RecyclerView.Adapter(), CoroutineScope { companion object { - private const val TAG = "AttendanceAdapter" + private const val TAG = "LabJsonAdapter" private const val ITEM_TYPE_OBJECT = 0 - private const val ITEM_TYPE_ARRAY = 1 - private const val ITEM_TYPE_ELEMENT = 2 + private const val ITEM_TYPE_SUB_OBJECT = 1 + private const val ITEM_TYPE_ARRAY = 2 + private const val ITEM_TYPE_ELEMENT = 3 const val STATE_CLOSED = 0 const val STATE_OPENED = 1 fun expand(item: Any, level: Int): MutableList { + val path = when (item) { + is LabJsonObject -> item.key + ":" + is LabJsonArray -> item.key + ":" + else -> "" + } val json = when (item) { is LabJsonObject -> item.jsonObject is LabJsonArray -> item.jsonArray @@ -53,17 +60,16 @@ class LabJsonAdapter( } return when (json) { - is JsonObject -> json.entrySet().mapNotNull { wrap(it.key, it.value, level) } - is JsonArray -> json.mapIndexedNotNull { index, jsonElement -> wrap(index.toString(), jsonElement, level) } - else -> listOf(LabJsonElement("?", json, level)) + is JsonObject -> json.entrySet().mapNotNull { wrap(path + it.key, it.value, level) } + is JsonArray -> json.mapIndexedNotNull { index, jsonElement -> wrap(path + index.toString(), jsonElement, level) } + else -> listOf(LabJsonElement("$path?", json, level)) }.toMutableList() } - fun wrap(key: String, item: JsonElement, level: Int = 0): Any? { + fun wrap(key: String, item: JsonElement, level: Int = 0): Any { return when (item) { is JsonObject -> LabJsonObject(key, item, level + 1) is JsonArray -> LabJsonArray(key, item, level + 1) - is JsonElement -> LabJsonElement(key, item, level + 1) - else -> null + else -> LabJsonElement(key, item, level + 1) } } } @@ -80,6 +86,7 @@ class LabJsonAdapter( val inflater = LayoutInflater.from(parent.context) return when (viewType) { ITEM_TYPE_OBJECT -> JsonObjectViewHolder(inflater, parent) + ITEM_TYPE_SUB_OBJECT -> JsonSubObjectViewHolder(inflater, parent) ITEM_TYPE_ARRAY -> JsonArrayViewHolder(inflater, parent) ITEM_TYPE_ELEMENT -> JsonElementViewHolder(inflater, parent) else -> throw IllegalArgumentException("Incorrect viewType") @@ -87,8 +94,10 @@ class LabJsonAdapter( } override fun getItemViewType(position: Int): Int { - return when (items[position]) { - is LabJsonObject -> ITEM_TYPE_OBJECT + return when (val item = items[position]) { + is LabJsonObject -> + if (item.level == 1) ITEM_TYPE_OBJECT + else ITEM_TYPE_SUB_OBJECT is LabJsonArray -> ITEM_TYPE_ARRAY is LabJsonElement -> ITEM_TYPE_ELEMENT else -> throw IllegalArgumentException("Incorrect viewType") @@ -118,7 +127,7 @@ class LabJsonAdapter( View.ROTATION, if (model.state == STATE_CLOSED) 0f else 180f, if (model.state == STATE_CLOSED) 180f else 0f - ).setDuration(200).start(); + ).setDuration(200).start() } // hide the preview, show summary @@ -143,7 +152,9 @@ class LabJsonAdapter( var end: Int = items.size for (i in start until items.size) { val model1 = items[i] - val level = (model1 as? ExpandableItemModel<*>)?.level ?: 3 + val level = (model1 as? ExpandableItemModel<*>)?.level + ?: (model1 as? LabJsonElement)?.level + ?: model.level if (level <= model.level) { end = i break @@ -170,6 +181,7 @@ class LabJsonAdapter( val viewType = when (holder) { is JsonObjectViewHolder -> ITEM_TYPE_OBJECT + is JsonSubObjectViewHolder -> ITEM_TYPE_SUB_OBJECT is JsonArrayViewHolder -> ITEM_TYPE_ARRAY is JsonElementViewHolder -> ITEM_TYPE_ELEMENT else -> throw IllegalArgumentException("Incorrect viewType") @@ -180,6 +192,7 @@ class LabJsonAdapter( when { holder is JsonObjectViewHolder && item is LabJsonObject -> holder.onBind(activity, app, item, position, this) + holder is JsonSubObjectViewHolder && item is LabJsonObject -> holder.onBind(activity, app, item, position, this) holder is JsonArrayViewHolder && item is LabJsonArray -> holder.onBind(activity, app, item, position, this) holder is JsonElementViewHolder && item is LabJsonElement -> holder.onBind(activity, app, item, position, this) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt index 72b9f9f5..29a0b2b3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.launch import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding +import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.fslogin.decode @@ -45,6 +46,8 @@ class LabPageFragment : LazyFragment(), CoroutineScope { } override fun onPageCreated(): Boolean { + b.app = app + b.last10unseen.onClick { launch(Dispatchers.Default) { val events = app.db.eventDao().getAllNow(App.profileId) @@ -58,6 +61,15 @@ class LabPageFragment : LazyFragment(), CoroutineScope { b.rodo.onClick { app.db.teacherDao().query(SimpleSQLiteQuery("UPDATE teachers SET teacherSurname = \"\" WHERE profileId = ${App.profileId}")) } + + b.fullSync.onClick { + app.db.query(SimpleSQLiteQuery("UPDATE profiles SET empty = 1 WHERE profileId = ${App.profileId}")) + app.db.query(SimpleSQLiteQuery("DELETE FROM endpointTimers WHERE profileId = ${App.profileId}")) + } + + b.clearProfile.onClick { + ProfileRemoveDialog(activity, App.profileId, "FAKE", noProfileRemoval = true) + } b.removeHomework.onClick { app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabProfileFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabProfileFragment.kt index cea59402..50c64762 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabProfileFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabProfileFragment.kt @@ -10,16 +10,14 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager -import com.google.gson.JsonObject -import com.google.gson.JsonParser +import com.afollestad.materialdialogs.MaterialDialog +import com.google.gson.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.MainActivity -import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.databinding.TemplateListPageFragmentBinding -import pl.szczodrzynski.edziennik.startCoroutineTimer import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import kotlin.coroutines.CoroutineContext @@ -38,6 +36,10 @@ class LabProfileFragment : LazyFragment(), CoroutineScope { get() = job + Dispatchers.Main // local/private variables go here + private lateinit var adapter: LabJsonAdapter + private val loginStore by lazy { + app.db.loginStoreDao().getByIdNow(app.profile.loginStoreId) + } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as MainActivity?) ?: return null @@ -48,22 +50,96 @@ class LabProfileFragment : LazyFragment(), CoroutineScope { } override fun onPageCreated(): Boolean { startCoroutineTimer(100L) { - val adapter = LabJsonAdapter(activity) - val json = JsonObject().also { json -> - json.add("app.profile", app.profile.studentData) - json.add("app.config", JsonParser().parse(app.gson.toJson(app.config.values))) - EdziennikTask.profile?.let { - json.add("API.profile", it.studentData) - } ?: { - json.addProperty("API.profile", "null") - }() - EdziennikTask.loginStore?.let { - json.add("API.loginStore", it.data) - } ?: { - json.addProperty("API.loginStore", "null") - }() - } - adapter.items = LabJsonAdapter.expand(json, 0) + adapter = LabJsonAdapter(activity, onJsonElementClick = { item -> + try { + var parent: Any = Unit + var obj: Any = Unit + var objName: String = "" + item.key.split(":").forEach { el -> + parent = obj + obj = when (el) { + "App.profile" -> app.profile + "App.profile.studentData" -> app.profile.studentData + "App.profile.loginStore" -> loginStore?.data ?: JsonObject() + "App.config" -> app.config.values + else -> when (obj) { + is JsonObject -> (obj as JsonObject).get(el) + is JsonArray -> (obj as JsonArray).get(el.toInt()) + is HashMap<*, *> -> (obj as HashMap)[el].toString() + else -> { + val field = obj::class.java.getDeclaredField(el) + field.isAccessible = true + field.get(obj) ?: return@forEach + } + } + } + objName = el + } + + val objVal = obj + val value = when (objVal) { + is JsonPrimitive -> when { + objVal.isString -> objVal.asString + objVal.isNumber -> objVal.asNumber.toString() + objVal.isBoolean -> objVal.asBoolean.toString() + else -> objVal.asString + } + else -> objVal.toString() + } + + MaterialDialog.Builder(activity) + .input("value", value, false) { _, input -> + val input = input.toString() + when (parent) { + is JsonObject -> { + val v = objVal as JsonPrimitive + when { + v.isString -> (parent as JsonObject)[objName] = input + v.isNumber -> (parent as JsonObject)[objName] = input.toLong() + v.isBoolean -> (parent as JsonObject)[objName] = input.toBoolean() + } + } + is JsonArray -> { + + } + is HashMap<*, *> -> app.config.set(objName, input) + else -> { + val field = parent::class.java.getDeclaredField(objName) + field.isAccessible = true + val newVal = when (objVal) { + is Int -> input.toInt() + is Boolean -> input.toBoolean() + is Float -> input.toFloat() + is Char -> input.toCharArray()[0] + is String -> input + is Long -> input.toLong() + is Double -> input.toDouble() + else -> input + } + field.set(parent, newVal) + } + } + + when (item.key.substringBefore(":")) { + "App.profile" -> app.profileSave() + "App.profile.studentData" -> app.profileSave() + "App.profile.loginStore" -> app.db.loginStoreDao().add(loginStore) + } + + showJson() + + } + .title(item.key) + .positiveText(R.string.ok) + .negativeText(R.string.cancel) + .show() + } + catch (e: Exception) { + activity.error(ApiError.fromThrowable(TAG, e)) + } + }) + + showJson() b.list.adapter = adapter b.list.apply { @@ -79,4 +155,15 @@ class LabProfileFragment : LazyFragment(), CoroutineScope { b.noData.isVisible = false }; return true } + + private fun showJson() { + val json = JsonObject().also { json -> + json.add("App.profile", app.gson.toJsonTree(app.profile)) + json.add("App.profile.studentData", app.profile.studentData) + json.add("App.profile.loginStore", loginStore?.data ?: JsonObject()) + json.add("App.config", JsonParser().parse(app.gson.toJson(app.config.values))) + } + adapter.items = LabJsonAdapter.expand(json, 0) + adapter.notifyDataSetChanged() + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonArrayViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonArrayViewHolder.kt index 08d4cd3c..56645c28 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonArrayViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonArrayViewHolder.kt @@ -13,6 +13,7 @@ import androidx.core.view.isInvisible import androidx.recyclerview.widget.RecyclerView import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.databinding.LabItemObjectBinding +import pl.szczodrzynski.edziennik.dp import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter import pl.szczodrzynski.edziennik.ui.modules.debug.LabJsonAdapter import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonArray @@ -32,6 +33,10 @@ class JsonArrayViewHolder( override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonArray, position: Int, adapter: LabJsonAdapter) { val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme) + b.root.setPadding(item.level * 8.dp + 8.dp, 8.dp, 8.dp, 8.dp) + + b.type.text = "Array" + b.dropdownIcon.rotation = when (item.state) { AttendanceAdapter.STATE_CLOSED -> 0f else -> 180f @@ -39,7 +44,7 @@ class JsonArrayViewHolder( b.previewContainer.isInvisible = item.state != AttendanceAdapter.STATE_CLOSED b.summaryContainer.isInvisible = item.state == AttendanceAdapter.STATE_CLOSED - b.key.text = item.key + b.key.text = item.key.substringAfterLast(":") b.previewContainer.text = item.jsonArray.toString().take(200) b.summaryContainer.text = item.jsonArray.size().toString() + " elements" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonElementViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonElementViewHolder.kt index 8ce6b461..20b1c2c8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonElementViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonElementViewHolder.kt @@ -32,6 +32,8 @@ class JsonElementViewHolder( override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonElement, position: Int, adapter: LabJsonAdapter) { val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme) + b.root.setPadding(item.level * 8.dp + 8.dp, 8.dp, 8.dp, 8.dp) + b.type.text = when (item.jsonElement) { is JsonPrimitive -> when { item.jsonElement.isNumber -> "Number" @@ -45,7 +47,9 @@ class JsonElementViewHolder( val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity) b.key.text = listOf( - item.key.asColoredSpannable(colorSecondary), + item.key + .substringAfterLast(":") + .asColoredSpannable(colorSecondary), ": ", item.jsonElement.toString().asItalicSpannable() ).concat("") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonObjectViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonObjectViewHolder.kt index 3131b0ea..b4de8efe 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonObjectViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonObjectViewHolder.kt @@ -13,6 +13,7 @@ import androidx.core.view.isInvisible import androidx.recyclerview.widget.RecyclerView import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.databinding.LabItemObjectBinding +import pl.szczodrzynski.edziennik.dp import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter import pl.szczodrzynski.edziennik.ui.modules.debug.LabJsonAdapter import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonObject @@ -32,6 +33,10 @@ class JsonObjectViewHolder( override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonObject, position: Int, adapter: LabJsonAdapter) { val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme) + b.root.setPadding(item.level * 8.dp + 8.dp, 8.dp, 8.dp, 8.dp) + + b.type.text = "Object" + b.dropdownIcon.rotation = when (item.state) { AttendanceAdapter.STATE_CLOSED -> 0f else -> 180f @@ -39,7 +44,7 @@ class JsonObjectViewHolder( b.previewContainer.isInvisible = item.state != AttendanceAdapter.STATE_CLOSED b.summaryContainer.isInvisible = item.state == AttendanceAdapter.STATE_CLOSED - b.key.text = item.key + b.key.text = item.key.substringAfterLast(":") b.previewContainer.text = item.jsonObject.toString().take(200) b.summaryContainer.text = item.jsonObject.size().toString() + " elements" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonSubObjectViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonSubObjectViewHolder.kt new file mode 100644 index 00000000..dbc71ca2 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/viewholder/JsonSubObjectViewHolder.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-2-26. + */ + +package pl.szczodrzynski.edziennik.ui.modules.debug.viewholder + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.view.ContextThemeWrapper +import androidx.recyclerview.widget.RecyclerView +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.databinding.LabItemSubObjectBinding +import pl.szczodrzynski.edziennik.dp +import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter +import pl.szczodrzynski.edziennik.ui.modules.debug.LabJsonAdapter +import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonObject +import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder +import pl.szczodrzynski.edziennik.utils.Themes + +class JsonSubObjectViewHolder( + inflater: LayoutInflater, + parent: ViewGroup, + val b: LabItemSubObjectBinding = LabItemSubObjectBinding.inflate(inflater, parent, false) +) : RecyclerView.ViewHolder(b.root), BindableViewHolder { + companion object { + private const val TAG = "JsonSubObjectViewHolder" + } + + @SuppressLint("SetTextI18n") + override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonObject, position: Int, adapter: LabJsonAdapter) { + val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme) + + b.root.setPadding(item.level * 8.dp + 8.dp, 8.dp, 8.dp, 8.dp) + + b.type.text = "Object" + + b.dropdownIcon.rotation = when (item.state) { + AttendanceAdapter.STATE_CLOSED -> 0f + else -> 180f + } + + b.key.text = item.key.substringAfterLast(":") + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt index e223d5fc..8776f355 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt @@ -14,7 +14,6 @@ import androidx.core.view.isVisible import androidx.core.widget.addTextChangedListener import androidx.fragment.app.Fragment import com.google.android.material.textfield.TextInputLayout -import com.google.gson.JsonParser import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.utils.paddingDp import com.mikepenz.iconics.utils.sizeDp @@ -72,7 +71,7 @@ class LoginFormFragment : Fragment(), CoroutineScope { val platformGuideText = arguments?.getString("platformGuideText") val platformDescription = arguments?.getString("platformDescription") val platformFormFields = arguments?.getString("platformFormFields")?.split(";") - val platformApiData = arguments?.getString("platformApiData")?.let { JsonParser().parse(it)?.asJsonObject } + val platformRealmData = arguments?.getString("platformRealmData")?.toJsonObject() b.title.setText(R.string.login_form_title_format, app.getString(register.registerName)) b.subTitle.text = platformName ?: app.getString(mode.name) @@ -159,9 +158,7 @@ class LoginFormFragment : Fragment(), CoroutineScope { payload.putBoolean("fakeLogin", true) } - platformApiData?.entrySet()?.forEach { - payload.putString(it.key, it.value.asString) - } + payload.putBundle("webRealmData", platformRealmData?.toBundle()) var hasErrors = false credentials.forEach { (credential, b) -> diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt index 13fa6123..949848a5 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt @@ -6,456 +6,412 @@ package pl.szczodrzynski.edziennik.ui.modules.login import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import com.google.gson.JsonObject import com.mikepenz.iconics.typeface.IIcon import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel +import pl.szczodrzynski.fslogin.realm.RealmData object LoginInfo { private fun getEmailCredential(keyName: String) = FormField( - keyName = keyName, - name = R.string.login_hint_email, - icon = CommunityMaterial.Icon.cmd_at, - emptyText = R.string.login_error_no_email, - invalidText = R.string.login_error_incorrect_email, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+", - caseMode = FormField.CaseMode.LOWER_CASE - ) - private fun getPasswordCredential(keyName: String) = FormField( - keyName = keyName, - name = R.string.login_hint_password, - icon = CommunityMaterial.Icon2.cmd_lock_outline, - emptyText = R.string.login_error_no_password, - invalidText = R.string.login_error_incorrect_login_or_password, - errorCodes = mapOf(), - isRequired = true, - validationRegex = ".*", - hideText = true + keyName = keyName, + name = R.string.login_hint_email, + icon = CommunityMaterial.Icon.cmd_at, + emptyText = R.string.login_error_no_email, + invalidText = R.string.login_error_incorrect_email, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+", + caseMode = FormField.CaseMode.LOWER_CASE ) - val list by lazy { listOf( + private fun getPasswordCredential(keyName: String) = FormField( + keyName = keyName, + name = R.string.login_hint_password, + icon = CommunityMaterial.Icon2.cmd_lock_outline, + emptyText = R.string.login_error_no_password, + invalidText = R.string.login_error_incorrect_login_or_password, + errorCodes = mapOf(), + isRequired = true, + validationRegex = ".*", + hideText = true + ) + + val list by lazy { + listOf( Register( - loginType = LOGIN_TYPE_LIBRUS, - internalName = "librus", - registerName = R.string.login_register_librus, - registerLogo = R.drawable.login_logo_librus, - loginModes = listOf( - Mode( - loginMode = LOGIN_MODE_LIBRUS_EMAIL, - name = R.string.login_mode_librus_email, - icon = R.drawable.login_mode_librus_email, - hintText = R.string.login_mode_librus_email_hint, - guideText = R.string.login_mode_librus_email_guide, - isRecommended = true, - credentials = listOf( - getEmailCredential("email"), - getPasswordCredential("password") + loginType = LOGIN_TYPE_LIBRUS, + internalName = "librus", + registerName = R.string.login_register_librus, + registerLogo = R.drawable.login_logo_librus, + loginModes = listOf( + Mode( + loginMode = LOGIN_MODE_LIBRUS_EMAIL, + name = R.string.login_mode_librus_email, + icon = R.drawable.login_mode_librus_email, + hintText = R.string.login_mode_librus_email_hint, + guideText = R.string.login_mode_librus_email_guide, + isRecommended = true, + credentials = listOf( + getEmailCredential("email"), + getPasswordCredential("password") + ), + errorCodes = mapOf( + ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED to R.string.login_error_account_not_activated, + ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password, + ERROR_CAPTCHA_LIBRUS_PORTAL to R.string.error_3001_reason + ) + ), + /*Mode( + loginMode = LOGIN_MODE_LIBRUS_SYNERGIA, + name = R.string.login_mode_librus_synergia, + icon = R.drawable.login_mode_librus_synergia, + hintText = R.string.login_mode_librus_synergia_hint, + guideText = R.string.login_mode_librus_synergia_guide, + credentials = listOf( + Credential( + keyName = "accountLogin", + name = R.string.login_hint_login, + icon = CommunityMaterial.Icon.cmd_account_outline, + emptyText = R.string.login_error_no_login, + invalidText = R.string.login_error_incorrect_login, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "[A-z0-9._\\-+]+", + caseMode = Credential.CaseMode.LOWER_CASE ), - errorCodes = mapOf( - ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED to R.string.login_error_account_not_activated, - ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password, - ERROR_CAPTCHA_LIBRUS_PORTAL to R.string.error_3001_reason - ) + getPasswordCredential("accountPassword") ), - /*Mode( - loginMode = LOGIN_MODE_LIBRUS_SYNERGIA, - name = R.string.login_mode_librus_synergia, - icon = R.drawable.login_mode_librus_synergia, - hintText = R.string.login_mode_librus_synergia_hint, - guideText = R.string.login_mode_librus_synergia_guide, - credentials = listOf( - Credential( - keyName = "accountLogin", - name = R.string.login_hint_login, - icon = CommunityMaterial.Icon.cmd_account_outline, - emptyText = R.string.login_error_no_login, - invalidText = R.string.login_error_incorrect_login, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "[A-z0-9._\\-+]+", - caseMode = Credential.CaseMode.LOWER_CASE - ), - getPasswordCredential("accountPassword") - ), - errorCodes = mapOf( - ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password, - ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST to R.string.login_error_incorrect_login_or_password - ) - ),*/ - Mode( - loginMode = LOGIN_MODE_LIBRUS_JST, - name = R.string.login_mode_librus_jst, - icon = R.drawable.login_mode_librus_jst, - hintText = R.string.login_mode_librus_jst_hint, - guideText = R.string.login_mode_librus_jst_guide, - credentials = listOf( - FormField( - keyName = "accountCode", - name = R.string.login_hint_token, - icon = CommunityMaterial.Icon.cmd_code_braces, - emptyText = R.string.login_error_no_token, - invalidText = R.string.login_error_incorrect_token, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "[A-Z0-9_]+", - caseMode = FormField.CaseMode.UPPER_CASE - ), - FormField( - keyName = "accountPin", - name = R.string.login_hint_pin, - icon = CommunityMaterial.Icon2.cmd_lock, - emptyText = R.string.login_error_no_pin, - invalidText = R.string.login_error_incorrect_pin, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "[a-z0-9_]+", - caseMode = FormField.CaseMode.LOWER_CASE - ) - ), - errorCodes = mapOf( - ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN to R.string.login_error_incorrect_code_or_pin, - ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST to R.string.login_error_incorrect_code_or_pin - ) + errorCodes = mapOf( + ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password, + ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST to R.string.login_error_incorrect_login_or_password ) - ) - ), - Register( - loginType = LOGIN_TYPE_VULCAN, - internalName = "vulcan", - registerName = R.string.login_type_vulcan, - registerLogo = R.drawable.login_logo_vulcan, - loginModes = listOf( - Mode( - loginMode = LOGIN_MODE_VULCAN_HEBE, - name = R.string.login_mode_vulcan_api, - icon = R.drawable.login_mode_vulcan_hebe, - hintText = R.string.login_mode_vulcan_api_hint, - guideText = R.string.login_mode_vulcan_api_guide, - isRecommended = true, - credentials = listOf( - FormField( - keyName = "deviceToken", - name = R.string.login_hint_token, - icon = CommunityMaterial.Icon.cmd_code_braces, - emptyText = R.string.login_error_no_token, - invalidText = R.string.login_error_incorrect_token, - errorCodes = mapOf( - ERROR_LOGIN_VULCAN_INVALID_TOKEN to R.string.login_error_incorrect_token - ), - isRequired = true, - validationRegex = "[A-Z0-9]{5,12}", - caseMode = FormField.CaseMode.UPPER_CASE - ), - FormField( - keyName = "symbol", - name = R.string.login_hint_symbol, - icon = CommunityMaterial.Icon2.cmd_school, - emptyText = R.string.login_error_no_symbol, - invalidText = R.string.login_error_incorrect_symbol, - errorCodes = mapOf( - ERROR_LOGIN_VULCAN_INVALID_SYMBOL to R.string.login_error_incorrect_symbol - ), - isRequired = true, - validationRegex = "[a-z0-9_-]+", - caseMode = FormField.CaseMode.LOWER_CASE - ), - FormField( - keyName = "devicePin", - name = R.string.login_hint_pin, - icon = CommunityMaterial.Icon2.cmd_lock, - emptyText = R.string.login_error_no_pin, - invalidText = R.string.login_error_incorrect_pin, - errorCodes = mapOf( - ERROR_LOGIN_VULCAN_INVALID_PIN to R.string.login_error_incorrect_pin - ), - isRequired = true, - validationRegex = "[0-9]+", - caseMode = FormField.CaseMode.LOWER_CASE - ) - ), - errorCodes = mapOf( - ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token - ) + ),*/ + Mode( + loginMode = LOGIN_MODE_LIBRUS_JST, + name = R.string.login_mode_librus_jst, + icon = R.drawable.login_mode_librus_jst, + hintText = R.string.login_mode_librus_jst_hint, + guideText = R.string.login_mode_librus_jst_guide, + credentials = listOf( + FormField( + keyName = "accountCode", + name = R.string.login_hint_token, + icon = CommunityMaterial.Icon.cmd_code_braces, + emptyText = R.string.login_error_no_token, + invalidText = R.string.login_error_incorrect_token, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "[A-Z0-9_]+", + caseMode = FormField.CaseMode.UPPER_CASE ), - Mode( - loginMode = LOGIN_MODE_VULCAN_WEB, - name = R.string.login_mode_vulcan_web, - icon = R.drawable.login_mode_vulcan_web, - hintText = R.string.login_mode_vulcan_web_hint, - guideText = R.string.login_mode_vulcan_web_guide, - isDevOnly = true, - isPlatformSelection = true, - credentials = listOf( - getEmailCredential("webEmail"), - FormField( - keyName = "webUsername", - name = R.string.login_hint_username, - icon = CommunityMaterial.Icon.cmd_account_outline, - emptyText = R.string.login_error_no_username, - invalidText = R.string.login_error_incorrect_username, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "[A-Z]{7}[0-9]+", - caseMode = FormField.CaseMode.UPPER_CASE - ), - getPasswordCredential("webPassword") - ), - errorCodes = mapOf() + FormField( + keyName = "accountPin", + name = R.string.login_hint_pin, + icon = CommunityMaterial.Icon2.cmd_lock, + emptyText = R.string.login_error_no_pin, + invalidText = R.string.login_error_incorrect_pin, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "[a-z0-9_]+", + caseMode = FormField.CaseMode.LOWER_CASE ) + ), + errorCodes = mapOf( + ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN to R.string.login_error_incorrect_code_or_pin, + ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST to R.string.login_error_incorrect_code_or_pin + ) ) + ) ), Register( - loginType = LOGIN_TYPE_MOBIDZIENNIK, - internalName = "mobidziennik", - registerName = R.string.login_type_mobidziennik, - registerLogo = R.drawable.login_logo_mobidziennik, - loginModes = listOf( - Mode( - loginMode = LOGIN_MODE_MOBIDZIENNIK_WEB, - name = R.string.login_mode_mobidziennik_web, - icon = R.drawable.login_mode_mobidziennik_web, - hintText = R.string.login_mode_mobidziennik_web_hint, - guideText = R.string.login_mode_mobidziennik_web_guide, - credentials = listOf( - FormField( - keyName = "username", - name = R.string.login_hint_login_email, - icon = CommunityMaterial.Icon.cmd_account_outline, - emptyText = R.string.login_error_no_login, - invalidText = R.string.login_error_incorrect_login, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "^[a-z0-9_\\-@+.]+$", - caseMode = FormField.CaseMode.LOWER_CASE - ), - FormField( - keyName = "password", - name = R.string.login_hint_password, - icon = CommunityMaterial.Icon2.cmd_lock_outline, - emptyText = R.string.login_error_no_password, - invalidText = R.string.login_error_incorrect_login_or_password, - errorCodes = mapOf( - ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD to R.string.login_error_old_password - ), - isRequired = true, - validationRegex = ".*", - hideText = true - ), - FormField( - keyName = "serverName", - name = R.string.login_hint_address, - icon = CommunityMaterial.Icon2.cmd_web, - emptyText = R.string.login_error_no_address, - invalidText = R.string.login_error_incorrect_address, - errorCodes = mapOf( - ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS to R.string.login_error_incorrect_address - ), - isRequired = true, - validationRegex = "^[a-z0-9_\\-]+\$", - caseMode = FormField.CaseMode.LOWER_CASE - ) - ), - errorCodes = mapOf( - ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password, - ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED to R.string.sync_error_archived - ) + loginType = LOGIN_TYPE_VULCAN, + internalName = "vulcan", + registerName = R.string.login_type_vulcan, + registerLogo = R.drawable.login_logo_vulcan, + loginModes = listOf( + Mode( + loginMode = LOGIN_MODE_VULCAN_HEBE, + name = R.string.login_mode_vulcan_api, + icon = R.drawable.login_mode_vulcan_hebe, + hintText = R.string.login_mode_vulcan_api_hint, + guideText = R.string.login_mode_vulcan_api_guide, + isRecommended = true, + credentials = listOf( + FormField( + keyName = "deviceToken", + name = R.string.login_hint_token, + icon = CommunityMaterial.Icon.cmd_code_braces, + emptyText = R.string.login_error_no_token, + invalidText = R.string.login_error_incorrect_token, + errorCodes = mapOf( + ERROR_LOGIN_VULCAN_INVALID_TOKEN to R.string.login_error_incorrect_token, + ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token + ), + isRequired = true, + validationRegex = "[A-Z0-9]{5,12}", + caseMode = FormField.CaseMode.UPPER_CASE + ), + FormField( + keyName = "symbol", + name = R.string.login_hint_symbol, + icon = CommunityMaterial.Icon2.cmd_school, + emptyText = R.string.login_error_no_symbol, + invalidText = R.string.login_error_incorrect_symbol, + errorCodes = mapOf( + ERROR_LOGIN_VULCAN_INVALID_SYMBOL to R.string.login_error_incorrect_symbol + ), + isRequired = true, + validationRegex = "[a-z0-9_-]+", + caseMode = FormField.CaseMode.LOWER_CASE + ), + FormField( + keyName = "devicePin", + name = R.string.login_hint_pin, + icon = CommunityMaterial.Icon2.cmd_lock, + emptyText = R.string.login_error_no_pin, + invalidText = R.string.login_error_incorrect_pin, + errorCodes = mapOf( + ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING to R.string.error_310_reason, + ERROR_LOGIN_VULCAN_INVALID_PIN_1_REMAINING to R.string.error_311_reason, + ERROR_LOGIN_VULCAN_INVALID_PIN_2_REMAINING to R.string.error_312_reason + ), + isRequired = true, + validationRegex = "[0-9]+", + caseMode = FormField.CaseMode.LOWER_CASE ) + ), + errorCodes = mapOf() + ), + Mode( + loginMode = LOGIN_MODE_VULCAN_WEB, + name = R.string.login_mode_vulcan_web, + icon = R.drawable.login_mode_vulcan_web, + hintText = R.string.login_mode_vulcan_web_hint, + guideText = R.string.login_mode_vulcan_web_guide, + isTesting = true, + isPlatformSelection = true, + credentials = listOf( + getEmailCredential("email"), + FormField( + keyName = "username", + name = R.string.login_hint_username, + icon = CommunityMaterial.Icon.cmd_account_outline, + emptyText = R.string.login_error_no_username, + invalidText = R.string.login_error_incorrect_username, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "[A-Z]{7}[0-9]+", + caseMode = FormField.CaseMode.UPPER_CASE + ), + getPasswordCredential("password") + ), + errorCodes = mapOf() ) + ) ), Register( - loginType = LOGIN_TYPE_IDZIENNIK, - internalName = "idziennik", - registerName = R.string.login_type_idziennik, - registerLogo = R.drawable.login_logo_iuczniowie, - loginModes = listOf( - Mode( - loginMode = LOGIN_MODE_IDZIENNIK_WEB, - name = R.string.login_mode_idziennik_web, - icon = R.drawable.login_mode_idziennik_web, - hintText = R.string.login_mode_idziennik_web_hint, - guideText = R.string.login_mode_idziennik_web_guide, - credentials = listOf( - FormField( - keyName = "schoolName", - name = R.string.login_hint_school_name, - icon = CommunityMaterial.Icon2.cmd_school, - emptyText = R.string.login_error_no_school_name, - invalidText = R.string.login_error_incorrect_school_name, - errorCodes = mapOf( - ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME to R.string.login_error_incorrect_school_name - ), - isRequired = true, - validationRegex = "^[a-z0-9_\\-.]+$", - caseMode = FormField.CaseMode.LOWER_CASE - ), - FormField( - keyName = "username", - name = R.string.login_hint_username, - icon = CommunityMaterial.Icon.cmd_account_outline, - emptyText = R.string.login_error_no_username, - invalidText = R.string.login_error_incorrect_username, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "^[a-z0-9_\\-.]+$", - caseMode = FormField.CaseMode.LOWER_CASE - ), - getPasswordCredential("password") - ), - errorCodes = mapOf( - ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password - ) + loginType = LOGIN_TYPE_MOBIDZIENNIK, + internalName = "mobidziennik", + registerName = R.string.login_type_mobidziennik, + registerLogo = R.drawable.login_logo_mobidziennik, + loginModes = listOf( + Mode( + loginMode = LOGIN_MODE_MOBIDZIENNIK_WEB, + name = R.string.login_mode_mobidziennik_web, + icon = R.drawable.login_mode_mobidziennik_web, + hintText = R.string.login_mode_mobidziennik_web_hint, + guideText = R.string.login_mode_mobidziennik_web_guide, + credentials = listOf( + FormField( + keyName = "username", + name = R.string.login_hint_login_email, + icon = CommunityMaterial.Icon.cmd_account_outline, + emptyText = R.string.login_error_no_login, + invalidText = R.string.login_error_incorrect_login, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "^[a-z0-9_\\-@+.]+$", + caseMode = FormField.CaseMode.LOWER_CASE + ), + FormField( + keyName = "password", + name = R.string.login_hint_password, + icon = CommunityMaterial.Icon2.cmd_lock_outline, + emptyText = R.string.login_error_no_password, + invalidText = R.string.login_error_incorrect_login_or_password, + errorCodes = mapOf( + ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD to R.string.login_error_old_password + ), + isRequired = true, + validationRegex = ".*", + hideText = true + ), + FormField( + keyName = "serverName", + name = R.string.login_hint_address, + icon = CommunityMaterial.Icon2.cmd_web, + emptyText = R.string.login_error_no_address, + invalidText = R.string.login_error_incorrect_address, + errorCodes = mapOf( + ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS to R.string.login_error_incorrect_address + ), + isRequired = true, + validationRegex = "^[a-z0-9_\\-]+\$", + caseMode = FormField.CaseMode.LOWER_CASE ) + ), + errorCodes = mapOf( + ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password, + ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED to R.string.sync_error_archived + ) ) + ) ), Register( - loginType = LOGIN_TYPE_EDUDZIENNIK, - internalName = "edudziennik", - registerName = R.string.login_type_edudziennik, - registerLogo = R.drawable.login_logo_edudziennik, - loginModes = listOf( - Mode( - loginMode = LOGIN_MODE_EDUDZIENNIK_WEB, - name = R.string.login_mode_edudziennik_web, - icon = R.drawable.login_mode_edudziennik_web, - hintText = R.string.login_mode_edudziennik_web_hint, - guideText = R.string.login_mode_edudziennik_web_guide, - credentials = listOf( - getEmailCredential("email"), - getPasswordCredential("password") - ), - errorCodes = mapOf( - ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password - ) - ) + loginType = LOGIN_TYPE_EDUDZIENNIK, + internalName = "edudziennik", + registerName = R.string.login_type_edudziennik, + registerLogo = R.drawable.login_logo_edudziennik, + loginModes = listOf( + Mode( + loginMode = LOGIN_MODE_EDUDZIENNIK_WEB, + name = R.string.login_mode_edudziennik_web, + icon = R.drawable.login_mode_edudziennik_web, + hintText = R.string.login_mode_edudziennik_web_hint, + guideText = R.string.login_mode_edudziennik_web_guide, + credentials = listOf( + getEmailCredential("email"), + getPasswordCredential("password") + ), + errorCodes = mapOf( + ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password + ) ) + ) ), Register( - loginType = LOGIN_TYPE_PODLASIE, - internalName = "podlasie", - registerName = R.string.login_type_podlasie, - registerLogo = R.drawable.login_logo_podlasie, - loginModes = listOf( - Mode( - loginMode = LOGIN_MODE_PODLASIE_API, - name = R.string.login_mode_podlasie_api, - icon = R.drawable.login_mode_podlasie_api, - guideText = R.string.login_mode_podlasie_api_guide, - credentials = listOf( - FormField( - keyName = "apiToken", - name = R.string.login_hint_token, - icon = CommunityMaterial.Icon2.cmd_lock_outline, - emptyText = R.string.login_error_no_token, - invalidText = R.string.login_error_incorrect_token, - errorCodes = mapOf(), - isRequired = true, - validationRegex = "[a-zA-Z0-9]{10}", - caseMode = FormField.CaseMode.UNCHANGED - ), - FormCheckbox( - keyName = "logoutDevices", - name = R.string.login_podlasie_logout_devices, - checked = false, - errorCodes = mapOf( - ERROR_LOGIN_PODLASIE_API_DEVICE_LIMIT to R.string.error_602_reason - ) - ) - ), - errorCodes = mapOf() + loginType = LOGIN_TYPE_PODLASIE, + internalName = "podlasie", + registerName = R.string.login_type_podlasie, + registerLogo = R.drawable.login_logo_podlasie, + loginModes = listOf( + Mode( + loginMode = LOGIN_MODE_PODLASIE_API, + name = R.string.login_mode_podlasie_api, + icon = R.drawable.login_mode_podlasie_api, + guideText = R.string.login_mode_podlasie_api_guide, + credentials = listOf( + FormField( + keyName = "apiToken", + name = R.string.login_hint_token, + icon = CommunityMaterial.Icon2.cmd_lock_outline, + emptyText = R.string.login_error_no_token, + invalidText = R.string.login_error_incorrect_token, + errorCodes = mapOf(), + isRequired = true, + validationRegex = "[a-zA-Z0-9]{10}", + caseMode = FormField.CaseMode.UNCHANGED + ), + FormCheckbox( + keyName = "logoutDevices", + name = R.string.login_podlasie_logout_devices, + checked = false, + errorCodes = mapOf( + ERROR_LOGIN_PODLASIE_API_DEVICE_LIMIT to R.string.error_602_reason + ) ) + ), + errorCodes = mapOf() ) + ) ) - ) } + ) + } data class Register( - val loginType: Int, - val internalName: String, - val registerName: Int, - @DrawableRes - val registerLogo: Int, + val loginType: Int, + val internalName: String, + val registerName: Int, + @DrawableRes + val registerLogo: Int, - val loginModes: List + val loginModes: List ) : ExpandableItemModel(loginModes.toMutableList()) { override var level = 1 } data class Mode( - val loginMode: Int, + val loginMode: Int, - @StringRes - val name: Int, - @DrawableRes - val icon: Int, - @StringRes - val hintText: Int? = null, - @StringRes - val guideText: Int, + @StringRes + val name: Int, + @DrawableRes + val icon: Int, + @StringRes + val hintText: Int? = null, + @StringRes + val guideText: Int, - val isRecommended: Boolean = false, - val isTesting: Boolean = false, - val isDevOnly: Boolean = false, - val isPlatformSelection: Boolean = false, + val isRecommended: Boolean = false, + val isTesting: Boolean = false, + val isDevOnly: Boolean = false, + val isPlatformSelection: Boolean = false, - val credentials: List, - val errorCodes: Map + val credentials: List, + val errorCodes: Map ) data class Platform( - val id: Int, - val loginType: Int, - val loginMode: Int, - val name: String, - val description: String?, - val guideText: String?, - val icon: String, - val screenshot: String?, - val formFields: List, - val apiData: JsonObject + val id: Int, + val name: String, + val description: String?, + val icon: String, + val screenshot: String?, + val formFields: List, + val realmData: RealmData ) open class BaseCredential( - open val keyName: String, - @StringRes - open val name: Int, - open val errorCodes: Map + open val keyName: String, + @StringRes + open val name: Int, + open val errorCodes: Map ) data class FormField( - override val keyName: String, + override val keyName: String, - @StringRes - override val name: Int, - val icon: IIcon, - @StringRes - val placeholder: Int? = null, - @StringRes - val emptyText: Int, - @StringRes - val invalidText: Int, - override val errorCodes: Map, - @StringRes - val hintText: Int? = null, + @StringRes + override val name: Int, + val icon: IIcon, + @StringRes + val placeholder: Int? = null, + @StringRes + val emptyText: Int, + @StringRes + val invalidText: Int, + override val errorCodes: Map, + @StringRes + val hintText: Int? = null, - val isRequired: Boolean = true, - val validationRegex: String, - val caseMode: CaseMode = CaseMode.UNCHANGED, - val hideText: Boolean = false, - val stripTextRegex: String? = null + val isRequired: Boolean = true, + val validationRegex: String, + val caseMode: CaseMode = CaseMode.UNCHANGED, + val hideText: Boolean = false, + val stripTextRegex: String? = null ) : BaseCredential(keyName, name, errorCodes) { enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE } } data class FormCheckbox( - override val keyName: String, - @StringRes - override val name: Int, - val checked: Boolean = false, - override val errorCodes: Map = mapOf() + override val keyName: String, + @StringRes + override val name: Int, + val checked: Boolean = false, + override val errorCodes: Map = mapOf() ) : BaseCredential(keyName, name, errorCodes) var chooserList: MutableList? = null diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt index ad5fb3d9..988d1bde 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPlatformListFragment.kt @@ -60,12 +60,12 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope { adapter = LoginPlatformAdapter(activity) { platform -> nav.navigate(R.id.loginFormFragment, Bundle( - "loginType" to platform.loginType, - "loginMode" to platform.loginMode, + "loginType" to loginType, + "loginMode" to loginMode, "platformName" to platform.name, "platformDescription" to platform.description, "platformFormFields" to platform.formFields.joinToString(";"), - "platformApiData" to platform.apiData.toString() + "platformRealmData" to app.gson.toJson(platform.realmData) ), activity.navOptions) } @@ -96,7 +96,7 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope { val platforms = LoginInfo.platformList[mode.name] ?: run { api.runCatching(activity) { - getPlatforms(register.internalName) + getRealms(register.internalName) } ?: run { nav.navigateUp() return@launch diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java index 551efd01..555bc3fd 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java @@ -258,7 +258,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { .color(IconicsColor.colorInt(iconColor)) ) .setOnClickAction(() -> { - new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName()); + new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName(), false); }) ); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentsView.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentsView.kt index 482ab847..354a8921 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentsView.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentsView.kt @@ -121,19 +121,21 @@ class AttachmentsView @JvmOverloads constructor( // open file by name, or first part before ':' (Vulcan OneDrive) Utils.openFile(context, File(Utils.getStorageDir(), attachment.name.substringBefore(":"))) return - } + } else if (attachment.name.contains(":")) { + Utils.openUrl(context, attachment.name.substringAfter(":")) + } else { + attachment.isDownloading = true + (adapter as? AttachmentAdapter)?.let { + it.notifyItemChanged(it.items.indexOf(attachment)) + } - attachment.isDownloading = true - (adapter as? AttachmentAdapter)?.let { - it.notifyItemChanged(it.items.indexOf(attachment)) - } - - EdziennikTask.attachmentGet( + EdziennikTask.attachmentGet( attachment.profileId, attachment.owner, attachment.id, attachment.name - ).enqueue(context) + ).enqueue(context) + } } private val lastUpdate: Long = 0 diff --git a/app/src/main/res/drawable/login_help_iuczniowie.webp b/app/src/main/res/drawable/login_help_iuczniowie.webp deleted file mode 100644 index 5a163bb9..00000000 Binary files a/app/src/main/res/drawable/login_help_iuczniowie.webp and /dev/null differ diff --git a/app/src/main/res/drawable/login_logo_iuczniowie.png b/app/src/main/res/drawable/login_logo_iuczniowie.png deleted file mode 100644 index 4356c305..00000000 Binary files a/app/src/main/res/drawable/login_logo_iuczniowie.png and /dev/null differ diff --git a/app/src/main/res/drawable/login_logo_vulcan.png b/app/src/main/res/drawable/login_logo_vulcan.png index fd7adcc8..fe00724a 100644 Binary files a/app/src/main/res/drawable/login_logo_vulcan.png and b/app/src/main/res/drawable/login_logo_vulcan.png differ diff --git a/app/src/main/res/drawable/login_mode_vulcan_api.png b/app/src/main/res/drawable/login_mode_vulcan_api.png deleted file mode 100644 index a8ec0993..00000000 Binary files a/app/src/main/res/drawable/login_mode_vulcan_api.png and /dev/null differ diff --git a/app/src/main/res/drawable/login_mode_vulcan_web.png b/app/src/main/res/drawable/login_mode_vulcan_web.png index 3644cd15..559b2eb5 100644 Binary files a/app/src/main/res/drawable/login_mode_vulcan_web.png and b/app/src/main/res/drawable/login_mode_vulcan_web.png differ diff --git a/app/src/main/res/drawable/logo_idziennik.png b/app/src/main/res/drawable/logo_idziennik.png deleted file mode 100644 index 7289caa6..00000000 Binary files a/app/src/main/res/drawable/logo_idziennik.png and /dev/null differ diff --git a/app/src/main/res/layout/lab_fragment.xml b/app/src/main/res/layout/lab_fragment.xml index b023e11c..8152f917 100644 --- a/app/src/main/res/layout/lab_fragment.xml +++ b/app/src/main/res/layout/lab_fragment.xml @@ -7,6 +7,10 @@ xmlns:android="http://schemas.android.com/apk/res/android" tools:ignore="HardcodedText"> + + + + @@ -41,6 +45,22 @@ android:text="Set last 10 as unseen" android:textAllCaps="false" /> +