)(.*?)""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_ATTENDANCE_COLUMN_SPAN by lazy {
+ """colspan="(\d+)"""".toRegex()
+ }
+ val MOBIDZIENNIK_ATTENDANCE_RANGE by lazy {
+ """([0-9:]+) - .+? (.+?) """.toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_ATTENDANCE_LESSON by lazy {
+ """(.+?) \s*\s*\((.+?),\s*(.+?)\)""".toRegex(DOT_MATCHES_ALL)
+ }
+
+ val MOBIDZIENNIK_HOMEWORK_ROW by lazy {
+ """class="rowRolling">(.+?\s*)""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_HOMEWORK_ITEM by lazy {
+ """ (.+?): \s*(.+?)\s*
""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_HOMEWORK_BODY by lazy {
+ """Treść:(.+?)""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_HOMEWORK_ID by lazy {
+ """zadanieFormularz\(([0-9]+),""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_HOMEWORK_ATTACHMENT by lazy {
+ """zalacznik(_zadania)?=([0-9]+)'.+?word-break">(.+?)""".toRegex(DOT_MATCHES_ALL)
+ }
+
+
+ val MOBIDZIENNIK_TIMETABLE_TOP by lazy {
+ """
.+?
""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_TIMETABLE_CELL by lazy {
+ """.+?style="(.+?)".+?title="(.+?)".+?>\s+(.+?)\s+
""".toRegex(DOT_MATCHES_ALL)
+ }
+ val MOBIDZIENNIK_TIMETABLE_LEFT by lazy {
+ """.+?
""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
- """ """.toRegex(RegexOption.DOT_MATCHES_ALL)
+ """ """.toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_ERROR by lazy {
- """id="spanErrorMessage">(.*?)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """id="spanErrorMessage">(.*?)""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME by lazy {
- """Imię i nazwisko:.+?">(.+?)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """Imię i nazwisko:.+?">(.+?)""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_IS_PARENT by lazy {
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
}
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy {
- """name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9]+)/([0-9]+)<""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
- """""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_STUDENT by lazy {
- """(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)""".toRegex(DOT_MATCHES_ALL)
+ }
+ val IDZIENNIK_MESSAGES_RECIPIENT_PARENT by lazy {
+ """(.+?)\s\((.+)\)""".toRegex()
+ }
+ /*Szczęśliwy los na dzisiaj to 19 . Los na jutro to 22 */
+ val IDZIENNIK_WEB_LUCKY_NUMBER by lazy {
+ """dzisiaj to ([0-9]+) """.toRegex()
+ }
+ val IDZIENNIK_WEB_SELECTED_REGISTER by lazy {
+ """selected="selected" value="([0-9]+)" data-id-ucznia""".toRegex()
}
- val VULCAN_SHITFT_ANNOTATION by lazy {
+ val VULCAN_SHIFT_ANNOTATION by lazy {
"""\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex()
}
+ val VULCAN_WEB_PERMISSIONS by lazy {
+ """permissions: '([A-z0-9/=+\-_|]+?)'""".toRegex()
+ }
+ val VULCAN_WEB_SYMBOL_VALIDATE by lazy {
+ """[A-z0-9]+""".toRegex(IGNORE_CASE)
+ }
val LIBRUS_ATTACHMENT_KEY by lazy {
- """singleUseKey=([0-9A-f_]+)""".toRegex()
+ """singleUseKey=([0-9A-z_]+)""".toRegex()
+ }
+ val LIBRUS_MESSAGE_ID by lazy {
+ """/wiadomosci/[0-9]+/[0-9]+/([0-9]+?)/""".toRegex()
+ }
+
+
+
+ val EDUDZIENNIK_STUDENTS_START by lazy {
+ """(.*?) """.toRegex()
+ }
+ val EDUDZIENNIK_ACCOUNT_NAME_START by lazy {
+ """(.*?) """.toRegex()
+ }
+ val EDUDZIENNIK_SUBJECTS_START by lazy {
+ """""".toRegex()
+ }
+
+ val EDUDZIENNIK_ATTENDANCE_ENTRIES by lazy {
+ """(.+?) """.toRegex()
+ }
+ val EDUDZIENNIK_ATTENDANCE_TYPES by lazy {
+ """.*?
(.*?)
""".toRegex(DOT_MATCHES_ALL)
+ }
+ val EDUDZIENNIK_ATTENDANCE_TYPE by lazy {
+ """\((.+?)\) (.+)""".toRegex()
+ }
+
+ val EDUDZIENNIK_ANNOUNCEMENT_DESCRIPTION by lazy {
+ """
.*?
(.*?)
""".toRegex(DOT_MATCHES_ALL)
+ }
+ val EDUDZIENNIK_HOMEWORK_DESCRIPTION by lazy {
+ """
(.*?)
""".toRegex(DOT_MATCHES_ALL)
+ }
+
+ val EDUDZIENNIK_SUBJECT_ID by lazy {
+ """/Courses/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_GRADE_ID by lazy {
+ """/Grades/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_EXAM_ID by lazy {
+ """/Evaluations/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_EVENT_TYPE_ID by lazy {
+ """/GradeLabels/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_ANNOUNCEMENT_ID by lazy {
+ """/Announcement/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_HOMEWORK_ID by lazy {
+ """/Homework/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_TEACHER_ID by lazy {
+ """/Teachers/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_EVENT_ID by lazy {
+ """/KlassEvent/([\w-_]+?)/""".toRegex()
+ }
+ val EDUDZIENNIK_NOTE_ID by lazy {
+ """/RegistryNotes/([\w-_]+?)/""".toRegex()
+ }
+
+ val EDUDZIENNIK_SCHOOL_DETAIL_ID by lazy {
+ """
.*?(.*?)
.*?""".toRegex(DOT_MATCHES_ALL)
+ }
+ val EDUDZIENNIK_CLASS_DETAIL_ID by lazy {
+ """(.*?) """.toRegex(DOT_MATCHES_ALL)
+ }
+
+ val EDUDZIENNIK_TEACHERS by lazy {
+ """.*?
(.+?) (.+?)
""".toRegex(DOT_MATCHES_ALL)
+ }
+
+
+
+
+ val LINKIFY_DATE_YMD by lazy {
+ """(1\d{3}|20\d{2})[\-./](1[0-2]|0?\d)[\-./]([1-2]\d|3[0-1]|0?\d)""".toRegex()
+ }
+ val LINKIFY_DATE_DMY by lazy {
+ """(?>? = null, onlyEndpoints: List
? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, onlyEndpoints, arguments))
+ fun syncProfileList(profileList: List) = EdziennikTask(-1, SyncProfileListRequest(profileList))
+ fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message))
+ fun messageSend(profileId: Int, recipients: List, subject: String, text: String) = EdziennikTask(profileId, MessageSendRequest(recipients, subject, text))
+ fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
+ fun announcementGet(profileId: Int, announcement: AnnouncementFull) = EdziennikTask(profileId, AnnouncementGetRequest(announcement))
+ fun attachmentGet(profileId: Int, owner: Any, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(owner, attachmentId, attachmentName))
+ fun recipientListGet(profileId: Int) = EdziennikTask(profileId, RecipientListGetRequest())
+ fun eventGet(profileId: Int, event: EventFull) = EdziennikTask(profileId, EventGetRequest(event))
+ }
+
+ private lateinit var loginStore: LoginStore
+
+ override fun prepare(app: App) {
+ if (request is FirstLoginRequest) {
+ // get the requested profile and login store
+ this.profile = null
+ loginStore = request.loginStore
+ // save the profile ID and name as the current task's
+ taskName = app.getString(R.string.edziennik_notification_api_first_login_title)
+ } else {
+ // get the requested profile and login store
+ val profile = app.db.profileDao().getByIdNow(profileId) ?: return
+ this.profile = profile
+ val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return
+ this.loginStore = loginStore
+ // save the profile ID and name as the current task's
+ taskName = app.getString(R.string.edziennik_notification_api_sync_title_format, profile.name)
+ }
+ EdziennikTask.profile = this.profile
+ EdziennikTask.loginStore = this.loginStore
+ }
+
+ private var edziennikInterface: EdziennikInterface? = null
+
+ internal fun run(app: App, taskCallback: EdziennikCallback) {
+ profile?.let { profile ->
+ if (profile.archived) {
+ d(TAG, "The profile $profileId is archived")
+ taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED))
+ return
+ }
+ else if (profile.shouldArchive()) {
+ d(TAG, "The profile $profileId's year ended on ${profile.dateYearEnd}, archiving")
+ ProfileArchiver(app, profile)
+ }
+ if (profile.isBeforeYear()) {
+ d(TAG, "The profile $profileId's school year has not started yet; aborting sync")
+ cancel()
+ taskCallback.onCompleted()
+ return
+ }
+
+ val error = app.availabilityManager.check(profile)
+ when (error?.type) {
+ Type.NOT_AVAILABLE -> {
+ if (EventBus.getDefault().hasSubscriberForEvent(RegisterAvailabilityEvent::class.java)) {
+ EventBus.getDefault().postSticky(RegisterAvailabilityEvent())
+ }
+ cancel()
+ taskCallback.onCompleted()
+ return
+ }
+ Type.API_ERROR -> {
+ taskCallback.onError(error.apiError!!)
+ return
+ }
+ else -> return@let
+ }
+ }
+
+ edziennikInterface = when (loginStore.type) {
+ 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_EDUDZIENNIK -> Edudziennik(app, profile, loginStore, taskCallback)
+ LOGIN_TYPE_PODLASIE -> Podlasie(app, profile, loginStore, taskCallback)
+ LOGIN_TYPE_TEMPLATE -> Template(app, profile, loginStore, taskCallback)
+ else -> null
+ }
+ if (edziennikInterface == null) {
+ return
+ }
+
+ when (request) {
+ is SyncProfileRequest -> edziennikInterface?.sync(
+ featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) }
+ ?: Features.getAllIds(),
+ viewId = request.viewIds?.get(0)?.first,
+ onlyEndpoints = request.onlyEndpoints,
+ arguments = request.arguments)
+ is MessageGetRequest -> edziennikInterface?.getMessage(request.message)
+ is MessageSendRequest -> edziennikInterface?.sendMessage(request.recipients, request.subject, request.text)
+ is FirstLoginRequest -> edziennikInterface?.firstLogin()
+ is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
+ is AnnouncementGetRequest -> edziennikInterface?.getAnnouncement(request.announcement)
+ is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.owner, request.attachmentId, request.attachmentName)
+ is RecipientListGetRequest -> edziennikInterface?.getRecipientList()
+ is EventGetRequest -> edziennikInterface?.getEvent(request.event)
+ }
+ }
+
+ override fun cancel() {
+ d(TAG, "Task ${toString()} cancelling...")
+ edziennikInterface?.cancel()
+ }
+
+ override fun toString(): String {
+ return "EdziennikTask(profileId=$profileId, request=$request, edziennikInterface=$edziennikInterface)"
+ }
+
+ data class FirstLoginRequest(val loginStore: LoginStore)
+ class SyncRequest
+ data class SyncProfileRequest(val viewIds: List>? = null, val onlyEndpoints: List? = null, val arguments: JsonObject? = null)
+ data class SyncProfileListRequest(val profileList: List)
+ data class MessageGetRequest(val message: MessageFull)
+ data class MessageSendRequest(val recipients: List, val subject: String, val text: String)
+ class AnnouncementsReadRequest
+ data class AnnouncementGetRequest(val announcement: AnnouncementFull)
+ data class AttachmentGetRequest(val owner: Any, val attachmentId: Long, val attachmentName: String)
+ class RecipientListGetRequest
+ data class EventGetRequest(val event: EventFull)
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt
new file mode 100644
index 00000000..15da9765
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-8-25.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik
+
+import android.content.Intent
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.Intent
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.utils.Utils.d
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class ProfileArchiver(val app: App, val profile: Profile) {
+ companion object {
+ private const val TAG = "ProfileArchiver"
+ }
+
+ init {
+ if (profile.archiveId == null)
+ profile.archiveId = profile.id
+ d(TAG, "Processing ${profile.name}#${profile.id}, archiveId = ${profile.archiveId}")
+
+ profile.archived = true
+ app.db.profileDao().add(profile)
+ //app.db.metadataDao().setAllSeen(profile.id, true)
+ app.db.notificationDao().clear(profile.id)
+ app.db.endpointTimerDao().clear(profile.id)
+ d(TAG, "Archived profile ${profile.id} saved")
+ profile.archived = false
+
+ // guess the nearest school year
+ val today = Date.getToday()
+ profile.studentSchoolYearStart = when {
+ today.month <= profile.dateYearEnd.month -> today.year - 1
+ else -> today.year
+ }
+
+ // set default semester dates
+ profile.dateSemester1Start = Date(profile.studentSchoolYearStart, 9, 1)
+ profile.dateSemester2Start = Date(profile.studentSchoolYearStart + 1, 2, 1)
+ profile.dateYearEnd = Date(profile.studentSchoolYearStart + 1, 6, 30)
+
+ val oldId = profile.id
+ val newId = (app.db.profileDao().lastId ?: profile.id) + 1
+ profile.id = newId
+ profile.subname = "Nowy rok szkolny - ${profile.studentSchoolYearStart}"
+ profile.studentClassName = null
+
+ d(TAG, "New profile ID for ${profile.name}: ${profile.id}")
+
+ when (profile.loginStoreType) {
+ LOGIN_TYPE_LIBRUS -> {
+ profile.removeStudentData("isPremium")
+ profile.removeStudentData("pushDeviceId")
+ profile.removeStudentData("startPointsSemester1")
+ profile.removeStudentData("startPointsSemester2")
+ profile.removeStudentData("enablePointGrades")
+ profile.removeStudentData("enableDescriptiveGrades")
+ }
+ LOGIN_TYPE_MOBIDZIENNIK -> {
+
+ }
+ LOGIN_TYPE_VULCAN -> {
+ // DataVulcan.isApiLoginValid() returns false so it will update the semester
+ profile.removeStudentData("currentSemesterEndDate")
+ profile.removeStudentData("studentSemesterId")
+ profile.removeStudentData("studentSemesterNumber")
+ profile.removeStudentData("semester1Id")
+ profile.removeStudentData("semester2Id")
+ profile.removeStudentData("studentClassId")
+ }
+ LOGIN_TYPE_IDZIENNIK -> {
+ profile.removeStudentData("schoolYearId")
+ }
+ LOGIN_TYPE_EDUDZIENNIK -> {
+
+ }
+ LOGIN_TYPE_PODLASIE -> {
+
+ }
+ }
+
+ d(TAG, "Processed student data: ${profile.studentData}")
+
+ app.db.profileDao().add(profile)
+
+ if (app.profileId == oldId) {
+ val intent = Intent(
+ Intent.ACTION_MAIN,
+ "profileId" to newId
+ )
+ app.sendBroadcast(intent)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt
new file mode 100644
index 00000000..49a9d4a0
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/DataEdudziennik.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
+
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
+import pl.szczodrzynski.edziennik.data.api.models.Data
+import pl.szczodrzynski.edziennik.data.db.entity.*
+
+/**
+ * Use http://patorjk.com/software/taag/#p=display&f=Big for the ascii art
+ *
+ * Use https://codepen.io/kubasz/pen/RwwwbGN to easily generate the student data getters/setters
+ */
+class DataEdudziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
+
+ fun isWebLoginValid() = webSessionIdExpiryTime-30 > currentTimeUnix() && webSessionId.isNotNullNorEmpty()
+
+ override fun satisfyLoginMethods() {
+ loginMethods.clear()
+ if (isWebLoginValid()) {
+ loginMethods += LOGIN_METHOD_EDUDZIENNIK_WEB
+ }
+ }
+
+ override fun generateUserCode() = "$schoolName:$loginEmail:${studentId?.crc32()}"
+
+ private var mLoginEmail: String? = null
+ var loginEmail: String?
+ get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail }
+ set(value) { loginStore.putLoginData("email", value); mLoginEmail = value }
+
+ private var mLoginPassword: String? = null
+ var loginPassword: String?
+ get() { mLoginPassword = mLoginPassword ?: loginStore.getLoginData("password", null); return mLoginPassword }
+ set(value) { loginStore.putLoginData("password", value); mLoginPassword = 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 mSchoolId: String? = null
+ var schoolId: String?
+ get() { mSchoolId = mSchoolId ?: profile?.getStudentData("schoolId", null); return mSchoolId }
+ set(value) { profile?.putStudentData("schoolId", value) ?: return; mSchoolId = value }
+
+ private var mClassId: String? = null
+ var classId: String?
+ get() { mClassId = mClassId ?: profile?.getStudentData("classId", null); return mClassId }
+ set(value) { profile?.putStudentData("classId", value) ?: return; mClassId = 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 mWebSessionIdExpiryTime: Long? = null
+ var webSessionIdExpiryTime: Long
+ get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("webSessionIdExpiryTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
+ set(value) { loginStore.putLoginData("webSessionIdExpiryTime", value); mWebSessionIdExpiryTime = value }
+
+ /* ____ _ _
+ / __ \| | | |
+ | | | | |_| |__ ___ _ __
+ | | | | __| '_ \ / _ \ '__|
+ | |__| | |_| | | | __/ |
+ \____/ \__|_| |_|\___|*/
+ private var mCurrentSemester: Int? = null
+ var currentSemester: Int
+ get() { mCurrentSemester = mCurrentSemester ?: profile?.getStudentData("currentSemester", 1); return mCurrentSemester ?: 1 }
+ set(value) { profile?.putStudentData("currentSemester", value) ?: return; mCurrentSemester = value }
+
+ private var mSchoolName: String? = null
+ var schoolName: String?
+ get() { mSchoolName = mSchoolName ?: profile?.getStudentData("schoolName", null); return mSchoolName }
+ set(value) { profile?.putStudentData("schoolName", value) ?: return; mSchoolName = value }
+
+ val studentEndpoint: String
+ get() = "Students/$studentId/"
+
+ val schoolEndpoint: String
+ get() = "Schools/$schoolId/"
+
+ val classStudentEndpoint: String
+ get() = "Class/$studentId/"
+
+ val schoolClassEndpoint: String
+ get() = "Schools/$classId/"
+
+ val studentAndClassEndpoint: String
+ get() = "Students/$studentId/Klass/$classId/"
+
+ val studentAndClassesEndpoint: String
+ get() = "Students/$studentId/Classes/$classId/"
+
+ val timetableEndpoint: String
+ get() = "Plan/$studentId/"
+
+ val studentAndTeacherClassEndpoint: String
+ get() = "Students/$studentId/Teachers/$classId/"
+
+ val courseStudentEndpoint: String
+ get() = "Course/$studentId/"
+
+ fun getEventType(longId: String, name: String): EventType {
+ val id = longId.crc16().toLong()
+ return eventTypes.singleOrNull { it.id == id } ?: run {
+ val eventType = EventType(profileId, id, name, colorFromName(name))
+ eventTypes.put(id, eventType)
+ eventType
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/Edudziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/Edudziennik.kt
new file mode 100644
index 00000000..23d9d3b1
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/Edudziennik.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
+
+import com.google.gson.JsonObject
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikData
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebGetAnnouncement
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebGetHomework
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin.EdudziennikFirstLogin
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLogin
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLoginWeb
+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.LoginStore
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
+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 Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
+ companion object {
+ private const val TAG = "Edudziennik"
+ }
+
+ val internalErrorList = mutableListOf()
+ val data: DataEdudziennik
+ private var afterLogin: (() -> Unit)? = null
+
+ init {
+ data = DataEdudziennik(app, profile, loginStore).apply {
+ callback = wrapCallback(this@Edudziennik.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(edudziennikLoginMethods, EdudziennikFeatures, 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(edudziennikLoginMethods, it) }
+ afterLogin?.let { this.afterLogin = it }
+ EdudziennikLogin(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() ?: EdudziennikData(data) {
+ completed()
+ }
+ }
+
+ override fun getMessage(message: MessageFull) {}
+ override fun sendMessage(recipients: List, subject: String, text: String) {}
+ override fun markAllAnnouncementsAsRead() {}
+
+ override fun getAnnouncement(announcement: AnnouncementFull) {
+ EdudziennikLoginWeb(data) {
+ EdudziennikWebGetAnnouncement(data, announcement) {
+ completed()
+ }
+ }
+ }
+
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {}
+ override fun getRecipientList() {}
+
+ override fun getEvent(eventFull: EventFull) {
+ EdudziennikLoginWeb(data) {
+ EdudziennikWebGetHomework(data, eventFull) {
+ completed()
+ }
+ }
+ }
+
+ override fun firstLogin() { EdudziennikFirstLogin(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_EDUDZIENNIK_WEB_SESSION_EXPIRED -> {
+ login()
+ }
+ ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID -> {
+ login()
+ }
+ ERROR_EDUDZIENNIK_WEB_LIMITED_ACCESS -> {
+ data()
+ }
+ else -> callback.onError(apiError)
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt
new file mode 100644
index 00000000..c3fd17ed
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-23
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
+
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.models.Feature
+
+const val ENDPOINT_EDUDZIENNIK_WEB_START = 1000
+const val ENDPOINT_EDUDZIENNIK_WEB_TEACHERS = 1001
+const val ENDPOINT_EDUDZIENNIK_WEB_GRADES = 1011
+const val ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE = 1012
+const val ENDPOINT_EDUDZIENNIK_WEB_EXAMS = 1013
+const val ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE = 1014
+const val ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS = 1015
+const val ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK = 1016
+const val ENDPOINT_EDUDZIENNIK_WEB_EVENTS = 1017
+const val ENDPOINT_EDUDZIENNIK_WEB_NOTES = 1018
+const val ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER = 1030
+
+val EdudziennikFeatures = listOf(
+ /* School and team info and subjects */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_STUDENT_INFO, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_START to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Teachers */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_TEACHERS, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_TEACHERS to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Timetable */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_TIMETABLE, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Grades */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_GRADES, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_GRADES to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Agenda */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_AGENDA, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_EXAMS to LOGIN_METHOD_EDUDZIENNIK_WEB,
+ ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK to LOGIN_METHOD_EDUDZIENNIK_WEB,
+ ENDPOINT_EDUDZIENNIK_WEB_EVENTS to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Homework */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_HOMEWORK, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Behaviour */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_BEHAVIOUR, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_NOTES to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Attendance */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_ATTENDANCE, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Announcements */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_ANNOUNCEMENTS, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
+ /* Lucky number */
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_LUCKY_NUMBER, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB))
+)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt
new file mode 100644
index 00000000..7eb58d1c
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
+
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.*
+import pl.szczodrzynski.edziennik.utils.Utils
+
+class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
+ companion object {
+ private const val TAG = "EdudziennikData"
+ }
+
+ 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_EDUDZIENNIK_WEB_START -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_data)
+ EdudziennikWebStart(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_TEACHERS -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_teachers)
+ EdudziennikWebTeachers(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_GRADES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_grades)
+ EdudziennikWebGrades(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_timetable)
+ EdudziennikWebTimetable(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_EXAMS -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_exams)
+ EdudziennikWebExams(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_attendance)
+ EdudziennikWebAttendance(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_announcements)
+ EdudziennikWebAnnouncements(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_homework)
+ EdudziennikWebHomework(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_EVENTS -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_events)
+ EdudziennikWebEvents(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_NOTES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_notices)
+ EdudziennikWebNotes(data, lastSync, onSuccess)
+ }
+ ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
+ EdudziennikWebLuckyNumber(data, lastSync, onSuccess)
+ }
+ else -> onSuccess(endpointId)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikWeb.kt
new file mode 100644
index 00000000..f5adfc5d
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikWeb.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
+
+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.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.utils.Utils.d
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+open class EdudziennikWeb(open val data: DataEdudziennik, open val lastSync: Long?) {
+ companion object {
+ private const val TAG = "EdudziennikWeb"
+ }
+
+ val profileId
+ get() = data.profile?.id ?: -1
+
+ val profile
+ get() = data.profile
+
+ fun webGet(tag: String, endpoint: String, xhr: Boolean = false, semester: Int? = null, onSuccess: (text: String) -> Unit) {
+ val url = "https://dziennikel.appspot.com/" + when (endpoint.endsWith('/') || endpoint.contains('?') || endpoint.isEmpty()) {
+ true -> endpoint
+ else -> "$endpoint/"
+ } + (semester?.let { "?semester=" + if(it == -1) "all" else it } ?: "")
+
+ d(tag, "Request: Edudziennik/Web - $url")
+
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response?) {
+ if (text == null || response == null) {
+ data.error(ApiError(tag, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return
+ }
+
+ if (semester == null && url.contains("start")) {
+ profile?.also { profile ->
+ val cookies = data.app.cookieJar.getAll("dziennikel.appspot.com")
+ val semesterCookie = cookies["semester"]?.toIntOrNull()
+
+ semesterCookie?.let { data.currentSemester = it }
+
+ if (semesterCookie == 2 && profile.dateSemester2Start > Date.getToday())
+ profile.dateSemester2Start = Date.getToday().stepForward(0, 0, -1)
+ }
+ }
+
+ try {
+ onSuccess(text)
+ } catch (e: Exception) {
+ data.error(ApiError(tag, EXCEPTION_EDUDZIENNIK_WEB_REQUEST)
+ .withThrowable(e)
+ .withResponse(response)
+ .withApiResponse(text))
+ }
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ val error = when (response?.code()) {
+ 402 -> ERROR_EDUDZIENNIK_WEB_LIMITED_ACCESS
+ 403 -> ERROR_EDUDZIENNIK_WEB_SESSION_EXPIRED
+ else -> ERROR_REQUEST_FAILURE
+ }
+ data.error(ApiError(tag, error)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ data.app.cookieJar.set("dziennikel.appspot.com", "sessionid", data.webSessionId)
+
+ Request.builder()
+ .url(url)
+ .userAgent(EDUDZIENNIK_USER_AGENT)
+ .apply {
+ if (xhr) header("X-Requested-With", "XMLHttpRequest")
+ }
+ .get()
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAnnouncements.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAnnouncements.kt
new file mode 100644
index 00000000..32ca353c
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAnnouncements.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-26
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ANNOUNCEMENT_ID
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.get
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class EdudziennikWebAnnouncements(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ const val TAG = "EdudziennikWebAnnouncements"
+ }
+
+ init { data.profile?.also { profile ->
+ webGet(TAG, data.schoolClassEndpoint + "Announcements") { text ->
+ val doc = Jsoup.parse(text)
+
+ if (doc.getElementsByClass("message").text().trim() != "Brak ogłoszeń.") {
+ doc.select("table.list tbody tr").forEach { announcementElement ->
+ val titleElement = announcementElement.child(0).child(0)
+
+ val longId = EDUDZIENNIK_ANNOUNCEMENT_ID.find(titleElement.attr("href"))?.get(1)
+ ?: return@forEach
+ val id = longId.crc32()
+ val subject = titleElement.text()
+
+ val teacherName = announcementElement.child(1).text()
+ val teacher = data.getTeacherByFirstLast(teacherName)
+
+ val dateString = announcementElement.getElementsByClass("datetime").first().text()
+ val startDate = Date.fromY_m_d(dateString)
+ val addedDate = Date.fromIsoHm(dateString)
+
+ val announcementObject = Announcement(
+ profileId = profileId,
+ id = id,
+ subject = subject,
+ text = null,
+ startDate = startDate,
+ endDate = null,
+ teacherId = teacher.id,
+ addedDate = addedDate
+ ).also {
+ it.idString = longId
+ }
+
+ data.announcementList.add(announcementObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_ANNOUNCEMENT,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+ }
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS)
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt
new file mode 100644
index 00000000..7fe18171
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-24
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_ENTRIES
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPE
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPES
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.singleOrNull
+import pl.szczodrzynski.edziennik.utils.models.Date
+import java.util.*
+
+class EdudziennikWebAttendance(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "EdudziennikWebAttendance"
+ }
+
+ private var requestSemester: Int? = null
+
+ init {
+ if (profile?.empty == true && data.currentSemester == 2) requestSemester = 1
+ getAttendances()
+ }
+
+ private fun getAttendances() { data.profile?.also { profile ->
+ webGet(TAG, data.studentEndpoint + "Presence", semester = requestSemester) { text ->
+
+ val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
+ val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
+ val symbol = type?.get(1)?.trim() ?: "?"
+ val name = type?.get(2)?.trim() ?: "nieznany rodzaj"
+ return@map Triple(
+ symbol,
+ name,
+ when (name.toLowerCase(Locale.ROOT)) {
+ "obecność" -> Attendance.TYPE_PRESENT
+ "nieobecność" -> Attendance.TYPE_ABSENT
+ "spóźnienie" -> Attendance.TYPE_BELATED
+ "nieobecność usprawiedliwiona" -> Attendance.TYPE_ABSENT_EXCUSED
+ "dzień wolny" -> Attendance.TYPE_DAY_FREE
+ "brak zajęć" -> Attendance.TYPE_DAY_FREE
+ "oddelegowany" -> Attendance.TYPE_RELEASED
+ else -> Attendance.TYPE_UNKNOWN
+ }
+ )
+ } ?: emptyList()
+
+ EDUDZIENNIK_ATTENDANCE_ENTRIES.findAll(text).forEach { attendanceElement ->
+ val date = Date.fromY_m_d(attendanceElement[1])
+ val lessonNumber = attendanceElement[2].toInt()
+ val attendanceSymbol = attendanceElement[3]
+
+ val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
+ val lesson = lessons.firstOrNull { it.lessonNumber == lessonNumber }
+
+ val id = "${date.stringY_m_d}:$lessonNumber:$attendanceSymbol".crc32()
+
+ val (typeSymbol, typeName, baseType) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol }
+ ?: return@forEach
+
+ val startTime = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }?.startTime
+ ?: return@forEach
+
+ val attendanceObject = Attendance(
+ profileId = profileId,
+ id = id,
+ baseType = baseType,
+ typeName = typeName,
+ typeShort = data.app.attendanceManager.getTypeShort(baseType),
+ typeSymbol = typeSymbol,
+ typeColor = null,
+ date = date,
+ startTime = lesson?.displayStartTime ?: startTime,
+ semester = profile.currentSemester,
+ teacherId = lesson?.displayTeacherId ?: -1,
+ subjectId = lesson?.displaySubjectId ?: -1
+ ).also {
+ it.lessonNumber = lessonNumber
+ }
+
+ data.attendanceList.add(attendanceObject)
+ if (baseType != Attendance.TYPE_PRESENT) {
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_ATTENDANCE,
+ id,
+ profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
+ profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
+ ))
+ }
+ }
+
+ if (profile.empty && requestSemester == 1 && data.currentSemester == 2) {
+ requestSemester = null
+ getAttendances()
+ } else {
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE)
+ }
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebEvents.kt
new file mode 100644
index 00000000..35c68478
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebEvents.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-1-1
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_EVENT_ID
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_EVENTS
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.get
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class EdudziennikWebEvents(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ const val TAG = "EdudziennikWebEvents"
+ }
+
+ init { data.profile?.also { profile ->
+ webGet(TAG, data.studentAndClassesEndpoint + "KlassEvent", xhr = true) { text ->
+ val doc = Jsoup.parseBodyFragment("")
+
+ doc.getElementsByTag("tr").forEach { eventElement ->
+ val date = Date.fromY_m_d(eventElement.child(1).text())
+
+ val titleElement = eventElement.child(2).child(0)
+ val title = titleElement.text().trim()
+
+ val id = EDUDZIENNIK_EVENT_ID.find(titleElement.attr("href"))?.get(1)?.crc32()
+ ?: return@forEach
+
+ val eventObject = Event(
+ profileId = profileId,
+ id = id,
+ date = date,
+ time = null,
+ topic = title,
+ color = null,
+ type = Event.TYPE_CLASS_EVENT,
+ teacherId = -1,
+ subjectId = -1,
+ teamId = data.teamClass?.id ?: -1
+ )
+
+ data.eventList.add(eventObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_EVENT,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_CLASS_EVENT))
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_EVENTS, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_EVENTS)
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_EVENTS) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebExams.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebExams.kt
new file mode 100644
index 00000000..c700100c
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebExams.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-24
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_EVENT_TYPE_ID
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_EXAM_ID
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECT_ID
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_EXAMS
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.get
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class EdudziennikWebExams(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ const val TAG = "EdudziennikWebExams"
+ }
+
+ init { profile?.also { profile ->
+ webGet(TAG, data.studentAndClassEndpoint + "Evaluations", xhr = true) { text ->
+ val doc = Jsoup.parseBodyFragment("")
+
+ doc.select("tr").forEach { examElement ->
+ val id = EDUDZIENNIK_EXAM_ID.find(examElement.child(0).child(0).attr("href"))
+ ?.get(1)?.crc32() ?: return@forEach
+ val topic = examElement.child(0).text().trim()
+
+ val subjectElement = examElement.child(1).child(0)
+ val subjectId = EDUDZIENNIK_SUBJECT_ID.find(subjectElement.attr("href"))?.get(1)
+ ?: return@forEach
+ val subjectName = subjectElement.text().trim()
+ val subject = data.getSubject(subjectId.crc32(), subjectName)
+
+ val dateString = examElement.child(2).text().trim()
+ if (dateString.isBlank()) return@forEach
+ val date = Date.fromY_m_d(dateString)
+
+ val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
+ val startTime = lessons.firstOrNull { it.displaySubjectId == subject.id }?.displayStartTime
+
+ val eventTypeElement = examElement.child(3).child(0)
+ val eventTypeId = EDUDZIENNIK_EVENT_TYPE_ID.find(eventTypeElement.attr("href"))?.get(1)
+ ?: return@forEach
+ val eventTypeName = eventTypeElement.text()
+ val eventType = data.getEventType(eventTypeId, eventTypeName)
+
+ val eventObject = Event(
+ profileId = profileId,
+ id = id,
+ date = date,
+ time = startTime,
+ topic = topic,
+ color = null,
+ type = eventType.id,
+ teacherId = -1,
+ subjectId = subject.id,
+ teamId = data.teamClass?.id ?: -1
+ )
+
+ data.eventList.add(eventObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_EVENT,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Events.futureExceptTypes(listOf(
+ Event.TYPE_HOMEWORK,
+ Event.TYPE_CLASS_EVENT
+ )))
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_EXAMS)
+ }
+ }}
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGetAnnouncement.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGetAnnouncement.kt
new file mode 100644
index 00000000..5d915e64
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGetAnnouncement.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-26
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent
+import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
+import pl.szczodrzynski.edziennik.get
+
+class EdudziennikWebGetAnnouncement(override val data: DataEdudziennik,
+ private val announcement: AnnouncementFull,
+ val onSuccess: () -> Unit
+) : EdudziennikWeb(data, null) {
+ companion object {
+ const val TAG = "EdudziennikWebGetAnnouncement"
+ }
+
+ init {
+ webGet(TAG, "Announcement/${announcement.idString}") { text ->
+ val description = Regexes.EDUDZIENNIK_ANNOUNCEMENT_DESCRIPTION.find(text)?.get(1)?.trim() ?: ""
+
+ announcement.text = description
+
+ EventBus.getDefault().postSticky(AnnouncementGetEvent(announcement))
+
+ data.announcementList.add(announcement)
+ onSuccess()
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGetHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGetHomework.kt
new file mode 100644
index 00000000..84171699
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGetHomework.kt
@@ -0,0 +1,45 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import android.text.Html
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.isNotNullNorEmpty
+
+class EdudziennikWebGetHomework(
+ override val data: DataEdudziennik,
+ val event: EventFull,
+ val onSuccess: () -> Unit
+) : EdudziennikWeb(data, null) {
+ companion object {
+ const val TAG = "EdudziennikWebGetHomework"
+ }
+
+ init {
+ if (event.attachmentNames.isNotNullNorEmpty()) {
+ val id = event.attachmentNames!![0]
+
+ webGet(TAG, "Homework/$id") { text ->
+ val description = Regexes.EDUDZIENNIK_HOMEWORK_DESCRIPTION.find(text)?.get(1)?.trim()
+
+ if (description != null) event.topic = Html.fromHtml(description).toString()
+
+ event.homeworkBody = ""
+ event.attachmentNames = null
+
+ data.eventList += event
+ data.eventListReplace = true
+
+ EventBus.getDefault().postSticky(EventGetEvent(event))
+ onSuccess()
+ }
+ } else {
+ EventBus.getDefault().postSticky(EventGetEvent(event))
+ onSuccess()
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGrades.kt
new file mode 100644
index 00000000..6a247290
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebGrades.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-25
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import android.graphics.Color
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.colorFromCssName
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_GRADES
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.Grade.Companion.TYPE_POINT_SUM
+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.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.utils.Utils
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class EdudziennikWebGrades(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "EdudziennikWebGrades"
+ }
+
+ private var requestSemester: Int? = null
+
+ init {
+ if (profile?.empty == true && data.currentSemester == 2) requestSemester = 1
+ getGrades()
+ }
+
+ private fun getGrades() { data.profile?.also { profile ->
+ webGet(TAG, data.studentEndpoint + "start", semester = requestSemester) { text ->
+ val semester = requestSemester ?: data.currentSemester
+
+ val doc = Jsoup.parse(text)
+ val subjects = doc.select("#student_grades tbody").firstOrNull()?.children()
+
+ subjects?.forEach { subjectElement ->
+ if (subjectElement.id().isBlank()) return@forEach
+
+ val subjectId = subjectElement.id().trim()
+ val subjectName = subjectElement.child(0).text().trim()
+ val subject = data.getSubject(subjectId.crc32(), subjectName)
+
+ val gradeType = when {
+ subjectElement.select("#sum").text().isNotBlank() -> TYPE_POINT_SUM
+ else -> TYPE_NORMAL
+ }
+
+ val gradeCountToAverage = subjectElement.select("#avg").text().isNotBlank()
+
+ val grades = subjectElement.select(".grade[data-edited]")
+ val gradesInfo = subjectElement.select(".grade-tip")
+
+ val gradeValues = if (grades.isNotEmpty()) {
+ subjects.select(".avg-$subjectId .grade-tip > p").first()
+ .text().split('+').map {
+ val split = it.split('*')
+ val value = split[1].trim().toFloatOrNull()
+ val weight = value?.let { split[0].trim().toFloatOrNull() } ?: 0f
+
+ Pair(value ?: 0f, weight)
+ }
+ } else emptyList()
+
+ grades.forEachIndexed { index, gradeElement ->
+ val id = Regexes.EDUDZIENNIK_GRADE_ID.find(gradeElement.attr("href"))?.get(1)?.crc32()
+ ?: return@forEachIndexed
+ val (value, weight) = gradeValues[index]
+ val name = gradeElement.text().trim().let {
+ if (it.contains(',') || it.contains('.')) {
+ val replaced = it.replace(',', '.')
+ val float = replaced.toFloatOrNull()
+
+ if (float != null && float % 1 == 0f) float.toInt().toString()
+ else it
+ } else it
+ }
+
+ val info = gradesInfo[index]
+ val fullName = info.child(0).text().trim()
+ val columnName = info.child(4).text().trim()
+ val comment = info.ownText()
+
+ val description = columnName + if (comment.isNotBlank()) " - $comment" else null
+
+ val teacherName = info.child(1).text()
+ val teacher = data.getTeacherByLastFirst(teacherName)
+
+ val addedDate = info.child(2).text().split(' ').let {
+ val day = it[0].toInt()
+ val month = Utils.monthFromName(it[1])
+ val year = it[2].toInt()
+
+ Date(year, month, day).inMillis
+ }
+
+ val color = Regexes.STYLE_CSS_COLOR.find(gradeElement.attr("style"))?.get(1)?.let {
+ if (it.startsWith('#')) Color.parseColor(it)
+ else colorFromCssName(it)
+ } ?: -1
+
+ val gradeObject = Grade(
+ profileId = profileId,
+ id = id,
+ name = name,
+ type = gradeType,
+ value = value,
+ weight = if (gradeCountToAverage) weight else 0f,
+ color = color,
+ category = fullName,
+ description = description,
+ comment = null,
+ semester = semester,
+ teacherId = teacher.id,
+ subjectId = subject.id,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ val proposed = subjectElement.select(".proposal").firstOrNull()?.text()?.trim()
+
+ if (proposed != null && proposed.isNotBlank()) {
+ val proposedGradeObject = Grade(
+ profileId = profileId,
+ id = (-1 * subject.id) - 1,
+ name = proposed,
+ type = when (semester) {
+ 1 -> TYPE_SEMESTER1_PROPOSED
+ else -> TYPE_SEMESTER2_PROPOSED
+ },
+ value = proposed.toFloatOrNull() ?: 0f,
+ weight = 0f,
+ color = -1,
+ category = null,
+ description = null,
+ comment = null,
+ semester = semester,
+ teacherId = -1,
+ subjectId = subject.id
+ )
+
+ data.gradeList.add(proposedGradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ proposedGradeObject.id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ val final = subjectElement.select(".final").firstOrNull()?.text()?.trim()
+
+ if (final != null && final.isNotBlank()) {
+ val finalGradeObject = Grade(
+ profileId = profileId,
+ id = (-1 * subject.id) - 2,
+ name = final,
+ type = when (semester) {
+ 1 -> TYPE_SEMESTER1_FINAL
+ else -> TYPE_SEMESTER2_FINAL
+ },
+ value = final.toFloatOrNull() ?: 0f,
+ weight = 0f,
+ color = -1,
+ category = null,
+ description = null,
+ comment = null,
+ semester = semester,
+ teacherId = -1,
+ subjectId = subject.id
+ )
+
+ data.gradeList.add(finalGradeObject)
+ data.metadataList.add(Metadata(
+ data.profileId,
+ Metadata.TYPE_GRADE,
+ finalGradeObject.id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+ }
+
+ if (!subjects.isNullOrEmpty()) {
+ data.toRemove.addAll(listOf(
+ TYPE_NORMAL,
+ TYPE_POINT_SUM,
+ TYPE_SEMESTER1_PROPOSED,
+ TYPE_SEMESTER2_PROPOSED,
+ TYPE_SEMESTER1_FINAL,
+ TYPE_SEMESTER2_FINAL
+ ).map {
+ DataRemoveModel.Grades.semesterWithType(semester, it)
+ })
+ }
+
+ if (profile.empty && requestSemester == 1 && data.currentSemester == 2) {
+ requestSemester = null
+ getGrades()
+ } else {
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_GRADES)
+ }
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_GRADES) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebHomework.kt
new file mode 100644
index 00000000..b843abe9
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebHomework.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_HOMEWORK_ID
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECT_ID
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.get
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class EdudziennikWebHomework(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ const val TAG = "EdudziennikWebHomework"
+ }
+
+ init { data.profile?.also { profile ->
+ webGet(TAG, data.courseStudentEndpoint + "Homework", xhr = true) { text ->
+ val doc = Jsoup.parseBodyFragment("")
+
+ if (doc.getElementsByClass("message").text().trim() != "Brak prac domowych") {
+ doc.getElementsByTag("tr").forEach { homeworkElement ->
+ val dateElement = homeworkElement.getElementsByClass("date").first().child(0)
+ val idStr = EDUDZIENNIK_HOMEWORK_ID.find(dateElement.attr("href"))?.get(1) ?: return@forEach
+ val id = idStr.crc32()
+ val date = Date.fromY_m_d(dateElement.text())
+
+ val subjectElement = homeworkElement.child(1).child(0)
+ val subjectId = EDUDZIENNIK_SUBJECT_ID.find(subjectElement.attr("href"))?.get(1)
+ ?: return@forEach
+ val subjectName = subjectElement.text()
+ val subject = data.getSubject(subjectId.crc32(), subjectName)
+
+ val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
+ val startTime = lessons.firstOrNull { it.subjectId == subject.id }?.displayStartTime
+
+ val teacherName = homeworkElement.child(2).text()
+ val teacher = data.getTeacherByFirstLast(teacherName)
+
+ val topic = homeworkElement.child(4).text()?.trim()
+
+ val eventObject = Event(
+ profileId = profileId,
+ id = id,
+ date = date,
+ time = startTime,
+ topic = topic ?: "",
+ color = null,
+ type = Event.TYPE_HOMEWORK,
+ teacherId = teacher.id,
+ subjectId = subject.id,
+ teamId = data.teamClass?.id ?: -1
+ )
+
+ eventObject.attachmentNames = mutableListOf(idStr)
+
+ data.eventList.add(eventObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_HOMEWORK,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+ }
+
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK)
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebLuckyNumber.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebLuckyNumber.kt
new file mode 100644
index 00000000..db8164c8
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebLuckyNumber.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-23
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.utils.models.Date
+
+class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "EdudziennikWebLuckyNumber"
+ }
+
+ init { data.profile?.also { profile ->
+ webGet(TAG, data.schoolEndpoint + "Lucky", xhr = true) { text ->
+ text.toIntOrNull()?.also { luckyNumber ->
+ val luckyNumberObject = LuckyNumber(
+ profileId = profileId,
+ date = Date.getToday(),
+ number = luckyNumber
+ )
+
+ data.luckyNumberList.add(luckyNumberObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_LUCKY_NUMBER,
+ luckyNumberObject.date.value.toLong(),
+ true,
+ profile.empty
+ ))
+ }
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER)
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebNotes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebNotes.kt
new file mode 100644
index 00000000..35a78168
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebNotes.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-1-1
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_NOTE_ID
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_NOTES
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class EdudziennikWebNotes(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ const val TAG = "EdudziennikWebNotes"
+ }
+
+ init { data.profile?.also { profile ->
+ webGet(TAG, data.classStudentEndpoint + "RegistryNotesStudent", xhr = true) { text ->
+ val doc = Jsoup.parseBodyFragment("")
+
+ doc.getElementsByTag("tr").forEach { noteElement ->
+ val dateElement = noteElement.getElementsByClass("date").first().child(0)
+ val addedDate = Date.fromY_m_d(dateElement.text()).inMillis
+
+ val id = EDUDZIENNIK_NOTE_ID.find(dateElement.attr("href"))?.get(0)?.crc32()
+ ?: return@forEach
+
+ val teacherName = noteElement.child(1).text()
+ val teacher = data.getTeacherByFirstLast(teacherName)
+
+ val description = noteElement.child(3).text()
+
+ val noticeObject = Notice(
+ profileId = profileId,
+ id = id,
+ type = Notice.TYPE_NEUTRAL,
+ semester = profile.currentSemester,
+ text = description,
+ category = null,
+ points = null,
+ teacherId = teacher.id,
+ addedDate = addedDate
+ )
+
+ data.noticeList.add(noticeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_NOTICE,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_NOTES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_NOTES)
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_NOTES) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt
new file mode 100644
index 00000000..3fdd6e0e
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-23
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import pl.szczodrzynski.edziennik.MONTH
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.ERROR_EDUDZIENNIK_WEB_TEAM_MISSING
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECTS_START
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.data.db.entity.Team
+import pl.szczodrzynski.edziennik.firstLettersName
+import pl.szczodrzynski.edziennik.get
+
+class EdudziennikWebStart(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "EdudziennikWebStart"
+ }
+
+ init {
+ webGet(TAG, data.studentEndpoint + "start") { text ->
+ getSchoolAndTeam(text)
+ getSubjects(text)
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_START, MONTH)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_START)
+ }
+ }
+
+ private fun getSchoolAndTeam(text: String) {
+ val schoolId = Regexes.EDUDZIENNIK_SCHOOL_DETAIL_ID.find(text)?.get(1)?.trim()
+ val schoolLongName = Regexes.EDUDZIENNIK_SCHOOL_DETAIL_NAME.find(text)?.get(1)?.trim()
+ data.schoolId = schoolId
+
+ val classId = Regexes.EDUDZIENNIK_CLASS_DETAIL_ID.find(text)?.get(1)?.trim()
+ val className = Regexes.EDUDZIENNIK_CLASS_DETAIL_NAME.find(text)?.get(1)?.trim()
+ data.classId = classId
+
+ if (classId == null || className == null || schoolId == null || schoolLongName == null) {
+ data.error(ApiError(TAG, ERROR_EDUDZIENNIK_WEB_TEAM_MISSING)
+ .withApiResponse(text))
+ return
+ }
+
+ val schoolName = schoolId.crc32().toString() + schoolLongName.firstLettersName + "_edu"
+ data.schoolName = schoolName
+
+ val teamId = classId.crc32()
+ val teamCode = "$schoolName:$className"
+
+ val teamObject = Team(
+ data.profileId,
+ teamId,
+ className,
+ Team.TYPE_CLASS,
+ teamCode,
+ -1
+ )
+
+ data.teamClass = teamObject
+ data.teamList.put(teamObject.id, teamObject)
+ }
+
+ private fun getSubjects(text: String) {
+ EDUDZIENNIK_SUBJECTS_START.findAll(text).forEach {
+ val id = it[1].trim()
+ val name = it[2].trim()
+ data.getSubject(id.crc32(), name)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTeachers.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTeachers.kt
new file mode 100644
index 00000000..d2f3ba15
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTeachers.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-25
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import pl.szczodrzynski.edziennik.MONTH
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_TEACHERS
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_TEACHERS
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.get
+
+class EdudziennikWebTeachers(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "EdudziennikWebTeachers"
+ }
+
+ init {
+ webGet(TAG, data.studentAndTeacherClassEndpoint + "grid") { text ->
+ EDUDZIENNIK_TEACHERS.findAll(text).forEach {
+ val lastName = it[1].trim()
+ val firstName = it[2].trim()
+ data.getTeacher(firstName, lastName)
+ }
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_TEACHERS, MONTH)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_TEACHERS)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTimetable.kt
new file mode 100644
index 00000000..33feb75e
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTimetable.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-23
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECT_ID
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_TEACHER_ID
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+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.get
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.singleOrNull
+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 EdudziennikWebTimetable(override val data: DataEdudziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : EdudziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "EdudziennikWebTimetable"
+ }
+
+ 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)
+
+ webGet(TAG, data.timetableEndpoint + "print?date=$getDate") { text ->
+ val doc = Jsoup.parse(text)
+
+ val dataDays = mutableListOf()
+ val dataStart = weekStart.clone()
+ while (dataStart <= weekEnd) {
+ dataDays += dataStart.value
+ dataStart.stepForward(0, 0, 1)
+ }
+
+ val table = doc.select("#Schedule tbody").first()
+
+ if (!table.text().contains("Brak planu lekcji.")) {
+ table.children().forEach { row ->
+ val rowElements = row.children()
+
+ val lessonNumber = rowElements[0].text().toInt()
+
+ val times = rowElements[1].text().split('-')
+ val startTime = Time.fromH_m(times[0].trim())
+ val endTime = Time.fromH_m(times[1].trim())
+
+ data.lessonRanges.singleOrNull {
+ it.lessonNumber == lessonNumber && it.startTime == startTime && it.endTime == endTime
+ } ?: run {
+ data.lessonRanges.put(lessonNumber, LessonRange(profileId, lessonNumber, startTime, endTime))
+ }
+
+ rowElements.subList(2, rowElements.size).forEachIndexed { index, lesson ->
+ val course = lesson.select(".course").firstOrNull() ?: return@forEachIndexed
+ val info = course.select("span > span")
+
+ if (info.isEmpty()) return@forEachIndexed
+
+ val type = when (course.hasClass("substitute")) {
+ true -> Lesson.TYPE_CHANGE
+ else -> Lesson.TYPE_NORMAL
+ }
+
+ /* Getting subject */
+
+ val subjectElement = info[0].child(0)
+ val subjectId = EDUDZIENNIK_SUBJECT_ID.find(subjectElement.attr("href"))?.get(1)
+ ?: return@forEachIndexed
+ val subjectName = subjectElement.text().trim()
+ val subject = data.getSubject(subjectId.crc32(), subjectName)
+
+ /* Getting teacher */
+
+ val teacherId = if (info.size >= 2) {
+ val teacherElement = info[1].child(0)
+ val teacherLongId = EDUDZIENNIK_TEACHER_ID.find(teacherElement.attr("href"))?.get(1)
+ val teacherName = teacherElement.text().trim()
+ data.getTeacherByLastFirst(teacherName, teacherLongId).id
+ } else null
+
+ val lessonObject = Lesson(profileId, -1).also {
+ it.type = type
+ it.date = weekStart.clone().stepForward(0, 0, index)
+ it.lessonNumber = lessonNumber
+ it.startTime = startTime
+ it.endTime = endTime
+ it.subjectId = subject.id
+ it.teacherId = teacherId
+ it.teamId = data.teamClass?.id
+
+ it.id = it.buildId()
+ }
+
+ data.lessonList.add(lessonObject)
+ dataDays.remove(lessonObject.date!!.value)
+
+ if (type != Lesson.TYPE_NORMAL) {
+ val seen = profile.empty || lessonObject.date!! < Date.getToday()
+
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_LESSON_CHANGE,
+ lessonObject.id,
+ seen,
+ seen
+ ))
+ }
+ }
+ }
+ }
+
+ for (day in dataDays) {
+ val lessonDate = Date.fromValue(day)
+ data.lessonList += Lesson(profileId, lessonDate.value.toLong()).apply {
+ type = Lesson.TYPE_NO_LESSONS
+ date = lessonDate
+ }
+ }
+
+ d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
+
+ data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE)
+ }
+ } ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt
new file mode 100644
index 00000000..a93632b1
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/firstlogin/EdudziennikFirstLogin.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ACCOUNT_NAME_START
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_STUDENTS_START
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLoginWeb
+import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.fixName
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.getShortName
+import pl.szczodrzynski.edziennik.set
+
+class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) {
+ companion object {
+ private const val TAG = "EdudziennikFirstLogin"
+ }
+
+ private val web = EdudziennikWeb(data, null)
+ private val profileList = mutableListOf()
+
+ init {
+ val loginStoreId = data.loginStore.id
+ val loginStoreType = LOGIN_TYPE_EDUDZIENNIK
+ var firstProfileId = loginStoreId
+
+ EdudziennikLoginWeb(data) {
+ web.webGet(TAG, "") { text ->
+ val accountNameLong = EDUDZIENNIK_ACCOUNT_NAME_START.find(text)?.get(1)?.fixName()
+
+ EDUDZIENNIK_STUDENTS_START.findAll(text).forEach {
+ val studentId = it[1]
+ val studentNameLong = it[2].fixName()
+
+ if (studentId.isBlank() || studentNameLong.isBlank()) return@forEach
+
+ val studentNameShort = studentNameLong.getShortName()
+ val accountName = if (accountNameLong == studentNameLong) null else accountNameLong
+
+ val profile = Profile(
+ firstProfileId++,
+ loginStoreId,
+ loginStoreType,
+ studentNameLong,
+ data.loginEmail,
+ studentNameLong,
+ studentNameShort,
+ accountName
+ ).apply {
+ studentData["studentId"] = studentId
+ }
+ 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/edudziennik/login/EdudziennikLogin.kt
similarity index 58%
rename from app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLogin.kt
rename to app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLogin.kt
index e1cef5c1..1cb2fd07 100644
--- 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/edudziennik/login/EdudziennikLogin.kt
@@ -1,18 +1,17 @@
/*
- * Copyright (c) Kuba Szczodrzyński 2019-10-25.
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
*/
-package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.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.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
import pl.szczodrzynski.edziennik.utils.Utils
-class IdziennikLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
+class EdudziennikLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) {
companion object {
- private const val TAG = "IdziennikLogin"
+ private const val TAG = "EdudziennikLogin"
}
private var cancelled = false
@@ -46,13 +45,9 @@ class IdziennikLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
}
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) }
+ LOGIN_METHOD_EDUDZIENNIK_WEB -> {
+ data.startProgress(R.string.edziennik_progress_login_edudziennik_web)
+ EdudziennikLoginWeb(data) { onSuccess(loginMethodId) }
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLoginWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLoginWeb.kt
new file mode 100644
index 00000000..6b1615a2
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLoginWeb.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-22
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login
+
+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.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.getUnixDate
+import pl.szczodrzynski.edziennik.isNotNullNorEmpty
+import pl.szczodrzynski.edziennik.utils.Utils.d
+
+class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit) {
+ companion object {
+ private const val TAG = "EdudziennikLoginWeb"
+ }
+
+ init { run {
+ if (data.isWebLoginValid()) {
+ onSuccess()
+ }
+ else {
+ data.app.cookieJar.clear("dziennikel.appspot.com")
+ if (data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
+ loginWithCredentials()
+ }
+ else {
+ data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
+ }
+ }
+ }}
+
+ private fun loginWithCredentials() {
+ d(TAG, "Request: Edudziennik/Login/Web - https://dziennikel.appspot.com/login/?next=/")
+
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response?) {
+ if (text == null || response == null) {
+ data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return
+ }
+
+ val url = response.raw().request().url().toString()
+
+ if (!url.contains("Student")) {
+ when {
+ text.contains("Wprowadzono nieprawidłową nazwę użytkownika lub hasło.") -> ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN
+ else -> ERROR_LOGIN_EDUDZIENNIK_WEB_OTHER
+ }.let { errorCode ->
+ data.error(ApiError(TAG, errorCode)
+ .withApiResponse(text)
+ .withResponse(response))
+ return
+ }
+ }
+
+ val cookies = data.app.cookieJar.getAll("dziennikel.appspot.com")
+ val sessionId = cookies["sessionid"]
+
+ if (sessionId == null) {
+ data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID)
+ .withResponse(response)
+ .withApiResponse(text))
+ return
+ }
+
+ data.webSessionId = sessionId
+ data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45 min */
+ onSuccess()
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url("https://dziennikel.appspot.com/login/?next=/")
+ .userAgent(EDUDZIENNIK_USER_AGENT)
+ .contentType("application/x-www-form-urlencoded")
+ .addParameter("email", data.loginEmail)
+ .addParameter("password", data.loginPassword)
+ .addParameter("auth_method", "password")
+ .addParameter("next", "/")
+ .post()
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/helper/DownloadAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/helper/DownloadAttachment.kt
new file mode 100644
index 00000000..a968818a
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/helper/DownloadAttachment.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-14
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.helper
+
+import im.wangchao.mhttp.Request
+import im.wangchao.mhttp.Response
+import im.wangchao.mhttp.callback.FileCallbackHandler
+import pl.szczodrzynski.edziennik.data.api.ERROR_FILE_DOWNLOAD
+import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
+import pl.szczodrzynski.edziennik.data.api.SYSTEM_USER_AGENT
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.utils.Utils
+import java.io.File
+
+class DownloadAttachment(
+ fileUrl: String,
+ val onSuccess: (file: File) -> Unit,
+ val onProgress: (written: Long, total: Long) -> Unit,
+ val onError: (apiError: ApiError) -> Unit
+) {
+ companion object {
+ private const val TAG = "DownloadAttachment"
+ }
+
+ init {
+ val targetFile = Utils.getStorageDir()
+
+ val callback = object : FileCallbackHandler(targetFile) {
+ override fun onSuccess(file: File?, response: Response?) {
+ if (file == null) {
+ onError(ApiError(TAG, ERROR_FILE_DOWNLOAD)
+ .withResponse(response))
+ return
+ }
+
+ try {
+ onSuccess(file)
+ } catch (e: Exception) {
+ onError(ApiError(TAG, ERROR_FILE_DOWNLOAD)
+ .withResponse(response)
+ .withThrowable(e))
+ }
+ }
+
+ override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
+ try {
+ this@DownloadAttachment.onProgress(bytesWritten, bytesTotal)
+ } catch (e: Exception) {
+ onError(ApiError(TAG, ERROR_FILE_DOWNLOAD)
+ .withThrowable(e))
+ }
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url(fileUrl)
+ .userAgent(SYSTEM_USER_AGENT)
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/helper/OneDriveDownloadAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/helper/OneDriveDownloadAttachment.kt
new file mode 100644
index 00000000..25b78527
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/helper/OneDriveDownloadAttachment.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-7.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.helper
+
+import im.wangchao.mhttp.Request
+import im.wangchao.mhttp.Response
+import im.wangchao.mhttp.callback.FileCallbackHandler
+import im.wangchao.mhttp.callback.TextCallbackHandler
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.data.api.ERROR_ONEDRIVE_DOWNLOAD
+import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
+import pl.szczodrzynski.edziennik.data.api.SYSTEM_USER_AGENT
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.utils.Utils
+import java.io.File
+
+class OneDriveDownloadAttachment(
+ app: App,
+ fileUrl: String,
+ val onSuccess: (file: File) -> Unit,
+ val onProgress: (written: Long, total: Long) -> Unit,
+ val onError: (apiError: ApiError) -> Unit
+) {
+ companion object {
+ private const val TAG = "OneDriveDownloadAttachment"
+ }
+
+ init {
+ Request.builder()
+ .url(fileUrl)
+ .userAgent(SYSTEM_USER_AGENT)
+ .withClient(app.httpLazy)
+ .callback(object : TextCallbackHandler() {
+ override fun onSuccess(text: String, response: Response) {
+ val location = response.headers().get("Location")
+ // https://onedrive.live.com/redir?resid=D75496A2EB87531C!706&authkey=!ABjZeh3pHMqj11Q
+ if (location?.contains("onedrive.live.com/redir?resid=") != true) {
+ onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
+ .withApiResponse(text)
+ .withResponse(response))
+ return
+ }
+ val url = location
+ .replace("onedrive.live.com/redir?resid=", "storage.live.com/items/")
+ .replace("?", "&")
+ .replaceFirst("&", "?")
+ downloadFile(url)
+ }
+
+ override fun onFailure(response: Response, throwable: Throwable) {
+ onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ })
+ .build()
+ .enqueue()
+ }
+
+ private fun downloadFile(url: String) {
+ val targetFile = Utils.getStorageDir()
+
+ val callback = object : FileCallbackHandler(targetFile) {
+ override fun onSuccess(file: File?, response: Response?) {
+ if (file == null) {
+ onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
+ .withResponse(response))
+ return
+ }
+
+ try {
+ onSuccess(file)
+ } catch (e: Exception) {
+ onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
+ .withResponse(response)
+ .withThrowable(e))
+ }
+ }
+
+ override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
+ try {
+ this@OneDriveDownloadAttachment.onProgress(bytesWritten, bytesTotal)
+ } catch (e: Exception) {
+ onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
+ .withThrowable(e))
+ }
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url(url)
+ .userAgent(SYSTEM_USER_AGENT)
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
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 c3bd925a..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/DataIdziennik.kt
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2019-10-25.
- */
-
-package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik
-
-import androidx.core.util.set
-import okhttp3.Cookie
-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.modules.login.LoginStore
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
-import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.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.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("ASP.NET_SessionId_iDziennik")
- .value(webSessionId!!)
- .domain("iuczniowie.progman.pl")
- .secure().httpOnly().build(),
- Cookie.Builder()
- .name(".ASPXAUTH")
- .value(webAuth!!)
- .domain("iuczniowie.progman.pl")
- .secure().httpOnly().build()
- ))
- }
- if (isApiLoginValid())
- loginMethods += LOGIN_METHOD_IDZIENNIK_API
- }
-
- 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 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 98010dc8..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/Idziennik.kt
+++ /dev/null
@@ -1,119 +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.CODE_INTERNAL_LIBRUS_ACCOUNT_410
-import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikData
-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.idziennikLoginMethods
-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.api.prepare
-import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
-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
-
- init {
- data = DataIdziennik(app, profile, loginStore).apply {
- callback = wrapCallback(this@Idziennik.callback)
- satisfyLoginMethods()
- }
- }
-
- private fun completed() {
- data.saveData()
- data.notify {
- callback.onCompleted()
- }
- }
-
- /* _______ _ _ _ _ _
- |__ __| | /\ | | (_) | | |
- | | | |__ ___ / \ | | __ _ ___ _ __ _| |_| |__ _ __ ___
- | | | '_ \ / _ \ / /\ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \
- | | | | | | __/ / ____ \| | (_| | (_) | | | | |_| | | | | | | | |
- |_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
- __/ |
- |__*/
- override fun sync(featureIds: List, viewId: Int?, arguments: JsonObject?) {
- data.arguments = arguments
- data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId)
- d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
- d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
- IdziennikLogin(data) {
- IdziennikData(data) {
- completed()
- }
- }
- }
-
- override fun getMessage(message: MessageFull) {
-
- }
-
- override fun markAllAnnouncementsAsRead() {
-
- }
-
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
-
- }
-
- 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) {
- when (apiError.errorCode) {
- in internalErrorList -> {
- // finish immediately if the same error occurs twice during the same sync
- callback.onError(apiError)
- }
- CODE_INTERNAL_LIBRUS_ACCOUNT_410 -> {
- internalErrorList.add(apiError.errorCode)
- loginStore.removeLoginData("refreshToken") // force a clean login
- //loginLibrus()
- }
- 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 05bd260d..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikApi.kt
+++ /dev/null
@@ -1,116 +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) {
- 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) {
- "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_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 7b285db9..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikData.kt
+++ /dev/null
@@ -1,89 +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
- }
- useEndpoint(data.targetEndpointIds.removeAt(0)) {
- data.progress(data.progressStep)
- nextEndpoint(onSuccess)
- }
- }
-
- private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
- Utils.d(TAG, "Using endpoint $endpointId")
- when (endpointId) {
- ENDPOINT_IDZIENNIK_WEB_TIMETABLE -> {
- data.startProgress(R.string.edziennik_progress_endpoint_timetable)
- IdziennikWebTimetable(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_GRADES -> {
- data.startProgress(R.string.edziennik_progress_endpoint_grades)
- IdziennikWebGrades(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES -> {
- data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades)
- IdziennikWebProposedGrades(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_EXAMS -> {
- data.startProgress(R.string.edziennik_progress_endpoint_exams)
- IdziennikWebExams(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_HOMEWORK -> {
- data.startProgress(R.string.edziennik_progress_endpoint_homework)
- IdziennikWebHomework(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_NOTICES -> {
- data.startProgress(R.string.edziennik_progress_endpoint_notices)
- IdziennikWebNotices(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS -> {
- data.startProgress(R.string.edziennik_progress_endpoint_announcements)
- IdziennikWebAnnouncements(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_WEB_ATTENDANCE -> {
- data.startProgress(R.string.edziennik_progress_endpoint_attendance)
- IdziennikWebAttendance(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER -> {
- data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
- IdziennikApiCurrentRegister(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX -> {
- data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
- IdziennikApiMessagesInbox(data, onSuccess)
- }
- ENDPOINT_IDZIENNIK_API_MESSAGES_SENT -> {
- data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
- IdziennikApiMessagesSent(data, onSuccess)
- }
- else -> onSuccess()
- }
- }
-}
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 c7b6820a..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/IdziennikWeb.kt
+++ /dev/null
@@ -1,159 +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.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.models.ApiError
-import pl.szczodrzynski.edziennik.utils.Utils.d
-import java.net.HttpURLConnection.HTTP_INTERNAL_ERROR
-import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
-
-open class IdziennikWeb(open val data: DataIdziennik) {
- 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
- }
-
- 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, 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)
- .get()
- .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 1970c225..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiCurrentRegister.kt
+++ /dev/null
@@ -1,94 +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.modules.luckynumber.LuckyNumber
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.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,
- val onSuccess: () -> Unit) : IdziennikApi(data) {
- companion object {
- private const val TAG = "IdziennikApiCurrentRegister"
- }
-
- init {
- data.profile?.luckyNumber = -1
- data.profile?.luckyNumberDate = null
-
- apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json ->
- if (json !is JsonObject) {
- onSuccess()
- return@apiGet
- }
-
- var nextSync = System.currentTimeMillis() + 14*DAY*1000
-
- val settings = json.getJsonObject("ustawienia")?.apply {
- profile?.dateSemester1Start = getString("poczatekSemestru1")?.let { Date.fromY_m_d(it) }
- profile?.dateSemester2Start = getString("koniecSemestru1")?.let { Date.fromY_m_d(it).stepForward(0, 0, 1) }
- profile?.dateYearEnd = getString("koniecSemestru2")?.let { 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(
- data.profileId,
- Date.getToday(),
- luckyNumber
- )
-
- data.luckyNumberList.add(luckyNumberObject)
- data.metadataList.add(
- Metadata(
- profileId,
- Metadata.TYPE_LUCKY_NUMBER,
- luckyNumberObject.date.value.toLong(),
- data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
- ))
- }
-
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER, syncAt = nextSync)
- onSuccess()
- }
- }
-}
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 5542db6c..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt
+++ /dev/null
@@ -1,94 +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.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.asJsonObjectList
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_DELETED
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-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,
- val onSuccess: () -> Unit) : IdziennikApi(data) {
- companion object {
- private const val TAG = "IdziennikApiMessagesInbox"
- }
-
- init {
- apiGet(TAG, IDZIENNIK_API_MESSAGES_INBOX) { json ->
- if (json !is JsonArray) {
- onSuccess()
- return@apiGet
- }
-
- json.asJsonObjectList()?.forEach { jMessage ->
- val subject = jMessage.getString("tytul")
- if (subject?.contains("(") == true && subject.startsWith("iDziennik - "))
- return@forEach
- if (subject?.startsWith("Uwaga dla ucznia (klasa:") == true)
- 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")
- val rTeacher = data.getTeacher(
- sender.getString("imie") ?: "",
- sender.getString("nazwisko") ?: ""
- )
- rTeacher.loginId = sender.getString("id") + ":" + sender.getString("usr")
-
- val message = Message(
- profileId,
- messageId,
- subject,
- body,
- if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
- rTeacher.id,
- -1
- )
-
- val messageRecipient = MessageRecipient(
- profileId,
- -1 /* me */,
- -1,
- readDate,
- /*messageId*/ messageId
- )
-
- data.messageIgnoreList.add(message)
- data.messageRecipientList.add(messageRecipient)
- data.messageMetadataList.add(Metadata(
- profileId,
- Metadata.TYPE_MESSAGE,
- message.id,
- readDate > 0,
- readDate > 0 || profile?.empty ?: false,
- sentDate
- ))
- }
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX, SYNC_ALWAYS)
- onSuccess()
- }
- }
-}
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 a8850416..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt
+++ /dev/null
@@ -1,85 +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.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.asJsonObjectList
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.utils.Utils.crc32
-import pl.szczodrzynski.edziennik.utils.models.Date
-
-class IdziennikApiMessagesSent(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikApi(data) {
- companion object {
- private const val TAG = "IdziennikApiMessagesSent"
- }
-
- init {
- apiGet(TAG, IDZIENNIK_API_MESSAGES_SENT) { json ->
- if (json !is JsonArray) {
- onSuccess()
- 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,
- messageId,
- subject,
- body,
- TYPE_SENT,
- -1,
- -1
- )
-
- 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.messageIgnoreList.add(message)
- data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
- }
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)
- onSuccess()
- }
- }
-}
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 20844220..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAnnouncements.kt
+++ /dev/null
@@ -1,74 +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.modules.announcements.Announcement
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.getJsonObject
-import pl.szczodrzynski.edziennik.utils.models.Date
-
-class IdziennikWebAnnouncements(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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.get("Id").asLong
-
- val rTeacher = data.getTeacherByFirstLast(jAnnouncement.get("Autor").asString)
- val addedDate = java.lang.Long.parseLong(jAnnouncement.get("DataDodania").asString.replace("[^\\d]".toRegex(), ""))
- val startDate = Date.fromMillis(java.lang.Long.parseLong(jAnnouncement.get("DataWydarzenia").asString.replace("[^\\d]".toRegex(), "")))
-
- val announcementObject = Announcement(
- profileId,
- announcementId,
- jAnnouncement.get("Temat").asString,
- jAnnouncement.get("Tresc").asString,
- startDate,
- null,
- rTeacher.id
- )
- data.announcementList.add(announcementObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_ANNOUNCEMENT,
- announcementObject.id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate
- ))
- }
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS, SYNC_ALWAYS)
- onSuccess()
- }
- }
-}
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 78f8e8b4..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2019-10-28.
- */
-
-package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
-
-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.crc16
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.*
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.getJsonObject
-import pl.szczodrzynski.edziennik.utils.models.Date
-import pl.szczodrzynski.edziennik.utils.models.Time
-
-class IdziennikWebAttendance(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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 attendanceTypeIdziennik = jAttendance.get("TypObecnosci").asInt
- if (attendanceTypeIdziennik == 5 || attendanceTypeIdziennik == 7)
- continue
- val attendanceDate = Date.fromY_m_d(jAttendance.get("Data").asString)
- val attendanceTime = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
- if (attendanceDate.combineWith(attendanceTime) > System.currentTimeMillis())
- continue
-
- val attendanceId = 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 attendanceName = "obecność"
- var attendanceType = Attendance.TYPE_CUSTOM
-
- when (attendanceTypeIdziennik) {
- 1 /* nieobecność usprawiedliwiona */ -> {
- attendanceName = "nieobecność usprawiedliwiona"
- attendanceType = TYPE_ABSENT_EXCUSED
- }
- 2 /* spóźnienie */ -> {
- attendanceName = "spóźnienie"
- attendanceType = TYPE_BELATED
- }
- 3 /* nieobecność nieusprawiedliwiona */ -> {
- attendanceName = "nieobecność nieusprawiedliwiona"
- attendanceType = TYPE_ABSENT
- }
- 4 /* zwolnienie */, 9 /* zwolniony / obecny */ -> {
- attendanceType = TYPE_RELEASED
- if (attendanceTypeIdziennik == 4)
- attendanceName = "zwolnienie"
- if (attendanceTypeIdziennik == 9)
- attendanceName = "zwolnienie / obecność"
- }
- 0 /* obecny */, 8 /* Wycieczka */ -> {
- attendanceType = TYPE_PRESENT
- if (attendanceTypeIdziennik == 8)
- attendanceName = "wycieczka"
- }
- }
-
- val semester = profile?.dateToSemester(attendanceDate) ?: 1
-
- val attendanceObject = Attendance(
- profileId,
- attendanceId,
- rTeacher.id,
- rSubject.id,
- semester,
- attendanceName,
- attendanceDate,
- attendanceTime,
- attendanceType
- )
-
- data.attendanceList.add(attendanceObject)
- if (attendanceObject.type != TYPE_PRESENT) {
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_ATTENDANCE,
- attendanceObject.id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
- ))
- }
- }
-
- 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()
- }
- }
- }
-}
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 bf32188c..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebExams.kt
+++ /dev/null
@@ -1,123 +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.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.utils.models.Date
-
-class IdziennikWebExams(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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") ?: ""
-
- val lessonList = data.db.timetableDao().getForDateNow(profileId, examDate)
- val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
-
- val eventType = when (exam.getString("rodzaj")) {
- "sprawdzian/praca klasowa" -> Event.TYPE_EXAM
- else -> Event.TYPE_SHORT_QUIZ
- }
-
- val eventObject = Event(
- profileId,
- id,
- examDate,
- startTime,
- topic,
- -1,
- eventType,
- false,
- teacherId,
- subjectId,
- data.teamClass?.id ?: -1
- )
-
- data.eventList.add(eventObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_EVENT,
- eventObject.id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
- ))
- }
-
- 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()
- }
- }
- }
-}
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 438d334e..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGrades.kt
+++ /dev/null
@@ -1,155 +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.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.utils.models.Date
-
-class IdziennikWebGrades(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- companion object {
- private const val TAG = "IdziennikWebGrades"
- }
-
- init {
- 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 gradeObject = Grade(
- profileId,
- id,
- category,
- colorInt,
- "",
- name,
- value,
- weight,
- semester,
- teacher.id,
- subject.id)
-
- 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 historyObject = Grade(
- profileId,
- gradeObject.id * -1,
- historyItem.get("Kategoria").asString,
- Color.parseColor("#" + historyItem.get("Kolor").asString),
- historyItem.get("Uzasadnienie").asString,
- historyItem.get("Ocena").asString,
- value,
- if (value > 0f && countToTheAverage) weight * -1f else 0f,
- historyItem.get("Semestr").asInt,
- teacher.id,
- subject.id)
- historyObject.parentId = gradeObject.id
-
- val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
-
- data.gradeList.add(historyObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_GRADE,
- historyObject.id,
- true,
- true,
- addedDate
- ))
- }
- // 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 = name
- gradeObject.weight = 0f
- }
- 2 -> {
- gradeObject.type = Grade.TYPE_YEAR_FINAL
- gradeObject.name = name
- gradeObject.weight = 0f
- }
- }
-
- val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
-
- data.gradeList.add(gradeObject)
- data.metadataList.add(
- Metadata(
- profileId,
- Metadata.TYPE_GRADE,
- id,
- data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- addedDate
- ))
- }
- }
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
- onSuccess()
- }
- }
-}
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 7cfc5b91..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebHomework.kt
+++ /dev/null
@@ -1,98 +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.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.utils.models.Date
-
-class IdziennikWebHomework(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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 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().getForDateNow(profileId, eventDate)
- val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime
- val topic = homework.getString("tytul") ?: ""
-
- val seen = when (profile?.empty) {
- true -> true
- else -> eventDate < Date.getToday()
- }
-
-
- val eventObject = Event(
- profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- Event.TYPE_HOMEWORK,
- false,
- teacherId,
- subjectId,
- data.teamClass?.id ?: -1
- )
-
- data.eventList.add(eventObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_HOMEWORK,
- eventObject.id,
- seen,
- seen,
- System.currentTimeMillis()
- ))
- }
-
- data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
- onSuccess()
- }
- }
-}
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 cfd0d5f6..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebNotices.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2019-10-28.
- */
-
-package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
-
-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.crc16
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice
-import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.*
-import pl.szczodrzynski.edziennik.getJsonObject
-import pl.szczodrzynski.edziennik.utils.models.Date
-
-class IdziennikWebNotices(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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,
- noticeId,
- jNotice.get("Tresc").asString,
- jNotice.get("Semestr").asInt,
- nType,
- rTeacher.id)
- data.noticeList.add(noticeObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_NOTICE,
- noticeObject.id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate.inMillis
- ))
- }
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_NOTICES, SYNC_ALWAYS)
- onSuccess()
- }
- }
-}
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 701620de..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebProposedGrades.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) Kuba Szczodrzyński 2019-10-28.
- */
-
-package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
-
-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.asJsonObjectList
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.getJsonArray
-import pl.szczodrzynski.edziennik.getJsonObject
-import pl.szczodrzynski.edziennik.getString
-import pl.szczodrzynski.edziennik.utils.Utils.getWordGradeValue
-
-class IdziennikWebProposedGrades(override val data: DataIdziennik,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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
- }
-
- 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 = getWordGradeValue(semester1Proposed)
- val semester1Id = subjectObject.id * (-100) - 1
-
- val semester2Proposed = subject.getString("OcenaSem2") ?: ""
- val semester2Value = getWordGradeValue(semester2Proposed)
- val semester2Id = subjectObject.id * (-100) - 2
-
- if (semester1Proposed != "") {
- val gradeObject = Grade(
- profileId,
- semester1Id,
- "",
- -1,
- "",
- semester1Value.toString(),
- semester1Value.toFloat(),
- 0f,
- 1,
- -1,
- subjectObject.id
- ).apply {
- type = TYPE_SEMESTER1_PROPOSED
- }
-
- data.gradeList.add(gradeObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_GRADE,
- gradeObject.id,
- profile.empty,
- profile.empty,
- System.currentTimeMillis()
- ))
- }
-
- if (semester2Proposed != "") {
- val gradeObject = Grade(
- profileId,
- semester2Id,
- "",
- -1,
- "",
- semester2Value.toString(),
- semester2Value.toFloat(),
- 0f,
- 2,
- -1,
- subjectObject.id
- ).apply {
- type = TYPE_YEAR_PROPOSED
- }
-
- data.gradeList.add(gradeObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_GRADE,
- gradeObject.id,
- profile.empty,
- profile.empty,
- System.currentTimeMillis()
- ))
- }
- }
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS)
- 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 d85e5692..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt
+++ /dev/null
@@ -1,192 +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.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
-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,
- val onSuccess: () -> Unit) : IdziennikWeb(data) {
- 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()?.forEach { range ->
- val lessonRange = LessonRange(
- profileId,
- range.getInt("LiczbaP") ?: return@forEach,
- range.getString("Poczatek")?.let { Time.fromH_m(it) } ?: return@forEach,
- range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEach
- )
- 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,
- System.currentTimeMillis()
- ))
- }
- }
-
- 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.lessonNewList.addAll(lessons)
- data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
-
- data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
- onSuccess()
- }
- }}
-}
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 6ef9950f..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/firstlogin/IdziennikFirstLogin.kt
+++ /dev/null
@@ -1,80 +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.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.modules.profiles.Profile
-import pl.szczodrzynski.edziennik.fixName
-import pl.szczodrzynski.edziennik.get
-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)
- private val profileList = mutableListOf()
-
- init {
- 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 schoolYearName: String? = null
- val schoolYear = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let {
- schoolYearName = it[2]
- 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 profile = Profile()
- profile.studentNameLong = "$firstName $lastName".fixName()
- profile.studentNameShort = "$firstName ${lastName[0]}.".fixName()
- profile.accountNameLong = accountNameLong
- profile.studentClassName = className
- profile.studentSchoolYear = schoolYearName
- profile.name = profile.studentNameLong
- profile.subname = data.webUsername
- profile.empty = true
- profile.putStudentData("studentId", studentId)
- profile.putStudentData("registerId", registerId)
- profile.putStudentData("schoolYearId", schoolYear)
- profileList.add(profile)
- }
-
- EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
- onSuccess()
- }
- }
- }
-}
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 9f10268e..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginWeb.kt
+++ /dev/null
@@ -1,148 +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 okhttp3.Cookie
-import pl.szczodrzynski.edziennik.HOUR
-import pl.szczodrzynski.edziennik.MINUTE
-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.get
-import pl.szczodrzynski.edziennik.getUnixDate
-import pl.szczodrzynski.edziennik.utils.Utils
-
-class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
- companion object {
- private const val TAG = "IdziennikLoginWeb"
- }
-
- init { run {
- if (data.isWebLoginValid()) {
- data.app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("ASP.NET_SessionId_iDziennik")
- .value(data.webSessionId!!)
- .domain("iuczniowie.progman.pl")
- .secure().httpOnly().build(),
- Cookie.Builder()
- .name(".ASPXAUTH")
- .value(data.webAuth!!)
- .domain("iuczniowie.progman.pl")
- .secure().httpOnly().build()
- ))
- onSuccess()
- }
- else {
- data.app.cookieJar.clearForDomain("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.getForDomain("iuczniowie.progman.pl")
- run {
- data.webSessionId = cookies.singleOrNull { it.name() == "ASP.NET_SessionId_iDziennik" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION
- data.webAuth = cookies.singleOrNull { it.name() == ".ASPXAUTH" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH
- data.apiBearer = cookies.singleOrNull { it.name() == "Bearer" }?.value() ?: 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. */
- 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/librus/DataLibrus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt
index 9ccdf5c6..e77dd50d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/DataLibrus.kt
@@ -4,16 +4,15 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus
-import okhttp3.Cookie
import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_MESSAGES
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_PORTAL
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_SYNERGIA
import pl.szczodrzynski.edziennik.data.api.models.Data
-import pl.szczodrzynski.edziennik.currentTimeUnix
-import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
@@ -31,26 +30,16 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
loginMethods += LOGIN_METHOD_LIBRUS_API
if (isSynergiaLoginValid()) {
loginMethods += LOGIN_METHOD_LIBRUS_SYNERGIA
- app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("DZIENNIKSID")
- .value(synergiaSessionId!!)
- .domain("synergia.librus.pl")
- .secure().httpOnly().build()
- ))
+ app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", synergiaSessionId)
}
if (isMessagesLoginValid()) {
loginMethods += LOGIN_METHOD_LIBRUS_MESSAGES
- app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("DZIENNIKSID")
- .value(messagesSessionId!!)
- .domain("wiadomosci.librus.pl")
- .secure().httpOnly().build()
- ))
+ app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", messagesSessionId)
}
}
+ override fun generateUserCode() = "$schoolName:$apiLogin"
+
fun getColor(id: Int?): Int {
return when (id) {
1 -> 0xFFF0E68C
@@ -131,7 +120,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiLogin: String? = null
var apiLogin: String?
get() { mApiLogin = mApiLogin ?: profile?.getStudentData("accountLogin", null); return mApiLogin }
- set(value) { profile?.putStudentData("accountLogin", value) ?: return; mApiLogin = value }
+ set(value) { profile?.putStudentData("accountLogin", value); mApiLogin = value }
/**
* A Synergia password.
* Used: for login (API Login Method) in Synergia mode.
@@ -140,7 +129,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiPassword: String? = null
var apiPassword: String?
get() { mApiPassword = mApiPassword ?: profile?.getStudentData("accountPassword", null); return mApiPassword }
- set(value) { profile?.putStudentData("accountPassword", value) ?: return; mApiPassword = value }
+ set(value) { profile?.putStudentData("accountPassword", value); mApiPassword = value }
/**
* A JST login Code.
@@ -149,7 +138,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiCode: String? = null
var apiCode: String?
get() { mApiCode = mApiCode ?: loginStore.getLoginData("accountCode", null); return mApiCode }
- set(value) { loginStore.putLoginData("accountCode", value) ?: return; mApiCode = value }
+ set(value) { profile?.putStudentData("accountCode", value); mApiCode = value }
/**
* A JST login PIN.
* Used only during first login in JST mode.
@@ -157,7 +146,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
private var mApiPin: String? = null
var apiPin: String?
get() { mApiPin = mApiPin ?: loginStore.getLoginData("accountPin", null); return mApiPin }
- set(value) { loginStore.putLoginData("accountPin", value) ?: return; mApiPin = value }
+ set(value) { profile?.putStudentData("accountPin", value); mApiPin = value }
/**
* A Synergia API access token.
@@ -187,6 +176,16 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L }
set(value) { mApiTokenExpiryTime = value; profile?.putStudentData("accountTokenTime", value) ?: return; }
+ /**
+ * A push device ID, generated by Librus when registering
+ * a FCM token. I don't really know if this has any use,
+ * but it may be worthy to save that ID.
+ */
+ private var mPushDeviceId: Int? = null
+ var pushDeviceId: Int
+ get() { mPushDeviceId = mPushDeviceId ?: profile?.getStudentData("pushDeviceId", 0); return mPushDeviceId ?: 0 }
+ set(value) { mPushDeviceId = value; profile?.putStudentData("pushDeviceId", value) ?: return; }
+
/* _____ _
/ ____| (_)
| (___ _ _ _ __ ___ _ __ __ _ _ __ _
@@ -256,6 +255,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
var startPointsSemester1: Int
get() { mStartPointsSemester1 = mStartPointsSemester1 ?: profile?.getStudentData("startPointsSemester1", 0); return mStartPointsSemester1 ?: 0 }
set(value) { profile?.putStudentData("startPointsSemester1", value) ?: return; mStartPointsSemester1 = value }
+
private var mStartPointsSemester2: Int? = null
var startPointsSemester2: Int
get() { mStartPointsSemester2 = mStartPointsSemester2 ?: profile?.getStudentData("startPointsSemester2", 0); return mStartPointsSemester2 ?: 0 }
@@ -265,8 +265,20 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
var enablePointGrades: Boolean
get() { mEnablePointGrades = mEnablePointGrades ?: profile?.getStudentData("enablePointGrades", true); return mEnablePointGrades ?: true }
set(value) { profile?.putStudentData("enablePointGrades", value) ?: return; mEnablePointGrades = value }
+
private var mEnableDescriptiveGrades: Boolean? = null
var enableDescriptiveGrades: Boolean
get() { mEnableDescriptiveGrades = mEnableDescriptiveGrades ?: profile?.getStudentData("enableDescriptiveGrades", true); return mEnableDescriptiveGrades ?: true }
set(value) { profile?.putStudentData("enableDescriptiveGrades", value) ?: return; mEnableDescriptiveGrades = value }
+
+ private var mTimetableNotPublic: Boolean? = null
+ var timetableNotPublic: Boolean
+ get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false }
+ set(value) { profile?.putStudentData("timetableNotPublic", value) ?: return; mTimetableNotPublic = value }
+
+ /**
+ * Set to false when Recaptcha helper doesn't provide a working token.
+ * When it's set to false uses Synergia for messages.
+ */
+ var messagesLoginSuccessful: Boolean = true
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt
index 842938c6..abf3ac5f 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt
@@ -8,18 +8,24 @@ import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusData
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api.LibrusApiAnnouncementMarkAsRead
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetAttachment
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetMessage
-import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaMarkAllAnnouncementsAsRead
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetRecipientList
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesSendMessage
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin
-import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin
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.modules.login.LoginStore
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
+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 Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
@@ -29,6 +35,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
val internalErrorList = mutableListOf()
val data: DataLibrus
+ private var afterLogin: (() -> Unit)? = null
init {
data = DataLibrus(app, profile, loginStore).apply {
@@ -39,9 +46,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
private fun completed() {
data.saveData()
- data.notify {
- callback.onCompleted()
- }
+ callback.onCompleted()
}
/* _______ _ _ _ _ _
@@ -52,18 +57,20 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
- override fun sync(featureIds: List, viewId: Int?, arguments: JsonObject?) {
+ override fun sync(featureIds: List, viewId: Int?, onlyEndpoints: List?, arguments: JsonObject?) {
data.arguments = arguments
- data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
+ data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId, onlyEndpoints)
login()
}
- private fun 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(librusLoginMethods, it) }
+ afterLogin?.let { this.afterLogin = it }
LibrusLogin(data) {
data()
}
@@ -75,57 +82,78 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
}
- LibrusData(data) {
+ afterLogin?.invoke() ?: LibrusData(data) {
completed()
}
}
override fun getMessage(message: MessageFull) {
- LibrusLoginPortal(data) {
- LibrusLoginApi(data) {
- LibrusLoginSynergia(data) {
- LibrusLoginMessages(data) {
- LibrusMessagesGetMessage(data, message) {
- completed()
- }
- }
- }
+ login(LOGIN_METHOD_LIBRUS_MESSAGES) {
+ if (data.messagesLoginSuccessful) LibrusMessagesGetMessage(data, message) { completed() }
+ else LibrusSynergiaGetMessage(data, message) { completed() }
+ }
+ }
+
+ override fun sendMessage(recipients: List, subject: String, text: String) {
+ login(LOGIN_METHOD_LIBRUS_MESSAGES) {
+ LibrusMessagesSendMessage(data, recipients, subject, text) {
+ completed()
}
}
}
override fun markAllAnnouncementsAsRead() {
- LibrusLoginPortal(data) {
- LibrusLoginApi(data) {
- LibrusLoginSynergia(data) {
- LibrusSynergiaMarkAllAnnouncementsAsRead(data) {
+ login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
+ LibrusSynergiaMarkAllAnnouncementsAsRead(data) {
+ completed()
+ }
+ }
+ }
+
+ override fun getAnnouncement(announcement: AnnouncementFull) {
+ login(LOGIN_METHOD_LIBRUS_API) {
+ LibrusApiAnnouncementMarkAsRead(data, announcement) {
+ completed()
+ }
+ }
+ }
+
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
+ when (owner) {
+ is Message -> {
+ login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
+ if (data.messagesLoginSuccessful) LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) { completed() }
+ LibrusSynergiaGetAttachment(data, owner, attachmentId, attachmentName) { completed() }
+ }
+ }
+ is EventFull -> {
+ login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
+ LibrusSynergiaHomeworkGetAttachment(data, owner, attachmentId, attachmentName) {
completed()
}
}
}
+ else -> completed()
}
}
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
- LibrusLoginPortal(data) {
- LibrusLoginApi(data) {
- LibrusLoginSynergia(data) {
- LibrusLoginMessages(data) {
- LibrusMessagesGetAttachment(data, message, attachmentId, attachmentName) {
- completed()
- }
- }
- }
+ override fun getRecipientList() {
+ login(LOGIN_METHOD_LIBRUS_MESSAGES) {
+ LibrusMessagesGetRecipientList(data) {
+ completed()
}
}
}
- override fun firstLogin() {
- LibrusFirstLogin(data) {
- completed()
+ override fun getEvent(eventFull: EventFull) {
+ login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
+ LibrusSynergiaGetHomework(data, eventFull) {
+ completed()
+ }
}
}
+ override fun firstLogin() { LibrusFirstLogin(data) { completed() } }
override fun cancel() {
d(TAG, "Cancelled")
data.cancel()
@@ -133,18 +161,9 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
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 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
@@ -155,35 +174,32 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
when (apiError.errorCode) {
ERROR_LIBRUS_PORTAL_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_PORTAL)
- data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_PORTAL)
- data.targetLoginMethodIds.sort()
+ data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_PORTAL)
data.portalTokenExpiryTime = 0
login()
}
ERROR_LIBRUS_API_ACCESS_DENIED,
ERROR_LIBRUS_API_TOKEN_EXPIRED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_API)
- data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_API)
- data.targetLoginMethodIds.sort()
+ data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_API)
data.apiTokenExpiryTime = 0
login()
}
ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_SYNERGIA)
- data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_SYNERGIA)
- data.targetLoginMethodIds.sort()
+ data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_SYNERGIA)
data.synergiaSessionIdExpiryTime = 0
login()
}
ERROR_LIBRUS_MESSAGES_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_MESSAGES)
- data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_MESSAGES)
- data.targetLoginMethodIds.sort()
+ data.prepareFor(librusLoginMethods, LOGIN_METHOD_LIBRUS_MESSAGES)
data.messagesSessionIdExpiryTime = 0
login()
}
ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE,
ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING,
+ ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED,
ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED,
ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED -> {
login()
@@ -202,15 +218,19 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID -> {
login()
}
- // TODO PORTAL CAPTCHA
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC -> {
- loginStore.putLoginData("timetableNotPublic", true)
+ data.timetableNotPublic = true
data()
}
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
data()
}
+ ERROR_LIBRUS_API_DEVICE_REGISTERED -> {
+ data.app.config.sync.tokenLibrusList =
+ data.app.config.sync.tokenLibrusList + data.profileId
+ data()
+ }
else -> callback.onError(apiError)
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusFeatures.kt
index 132d6af1..c14a00df 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusFeatures.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusFeatures.kt
@@ -15,6 +15,7 @@ const val ENDPOINT_LIBRUS_API_UNITS = 1005
const val ENDPOINT_LIBRUS_API_USERS = 1006
const val ENDPOINT_LIBRUS_API_SUBJECTS = 1007
const val ENDPOINT_LIBRUS_API_CLASSROOMS = 1008
+const val ENDPOINT_LIBRUS_API_LESSONS = 1009
const val ENDPOINT_LIBRUS_API_PUSH_CONFIG = 1010
const val ENDPOINT_LIBRUS_API_TIMETABLES = 1015
const val ENDPOINT_LIBRUS_API_SUBSTITUTIONS = 1016
@@ -49,19 +50,23 @@ const val ENDPOINT_LIBRUS_API_CLASS_FREE_DAYS = 1130
const val ENDPOINT_LIBRUS_SYNERGIA_INFO = 2010
const val ENDPOINT_LIBRUS_SYNERGIA_GRADES = 2020
const val ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK = 2030
+const val ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_RECEIVED = 2040
+const val ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_SENT = 2050
const val ENDPOINT_LIBRUS_MESSAGES_RECEIVED = 3010
const val ENDPOINT_LIBRUS_MESSAGES_SENT = 3020
const val ENDPOINT_LIBRUS_MESSAGES_TRASH = 3030
-const val ENDPOINT_LIBRUS_MESSAGES_RECEIVERS = 3040
-const val ENDPOINT_LIBRUS_MESSAGES_GET = 3040
val LibrusFeatures = listOf(
+ Feature(LOGIN_TYPE_LIBRUS, FEATURE_ALWAYS_NEEDED, listOf(
+ ENDPOINT_LIBRUS_API_LESSONS to LOGIN_METHOD_LIBRUS_API
+ ), listOf(LOGIN_METHOD_LIBRUS_API)),
+
// push config
Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf(
ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
- !data.app.config.sync.tokenLibrusList.contains(data.profileId)
+ (data as DataLibrus).isPremium && !data.app.config.sync.tokenLibrusList.contains(data.profileId)
},
@@ -96,7 +101,8 @@ val LibrusFeatures = listOf(
ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
- ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
+ // Commented out, because TextGrades/Categories is the same as Grades/Categories
+ /* ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API, */
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API,
@@ -112,11 +118,11 @@ val LibrusFeatures = listOf(
* Homework - using API.
* Sync only if account has premium access.
*/
- Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
+ /*Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
ENDPOINT_LIBRUS_API_HOMEWORK to LOGIN_METHOD_LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
(data as DataLibrus).isPremium
- },
+ },*/
/**
* Behaviour - using API.
*/
@@ -223,9 +229,9 @@ val LibrusFeatures = listOf(
*/
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LOGIN_METHOD_LIBRUS_SYNERGIA
- ), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)).withShouldSync { data ->
+ ), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA))/*.withShouldSync { data ->
!(data as DataLibrus).isPremium
- },
+ }*/,
/**
* Messages inbox - using messages website.
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusRecaptchaHelper.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusRecaptchaHelper.kt
new file mode 100644
index 00000000..3652f18a
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/LibrusRecaptchaHelper.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-5-8.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus
+
+import android.content.Context
+import android.webkit.WebView
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import pl.szczodrzynski.edziennik.startCoroutineTimer
+import kotlin.coroutines.CoroutineContext
+
+class LibrusRecaptchaHelper(
+ val context: Context,
+ url: String,
+ html: String,
+ val onSuccess: (url: String) -> Unit,
+ val onTimeout: () -> Unit
+) : CoroutineScope {
+ companion object {
+ private const val TAG = "LibrusRecaptchaHelper"
+ }
+
+ private val job: Job = Job()
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Default
+
+ private val webView by lazy {
+ WebView(context).also {
+ it.settings.javaScriptEnabled = true
+ it.webViewClient = WebViewClient()
+ }
+ }
+
+ private var timeout: Job? = null
+ private var timedOut = false
+
+ inner class WebViewClient : android.webkit.WebViewClient() {
+ override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
+ timeout?.cancel()
+ if (!timedOut) {
+ onSuccess(url)
+ }
+ return true
+ }
+ }
+
+ init {
+ launch(Dispatchers.Main) {
+ webView.loadDataWithBaseURL(url, html, "text/html", "UTF-8", null)
+ }
+ timeout = startCoroutineTimer(delayMillis = 10000L) {
+ timedOut = true
+ onTimeout()
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusApi.kt
index 317a79aa..d06cc219 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusApi.kt
@@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.Utils.d
import java.net.HttpURLConnection.*
-open class LibrusApi(open val data: DataLibrus) {
+open class LibrusApi(open val data: DataLibrus, open val lastSync: Long?) {
companion object {
private const val TAG = "LibrusApi"
}
@@ -26,7 +26,7 @@ open class LibrusApi(open val data: DataLibrus) {
val profile
get() = data.profile
- fun apiGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject) -> Unit) {
+ fun apiGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, ignoreErrors: List = emptyList(), onSuccess: (json: JsonObject) -> Unit) {
d(tag, "Request: Librus/Api - ${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
@@ -44,9 +44,12 @@ open class LibrusApi(open val data: DataLibrus) {
.withResponse(response))
return
}
+ /*
+{"Status":"Error","Code":"DeviceRegistered","Message":"This device is alerdy registered.","Resources":{"..":{"Url":"https:\/\/api.librus.pl\/2.0\/Root"}},"Url":"https:\/\/api.librus.pl\/2.0\/ChangeRegister"}*/
val error = if (response?.code() == 200) null else
json.getString("Code") ?:
json.getString("Message") ?:
+ json.getString("Status") ?:
response?.parserErrorBody
error?.let { code ->
when (code) {
@@ -63,12 +66,17 @@ open class LibrusApi(open val data: DataLibrus) {
"NotesIsNotActive" -> ERROR_LIBRUS_API_NOTES_NOT_ACTIVE
"InvalidRequest" -> ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
"Nieprawidłowy węzeł." -> ERROR_LIBRUS_API_INCORRECT_ENDPOINT
+ "NoticeboardProblem" -> ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
+ "DeviceRegistered" -> ERROR_LIBRUS_API_DEVICE_REGISTERED
+ "Maintenance" -> ERROR_LIBRUS_API_MAINTENANCE
else -> ERROR_LIBRUS_API_OTHER
}.let { errorCode ->
- data.error(ApiError(tag, errorCode)
- .withApiResponse(json)
- .withResponse(response))
- return
+ if (errorCode !in ignoreErrors) {
+ data.error(ApiError(tag, errorCode)
+ .withApiResponse(json)
+ .withResponse(response))
+ return
+ }
}
}
@@ -112,6 +120,8 @@ open class LibrusApi(open val data: DataLibrus) {
.allowErrorCode(HTTP_FORBIDDEN)
.allowErrorCode(HTTP_UNAUTHORIZED)
.allowErrorCode(HTTP_UNAVAILABLE)
+ .allowErrorCode(HTTP_NOT_FOUND)
+ .allowErrorCode(503)
.callback(callback)
.build()
.enqueue()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusData.kt
index bccb86b3..877d803b 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusData.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusData.kt
@@ -8,9 +8,10 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetList
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaGetMessages
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaHomework
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaInfo
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
+import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.utils.Utils
class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
@@ -31,129 +32,163 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess()
return
}
- useEndpoint(data.targetEndpointIds.removeAt(0)) {
+ 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, onSuccess: () -> Unit) {
- Utils.d(TAG, "Using endpoint $endpointId")
+ private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
+ Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
/**
* API
*/
ENDPOINT_LIBRUS_API_ME -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
- LibrusApiMe(data, onSuccess)
+ LibrusApiMe(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_SCHOOLS -> {
data.startProgress(R.string.edziennik_progress_endpoint_school_info)
- LibrusApiSchools(data, onSuccess)
+ LibrusApiSchools(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_CLASSES -> {
data.startProgress(R.string.edziennik_progress_endpoint_classes)
- LibrusApiClasses(data, onSuccess)
+ LibrusApiClasses(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES -> {
data.startProgress(R.string.edziennik_progress_endpoint_teams)
- LibrusApiVirtualClasses(data, onSuccess)
+ LibrusApiVirtualClasses(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_UNITS -> {
data.startProgress(R.string.edziennik_progress_endpoint_units)
- LibrusApiUnits(data, onSuccess)
+ LibrusApiUnits(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_USERS -> {
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
- LibrusApiUsers(data, onSuccess)
+ LibrusApiUsers(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_SUBJECTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_subjects)
- LibrusApiSubjects(data, onSuccess)
+ LibrusApiSubjects(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_CLASSROOMS -> {
data.startProgress(R.string.edziennik_progress_endpoint_classrooms)
- LibrusApiClassrooms(data, onSuccess)
+ LibrusApiClassrooms(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_LESSONS -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_lessons)
+ LibrusApiLessons(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_PUSH_CONFIG -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_push_config)
+ LibrusApiPushConfig(data, lastSync, onSuccess)
}
- // TODO push config
ENDPOINT_LIBRUS_API_TIMETABLES -> {
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
- LibrusApiTimetables(data, onSuccess)
+ LibrusApiTimetables(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
- LibrusApiGradeCategories(data, onSuccess)
+ LibrusApiGradeCategories(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
- LibrusApiBehaviourGradeCategories(data, onSuccess)
+ LibrusApiBehaviourGradeCategories(data, lastSync, onSuccess)
}
+ ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
+ LibrusApiDescriptiveGradeCategories(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
+ LibrusApiTextGradeCategories(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
+ LibrusApiPointGradeCategories(data, lastSync, onSuccess)
+ }
+
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
- LibrusApiGradeComments(data, onSuccess)
+ LibrusApiGradeComments(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
- LibrusApiBehaviourGradeComments(data, onSuccess)
+ LibrusApiBehaviourGradeComments(data, lastSync, onSuccess)
}
+
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grades)
- LibrusApiGrades(data, onSuccess)
+ LibrusApiGrades(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_behaviour_grades)
- LibrusApiBehaviourGrades(data, onSuccess)
+ LibrusApiBehaviourGrades(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_descriptive_grades)
+ LibrusApiDescriptiveGrades(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_TEXT_GRADES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_descriptive_grades)
+ LibrusApiTextGrades(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_API_POINT_GRADES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_point_grades)
+ LibrusApiPointGrades(data, lastSync, onSuccess)
}
- // TODO grades
ENDPOINT_LIBRUS_API_EVENT_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_event_types)
- LibrusApiEventTypes(data, onSuccess)
+ LibrusApiEventTypes(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_EVENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_events)
- LibrusApiEvents(data, onSuccess)
+ LibrusApiEvents(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_HOMEWORK -> {
data.startProgress(R.string.edziennik_progress_endpoint_homework)
- LibrusApiHomework(data, onSuccess)
+ LibrusApiHomework(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_LUCKY_NUMBER -> {
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
- LibrusApiLuckyNumber(data, onSuccess)
+ LibrusApiLuckyNumber(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_NOTICE_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_notice_types)
- LibrusApiNoticeTypes(data, onSuccess)
+ LibrusApiNoticeTypes(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_NOTICES -> {
data.startProgress(R.string.edziennik_progress_endpoint_notices)
- LibrusApiNotices(data, onSuccess)
+ LibrusApiNotices(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance_types)
- LibrusApiAttendanceTypes(data, onSuccess)
+ LibrusApiAttendanceTypes(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_ATTENDANCES -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
- LibrusApiAttendances(data, onSuccess)
+ LibrusApiAttendances(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_ANNOUNCEMENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
- LibrusApiAnnouncements(data, onSuccess)
+ LibrusApiAnnouncements(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_PT_MEETINGS -> {
data.startProgress(R.string.edziennik_progress_endpoint_pt_meetings)
- LibrusApiPtMeetings(data, onSuccess)
+ LibrusApiPtMeetings(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_day_types)
- LibrusApiTeacherFreeDayTypes(data, onSuccess)
+ LibrusApiTeacherFreeDayTypes(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS -> {
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_days)
- LibrusApiTeacherFreeDays(data, onSuccess)
+ LibrusApiTeacherFreeDays(data, lastSync, onSuccess)
}
/**
@@ -161,11 +196,19 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
*/
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK -> {
data.startProgress(R.string.edziennik_progress_endpoint_homework)
- LibrusSynergiaHomework(data, onSuccess)
+ LibrusSynergiaHomework(data, lastSync, onSuccess)
}
ENDPOINT_LIBRUS_SYNERGIA_INFO -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
- LibrusSynergiaInfo(data, onSuccess)
+ LibrusSynergiaInfo(data, lastSync, onSuccess)
+ }
+ ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_RECEIVED -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
+ LibrusSynergiaGetMessages(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
+ }
+ ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_SENT -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
+ LibrusSynergiaGetMessages(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
}
/**
@@ -173,14 +216,16 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
*/
ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
- LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, onSuccess = onSuccess)
+ if (data.messagesLoginSuccessful) LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
+ else LibrusSynergiaGetMessages(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
}
ENDPOINT_LIBRUS_MESSAGES_SENT -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
- LibrusMessagesGetList(data, type = Message.TYPE_SENT, onSuccess = onSuccess)
+ if (data.messagesLoginSuccessful) LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
+ else LibrusSynergiaGetMessages(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
}
- else -> onSuccess()
+ else -> onSuccess(endpointId)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusMessages.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusMessages.kt
index 2915d4d7..dc8d8c47 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusMessages.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusMessages.kt
@@ -5,13 +5,15 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data
import com.google.gson.JsonObject
+import com.google.gson.JsonParser
import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.FileCallbackHandler
import im.wangchao.mhttp.callback.JsonCallbackHandler
import im.wangchao.mhttp.callback.TextCallbackHandler
-import okhttp3.Cookie
+import org.json.JSONObject
+import org.json.XML
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.parser.Parser
@@ -27,7 +29,7 @@ import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
-open class LibrusMessages(open val data: DataLibrus) {
+open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
companion object {
private const val TAG = "LibrusMessages"
}
@@ -38,10 +40,10 @@ open class LibrusMessages(open val data: DataLibrus) {
val profile
get() = data.profile
- fun messagesGet(tag: String, endpoint: String, method: Int = POST,
+ fun messagesGet(tag: String, module: String, method: Int = POST,
parameters: Map? = null, onSuccess: (doc: Document) -> Unit) {
- d(tag, "Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$endpoint")
+ d(tag, "Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$module")
val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response?) {
@@ -52,13 +54,20 @@ open class LibrusMessages(open val data: DataLibrus) {
}
when {
- text.contains("Niepoprawny login i/lub hasło. ") -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
- text.contains("stop.png") -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
- text.contains("eAccessDeny") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
- text.contains("OffLine") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
- text.contains("error ") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
- text.contains("eVarWhitThisNameNotExists ") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
- text.contains("") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
+ text.contains("Niepoprawny login i/lub hasło. ") -> ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN
+ text.contains("Nie odnaleziono wiadomości. ") -> ERROR_LIBRUS_MESSAGES_NOT_FOUND
+ text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
+ text.contains("eAccessDeny") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
+ text.contains("OffLine") -> ERROR_LIBRUS_MESSAGES_MAINTENANCE
+ text.contains("error ") -> ERROR_LIBRUS_MESSAGES_ERROR
+ text.contains("eVarWhitThisNameNotExists ") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
+ text.contains("") -> ERROR_LIBRUS_MESSAGES_OTHER
+ else -> null
+ }?.let { errorCode ->
+ data.error(ApiError(tag, errorCode)
+ .withApiResponse(text)
+ .withResponse(response))
+ return
}
try {
@@ -79,14 +88,7 @@ open class LibrusMessages(open val data: DataLibrus) {
}
}
- data.app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("DZIENNIKSID")
- .value(data.messagesSessionId!!)
- .domain("wiadomosci.librus.pl")
- .secure().httpOnly().build()
- ))
-
+ data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
val doc = docBuilder.newDocument()
@@ -107,22 +109,92 @@ open class LibrusMessages(open val data: DataLibrus) {
transformer.transform(DOMSource(doc), StreamResult(stringWriter))
val requestXml = stringWriter.toString()
- /*val requestXml = xml("service") {
- "header" { }
- "data" {
- for ((key, value) in parameters.orEmpty()) {
- key {
- -value.toString()
+ Request.builder()
+ .url("$LIBRUS_MESSAGES_URL/$module")
+ .userAgent(SYNERGIA_USER_AGENT)
+ .setTextBody(requestXml, MediaTypeUtils.APPLICATION_XML)
+ .apply {
+ when (method) {
+ GET -> get()
+ POST -> post()
}
}
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+
+ fun messagesGetJson(tag: String, module: String, method: Int = POST,
+ parameters: Map? = null, onSuccess: (json: JsonObject?) -> Unit) {
+
+ d(tag, "Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$module")
+
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response?) {
+ if (text.isNullOrEmpty()) {
+ data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return
+ }
+
+ when {
+ text.contains("Niepoprawny login i/lub hasło. ") -> ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN
+ text.contains("Nie odnaleziono wiadomości. ") -> ERROR_LIBRUS_MESSAGES_NOT_FOUND
+ text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
+ text.contains("eAccessDeny") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
+ text.contains("OffLine") -> ERROR_LIBRUS_MESSAGES_MAINTENANCE
+ text.contains("error ") -> ERROR_LIBRUS_MESSAGES_ERROR
+ text.contains("eVarWhitThisNameNotExists ") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
+ text.contains("") -> ERROR_LIBRUS_MESSAGES_OTHER
+ else -> null
+ }?.let { errorCode ->
+ data.error(ApiError(tag, errorCode)
+ .withApiResponse(text)
+ .withResponse(response))
+ return
+ }
+
+ try {
+ val json: JSONObject? = XML.toJSONObject(text)
+ onSuccess(JsonParser().parse(json?.toString() ?: "{}")?.asJsonObject)
+ } catch (e: Exception) {
+ data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
+ .withResponse(response)
+ .withThrowable(e)
+ .withApiResponse(text))
+ }
}
- }.toString(PrintOptions(
- singleLineTextElements = true,
- useSelfClosingTags = true
- ))*/
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
+
+ val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
+ val doc = docBuilder.newDocument()
+ val serviceElement = doc.createElement("service")
+ val headerElement = doc.createElement("header")
+ val dataElement = doc.createElement("data")
+ for ((key, value) in parameters.orEmpty()) {
+ val element = doc.createElement(key)
+ element.appendChild(doc.createTextNode(value.toString()))
+ dataElement.appendChild(element)
+ }
+ serviceElement.appendChild(headerElement)
+ serviceElement.appendChild(dataElement)
+ doc.appendChild(serviceElement)
+ val transformer = TransformerFactory.newInstance().newTransformer()
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
+ val stringWriter = StringWriter()
+ transformer.transform(DOMSource(doc), StreamResult(stringWriter))
+ val requestXml = stringWriter.toString()
Request.builder()
- .url("$LIBRUS_MESSAGES_URL/$endpoint")
+ .url("$LIBRUS_MESSAGES_URL/$module")
.userAgent(SYNERGIA_USER_AGENT)
.setTextBody(requestXml, MediaTypeUtils.APPLICATION_XML)
.apply {
@@ -180,10 +252,11 @@ open class LibrusMessages(open val data: DataLibrus) {
.enqueue()
}
- fun sandboxGetFile(tag: String, action: String, targetFile: File, onSuccess: (file: File) -> Unit,
+ fun sandboxGetFile(tag: String, url: String, targetFile: File, onSuccess: (file: File) -> Unit,
+ method: Int = GET,
onProgress: (written: Long, total: Long) -> Unit) {
- d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
+ d(tag, "Request: Librus/Messages - $url")
val callback = object : FileCallbackHandler(targetFile) {
override fun onSuccess(file: File?, response: Response?) {
@@ -219,9 +292,14 @@ open class LibrusMessages(open val data: DataLibrus) {
}
Request.builder()
- .url("$LIBRUS_SANDBOX_URL$action")
+ .url(url)
.userAgent(SYNERGIA_USER_AGENT)
- .post()
+ .also {
+ when (method) {
+ POST -> it.post()
+ else -> it.get()
+ }
+ }
.callback(callback)
.build()
.enqueue()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusPortal.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusPortal.kt
index 48017438..4a5e0af6 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusPortal.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusPortal.kt
@@ -44,6 +44,7 @@ open class LibrusPortal(open val data: DataLibrus) {
"Access token is invalid" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
"ApiDisabled" -> ERROR_LIBRUS_PORTAL_API_DISABLED
"Account not found" -> ERROR_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND
+ "Unable to refresh the account" -> ERROR_LIBRUS_PORTAL_MAINTENANCE
else -> when (json.getString("hint")) {
"Error while decoding to JSON" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
else -> ERROR_LIBRUS_PORTAL_OTHER
@@ -97,6 +98,7 @@ open class LibrusPortal(open val data: DataLibrus) {
.allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
.allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST)
.allowErrorCode(HttpURLConnection.HTTP_GONE)
+ .allowErrorCode(424)
.callback(callback)
.build()
.enqueue()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusSynergia.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusSynergia.kt
index d748cb13..72faf801 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusSynergia.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusSynergia.kt
@@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils.d
-open class LibrusSynergia(open val data: DataLibrus) {
+open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
companion object {
private const val TAG = "LibrusSynergia"
}
@@ -35,7 +35,7 @@ open class LibrusSynergia(open val data: DataLibrus) {
return
}
- if (!text.contains("jesteś zalogowany")) {
+ if (!text.contains("jesteś zalogowany") && !text.contains("Podgląd zadania")) {
when {
text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
text.contains("Przerwa techniczna") -> ERROR_LIBRUS_SYNERGIA_MAINTENANCE
@@ -48,7 +48,6 @@ open class LibrusSynergia(open val data: DataLibrus) {
}
}
-
try {
onSuccess(text)
} catch (e: Exception) {
@@ -90,4 +89,44 @@ open class LibrusSynergia(open val data: DataLibrus) {
.build()
.enqueue()
}
+
+ fun redirectUrlGet(tag: String, url: String, onSuccess: (url: String) -> Unit) {
+ d(tag, "Request: Librus/Synergia - $url")
+
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response) {
+ val redirectUrl = response.headers().get("Location")
+
+ if (redirectUrl != null) {
+ try {
+ onSuccess(redirectUrl)
+ } catch (e: Exception) {
+ data.error(ApiError(tag, EXCEPTION_LIBRUS_SYNERGIA_REQUEST)
+ .withResponse(response)
+ .withThrowable(e)
+ .withApiResponse(text))
+ }
+ } else {
+ data.error(ApiError(tag, ERROR_LIBRUS_SYNERGIA_OTHER)
+ .withResponse(response)
+ .withApiResponse(text))
+ }
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url(url)
+ .userAgent(LIBRUS_USER_AGENT)
+ .withClient(data.app.httpLazy)
+ .get()
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncementMarkAsRead.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncementMarkAsRead.kt
new file mode 100644
index 00000000..23cfceb4
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncementMarkAsRead.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-27
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
+import pl.szczodrzynski.edziennik.data.api.ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
+import pl.szczodrzynski.edziennik.data.api.POST
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
+
+class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
+ private val announcement: AnnouncementFull,
+ val onSuccess: () -> Unit
+) : LibrusApi(data, null) {
+ companion object {
+ const val TAG = "LibrusApiAnnouncementMarkAsRead"
+ }
+
+ init {
+ apiGet(TAG, "SchoolNotices/MarkAsRead/${announcement.idString}", method = POST,
+ ignoreErrors = listOf(
+ ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS,
+ ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
+ )) {
+ announcement.seen = true
+
+ EventBus.getDefault().postSticky(AnnouncementGetEvent(announcement))
+
+ data.setSeenMetadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_ANNOUNCEMENT,
+ announcement.id,
+ announcement.seen,
+ announcement.notified
+ ))
+ onSuccess()
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt
index 2dd3a5ec..d19be231 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAnnouncements.kt
@@ -8,23 +8,26 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ANNOUNCEMENTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.utils.models.Date
class LibrusApiAnnouncements(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiAnnouncements"
}
init { data.profile?.also { profile ->
apiGet(TAG, "SchoolNotices") { json ->
- val announcements = json.getJsonArray("SchoolNotices").asJsonObjectList()
+ val announcements = json.getJsonArray("SchoolNotices")?.asJsonObjectList()
announcements?.forEach { announcement ->
- val id = announcement.getString("Id")?.crc32() ?: return@forEach
+ val longId = announcement.getString("Id") ?: return@forEach
+ val id = longId.crc32()
val subject = announcement.getString("Subject") ?: ""
val text = announcement.getString("Content") ?: ""
val startDate = Date.fromY_m_d(announcement.getString("StartDate"))
@@ -35,28 +38,30 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
val read = announcement.getBoolean("WasRead") ?: false
val announcementObject = Announcement(
- profileId,
- id,
- subject,
- text,
- startDate,
- endDate,
- teacherId
- )
+ profileId = profileId,
+ id = id,
+ subject = subject,
+ text = text,
+ startDate = startDate,
+ endDate = endDate,
+ teacherId = teacherId,
+ addedDate = addedDate
+ ).also {
+ it.idString = longId
+ }
data.announcementList.add(announcementObject)
- data.metadataList.add(Metadata(
+ data.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_ANNOUNCEMENT,
id,
read,
- profile.empty || read,
- addedDate
+ profile.empty || read
))
}
data.setSyncNext(ENDPOINT_LIBRUS_API_ANNOUNCEMENTS, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_ANNOUNCEMENTS)
}
}}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt
index 2d85e1fa..c620d13d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendanceTypes.kt
@@ -9,41 +9,57 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.AttendanceType
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance
+import pl.szczodrzynski.edziennik.data.db.entity.AttendanceType
class LibrusApiAttendanceTypes(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiAttendanceTypes"
}
init {
apiGet(TAG, "Attendances/Types") { json ->
- val attendanceTypes = json.getJsonArray("Types").asJsonObjectList()
+ val attendanceTypes = json.getJsonArray("Types")?.asJsonObjectList()
attendanceTypes?.forEach { attendanceType ->
val id = attendanceType.getLong("Id") ?: return@forEach
- val name = attendanceType.getString("Name") ?: ""
- val color = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") } ?: -1
- val standardId = when (attendanceType.getBoolean("Standard") ?: false) {
- true -> id
- false -> attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id
- }
- val type = when (standardId) {
+ val typeName = attendanceType.getString("Name") ?: ""
+ val typeSymbol = attendanceType.getString("Short") ?: ""
+ val typeColor = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") }
+
+ val isStandard = attendanceType.getBoolean("Standard") ?: false
+ val baseType = when (attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id) {
1L -> Attendance.TYPE_ABSENT
2L -> Attendance.TYPE_BELATED
3L -> Attendance.TYPE_ABSENT_EXCUSED
4L -> Attendance.TYPE_RELEASED
- /*100*/else -> Attendance.TYPE_PRESENT
+ /*100*/else -> when (isStandard) {
+ true -> Attendance.TYPE_PRESENT
+ false -> Attendance.TYPE_PRESENT_CUSTOM
+ }
+ }
+ val typeShort = when (isStandard) {
+ true -> data.app.attendanceManager.getTypeShort(baseType)
+ false -> typeSymbol
}
- data.attendanceTypes.put(id, AttendanceType(profileId, id, name, type, color))
+ data.attendanceTypes.put(id, AttendanceType(
+ profileId,
+ id,
+ baseType,
+ typeName,
+ typeShort,
+ typeSymbol,
+ typeColor
+ ))
}
- data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 4*DAY)
- onSuccess()
+ data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 2*DAY)
+ onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt
index bbc0d26e..7857dc2a 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt
@@ -9,14 +9,15 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ATTENDANCES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.utils.Utils
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance
+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 LibrusApiAttendances(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiAttendances"
}
@@ -25,54 +26,65 @@ class LibrusApiAttendances(override val data: DataLibrus,
if (data.attendanceTypes.isEmpty()) {
data.db.attendanceTypeDao().getAllNow(profileId).toSparseArray(data.attendanceTypes) { it.id }
}
+ if (data.librusLessons.isEmpty()) {
+ data.db.librusLessonDao().getAllNow(profileId).toSparseArray(data.librusLessons) { it.lessonId }
+ }
apiGet(TAG, "Attendances") { json ->
- val attendances = json.getJsonArray("Attendances").asJsonObjectList()
+ val attendances = json.getJsonArray("Attendances")?.asJsonObjectList()
attendances?.forEach { attendance ->
- val id = Utils.strToInt((attendance.getString("Id") ?: return@forEach)
+ val id = ((attendance.getString("Id") ?: return@forEach)
.replace("[^\\d.]".toRegex(), "")).toLong()
- val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id") ?: -1
+ val lessonId = attendance.getJsonObject("Lesson")?.getLong("Id") ?: -1
val lessonNo = attendance.getInt("LessonNo") ?: return@forEach
- val startTime = data.lessonRanges.get(lessonNo).startTime
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
+ val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id")
val semester = attendance.getInt("Semester") ?: return@forEach
- val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
- val typeObject = data.attendanceTypes.get(type)
- val topic = typeObject?.name ?: ""
- val lessonList = data.db.timetableDao().getForDateNow(profileId, lessonDate)
- val subjectId = lessonList.firstOrNull { it.startTime == startTime }?.subjectId ?: -1
+ val typeId = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
+ val type = data.attendanceTypes[typeId] ?: null
- val attendanceObject = Attendance(
- profileId,
- id,
- teacherId,
- subjectId,
- semester,
- topic,
- lessonDate,
- startTime,
- typeObject.type
- )
+ val startTime = data.lessonRanges.get(lessonNo)?.startTime
+
+ val lesson = if (lessonId != -1L)
+ data.librusLessons.singleOrNull { it.lessonId == lessonId }
+ else null
val addedDate = Date.fromIso(attendance.getString("AddDate") ?: return@forEach)
+ val attendanceObject = Attendance(
+ profileId = profileId,
+ id = id,
+ baseType = type?.baseType ?: Attendance.TYPE_UNKNOWN,
+ typeName = type?.typeName ?: "nieznany rodzaj",
+ typeShort = type?.typeShort ?: "?",
+ typeSymbol = type?.typeSymbol ?: "?",
+ typeColor = type?.typeColor,
+ date = lessonDate,
+ startTime = startTime,
+ semester = semester,
+ teacherId = teacherId ?: lesson?.teacherId ?: -1,
+ subjectId = lesson?.subjectId ?: -1,
+ addedDate = addedDate
+ ).also {
+ it.lessonNumber = lessonNo
+ }
+
data.attendanceList.add(attendanceObject)
- if(typeObject.type != Attendance.TYPE_PRESENT) {
+ if(type?.baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate
+ profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN,
+ profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN
))
}
}
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeCategories.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeCategories.kt
index c12499ef..650dfbb5 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeCategories.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeCategories.kt
@@ -9,10 +9,12 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
class LibrusApiBehaviourGradeCategories(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiBehaviourGradeCategories"
}
@@ -40,7 +42,7 @@ class LibrusApiBehaviourGradeCategories(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES, 1 * WEEK)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeComments.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeComments.kt
index 43a4d5f9..eedb1d1d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeComments.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGradeComments.kt
@@ -8,11 +8,13 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
class LibrusApiBehaviourGradeComments(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiBehaviourGradeComments"
}
@@ -38,7 +40,7 @@ class LibrusApiBehaviourGradeComments(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGrades.kt
index 33f6ab5d..fae79a50 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGrades.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiBehaviourGrades.kt
@@ -8,71 +8,94 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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_POINT_SUM
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+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.text.DecimalFormat
class LibrusApiBehaviourGrades(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiBehaviourGrades"
}
private val nameFormat by lazy { DecimalFormat("#.##") }
- init { data.profile?.let { profile ->
+ private val types by lazy {
+ mapOf(
+ 1 to ("wz" to "wzorowe"),
+ 2 to ("bdb" to "bardzo dobre"),
+ 3 to ("db" to "dobre"),
+ 4 to ("popr" to "poprawne"),
+ 5 to ("ndp" to "nieodpowiednie"),
+ 6 to ("ng" to "naganne")
+ )
+ }
+
+ init { data.profile?.also { profile ->
apiGet(TAG, "BehaviourGrades/Points") { json ->
- val semester1StartGradeObject = Grade(
- profileId,
- -101,
- data.app.getString(R.string.grade_start_points),
- 0xffbdbdbd.toInt(),
- data.app.getString(R.string.grade_start_points_format, 1),
- nameFormat.format(data.startPointsSemester1),
- data.startPointsSemester1.toFloat(),
- -1f,
- 1,
- -1,
- 1
- ).apply { type = Grade.TYPE_BEHAVIOUR }
+ if (data.startPointsSemester1 > 0) {
+ val semester1StartGradeObject = Grade(
+ profileId = profileId,
+ id = -101,
+ name = nameFormat.format(data.startPointsSemester1),
+ type = TYPE_POINT_SUM,
+ value = data.startPointsSemester1.toFloat(),
+ weight = 0f,
+ color = 0xffbdbdbd.toInt(),
+ category = data.app.getString(R.string.grade_start_points),
+ description = data.app.getString(R.string.grade_start_points_format, 1),
+ comment = null,
+ semester = 1,
+ teacherId = -1,
+ subjectId = 1,
+ addedDate = profile.getSemesterStart(1).inMillis
+ )
- data.gradeList.add(semester1StartGradeObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_GRADE,
- semester1StartGradeObject.id,
- true,
- true,
- profile.getSemesterStart(1).inMillis
- ))
+ data.gradeList.add(semester1StartGradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ semester1StartGradeObject.id,
+ true,
+ true
+ ))
+ }
- val semester2StartGradeObject = Grade(
- profileId,
- -102,
- data.app.getString(R.string.grade_start_points),
- 0xffbdbdbd.toInt(),
- data.app.getString(R.string.grade_start_points_format, 2),
- nameFormat.format(data.startPointsSemester2),
- data.startPointsSemester2.toFloat(),
- -1f,
- 2,
- -1,
- 1
- ).apply { type = Grade.TYPE_BEHAVIOUR }
+ if (data.startPointsSemester2 > 0) {
+ val semester2StartGradeObject = Grade(
+ profileId = profileId,
+ id = -102,
+ name = nameFormat.format(data.startPointsSemester2),
+ type = TYPE_POINT_SUM,
+ value = data.startPointsSemester2.toFloat(),
+ weight = -1f,
+ color = 0xffbdbdbd.toInt(),
+ category = data.app.getString(R.string.grade_start_points),
+ description = data.app.getString(R.string.grade_start_points_format, 2),
+ comment = null,
+ semester = 2,
+ teacherId = -1,
+ subjectId = 1,
+ addedDate = profile.getSemesterStart(2).inMillis
+ )
- data.gradeList.add(semester2StartGradeObject)
- data.metadataList.add(Metadata(
- profileId,
- Metadata.TYPE_GRADE,
- semester2StartGradeObject.id,
- true,
- true,
- profile.getSemesterStart(2).inMillis
- ))
+ data.gradeList.add(semester2StartGradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ semester2StartGradeObject.id,
+ true,
+ true
+ ))
+ }
json.getJsonArray("Grades")?.asJsonObjectList()?.forEach { grade ->
val id = grade.getLong("Id") ?: return@forEach
@@ -83,8 +106,12 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
val addedDate = grade.getString("AddDate")?.let { Date.fromIso(it) }
?: System.currentTimeMillis()
+ val text = grade.getString("Text")
+ val type = grade.getJsonObject("BehaviourGrade")?.getInt("Id")?.let { types[it] }
+
val name = when {
- value != null -> (if (value >= 0) "+" else "") + nameFormat.format(value)
+ type != null -> type.first
+ value != null -> (if (value > 0) "+" else "") + nameFormat.format(value)
shortName != null -> shortName
else -> return@forEach
}
@@ -103,32 +130,34 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
val categoryName = category?.text ?: ""
- val description = grade.getJsonArray("Comments")?.asJsonObjectList()?.let { comments ->
- if (comments.isNotEmpty()) {
- data.gradeCategories.singleOrNull {
- it.type == GradeCategory.TYPE_BEHAVIOUR_COMMENT
- && it.categoryId == comments[0].asJsonObject.getLong("Id")
- }?.text
- } else null
- } ?: ""
+ val comments = grade.getJsonArray("Comments")
+ ?.asJsonObjectList()
+ ?.mapNotNull { comment ->
+ val cId = comment.getLong("Id") ?: return@mapNotNull null
+ data.gradeCategories[cId]?.text
+ } ?: listOf()
+
+ val description = listOfNotNull(type?.second) + comments
val valueFrom = value ?: category?.valueFrom ?: 0f
val valueTo = category?.valueTo ?: 0f
val gradeObject = Grade(
- profileId,
- id,
- categoryName,
- color,
- description,
- name,
- valueFrom,
- -1f,
- semester,
- teacherId,
- 1
+ profileId = profileId,
+ id = id,
+ name = name,
+ type = TYPE_POINT_SUM,
+ value = valueFrom,
+ weight = -1f,
+ color = color,
+ category = categoryName,
+ description = text ?: description.join(" - "),
+ comment = if (text != null) description.join(" - ") else null,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = 1,
+ addedDate = addedDate
).apply {
- type = Grade.TYPE_BEHAVIOUR
valueMax = valueTo
}
@@ -138,13 +167,13 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
+ data.toRemove.add(DataRemoveModel.Grades.semesterWithType(profile.currentSemester, Grade.TYPE_POINT_SUM))
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES)
}
- }}
+ } ?: onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES) }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt
index 6f497021..171e80e1 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClasses.kt
@@ -8,14 +8,16 @@ import pl.szczodrzynski.edziennik.DAY
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_CLASSES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
+import pl.szczodrzynski.edziennik.data.db.entity.Team
import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getLong
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date
class LibrusApiClasses(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiClasses"
}
@@ -38,6 +40,8 @@ class LibrusApiClasses(override val data: DataLibrus,
teacherId
)
+ data.profile?.studentClassName = name
+
data.teamList.put(id, teamObject)
data.unitId = studentClass.getJsonObject("Unit").getLong("Id") ?: 0L
@@ -53,7 +57,7 @@ class LibrusApiClasses(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_CLASSES, 4 * DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_CLASSES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt
index 422321ca..80a11105 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiClassrooms.kt
@@ -8,26 +8,29 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_CLASSROOMS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.classrooms.Classroom
+import pl.szczodrzynski.edziennik.data.db.entity.Classroom
import java.util.*
class LibrusApiClassrooms(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiClassrooms"
}
init {
apiGet(TAG, "Classrooms") { json ->
- val classrooms = json.getJsonArray("Classrooms").asJsonObjectList()
+ val classrooms = json.getJsonArray("Classrooms")?.asJsonObjectList()
classrooms?.forEach { classroom ->
val id = classroom.getLong("Id") ?: return@forEach
val name = classroom.getString("Name")?.toLowerCase(Locale.getDefault()) ?: ""
val symbol = classroom.getString("Symbol")?.toLowerCase(Locale.getDefault()) ?: ""
- val nameShort = name.split(" ").onEach { it[0] }.joinToString()
+ val nameShort = name.fixWhiteSpaces().split(" ").onEach { it[0] }.joinToString()
+ val symbolParts = symbol.fixWhiteSpaces().split(" ")
- val friendlyName = if (name != symbol && !name.contains(symbol) && !nameShort.contains(symbol)) {
+ val friendlyName = if (name != symbol && !name.contains(symbol) && !name.containsAll(symbolParts) && !nameShort.contains(symbol)) {
classroom.getString("Symbol") + " " + classroom.getString("Name")
}
else {
@@ -38,7 +41,7 @@ class LibrusApiClassrooms(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_CLASSROOMS, 4*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_CLASSROOMS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiDescriptiveGradeCategories.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiDescriptiveGradeCategories.kt
new file mode 100644
index 00000000..94ce6972
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiDescriptiveGradeCategories.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import android.graphics.Color
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+
+class LibrusApiDescriptiveGradeCategories(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiDescriptiveGradeCategories"
+ }
+
+ init {
+ apiGet(TAG, "DescriptiveTextGrades/Skills") { json ->
+ json.getJsonArray("Skills")?.asJsonObjectList()?.forEach { category ->
+ val id = category.getLong("Id") ?: return@forEach
+ val name = category.getString("Name") ?: ""
+ val color = category.getJsonObject("Color")?.getInt("Id")
+ ?.let { data.getColor(it) } ?: Color.BLUE
+
+ val gradeCategoryObject = GradeCategory(
+ profileId,
+ id,
+ -1f,
+ color,
+ name
+ ).apply {
+ type = GradeCategory.TYPE_DESCRIPTIVE
+ }
+
+ data.gradeCategories.put(id, gradeCategoryObject)
+ }
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES, 1 * DAY)
+ onSuccess(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiDescriptiveGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiDescriptiveGrades.kt
new file mode 100644
index 00000000..8cc4f1c1
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiDescriptiveGrades.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+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_TEXT
+import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_TEXT
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+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 LibrusApiDescriptiveGrades(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiDescriptiveGrades"
+ }
+
+ init { data.profile?.also { profile ->
+ apiGet(TAG, "BaseTextGrades") { json ->
+
+ json.getJsonArray("Grades")?.asJsonObjectList()?.forEach { grade ->
+ val id = grade.getLong("Id") ?: return@forEach
+ val teacherId = grade.getJsonObject("AddedBy")?.getLong("Id") ?: return@forEach
+ val semester = grade.getInt("Semester") ?: return@forEach
+ val subjectId = grade.getJsonObject("Subject")?.getLong("Id") ?: return@forEach
+ val description = grade.getString("Grade")
+
+ val categoryId = grade.getJsonObject("Skill")?.getLong("Id")
+ ?: grade.getJsonObject("Category")?.getLong("Id")
+ ?: return@forEach
+ val type = when (grade.getJsonObject("Category")) {
+ null -> TYPE_DESCRIPTIVE_TEXT
+ else -> TYPE_TEXT
+ }
+
+ val category = data.gradeCategories.singleOrNull {
+ it.categoryId == categoryId && it.type == when (type) {
+ TYPE_DESCRIPTIVE_TEXT -> GradeCategory.TYPE_DESCRIPTIVE
+ else -> GradeCategory.TYPE_NORMAL
+ }
+ }
+
+ val addedDate = Date.fromIso(grade.getString("AddDate") ?: return@forEach)
+
+ val gradeObject = Grade(
+ profileId = profileId,
+ id = id,
+ name = " ",
+ type = type,
+ value = 0f,
+ weight = 0f,
+ color = category?.color ?: -1,
+ category = category?.text,
+ description = description,
+ comment = null,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ data.toRemove.addAll(listOf(
+ TYPE_DESCRIPTIVE_TEXT,
+ TYPE_TEXT
+ ).map {
+ DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
+ })
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES)
+ }
+ } ?: onSuccess(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt
index 48c479c1..331b8249 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEventTypes.kt
@@ -8,17 +8,19 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_EVENT_TYPES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.events.EventType
+import pl.szczodrzynski.edziennik.data.db.entity.EventType
class LibrusApiEventTypes(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiEventTypes"
}
init {
apiGet(TAG, "HomeWorks/Categories") { json ->
- val eventTypes = json.getJsonArray("Categories").asJsonObjectList()
+ val eventTypes = json.getJsonArray("Categories")?.asJsonObjectList()
eventTypes?.forEach { eventType ->
val id = eventType.getLong("Id") ?: return@forEach
@@ -29,7 +31,7 @@ class LibrusApiEventTypes(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_EVENT_TYPES, 4*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_EVENT_TYPES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt
index 7b87c462..7a76f88e 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiEvents.kt
@@ -10,14 +10,16 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_EVENTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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 pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiEvents(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiEvents"
}
@@ -28,13 +30,13 @@ class LibrusApiEvents(override val data: DataLibrus,
}
apiGet(TAG, "HomeWorks") { json ->
- val events = json.getJsonArray("HomeWorks").asJsonObjectList()
+ val events = json.getJsonArray("HomeWorks")?.asJsonObjectList()
events?.forEach { event ->
val id = event.getLong("Id") ?: return@forEach
val eventDate = Date.fromY_m_d(event.getString("Date"))
- val topic = event.getString("Content") ?: ""
- val type = event.getJsonObject("Category")?.getInt("Id") ?: -1
+ var topic = event.getString("Content")?.trim() ?: ""
+ val type = event.getJsonObject("Category")?.getLong("Id") ?: -1
val teacherId = event.getJsonObject("CreatedBy")?.getLong("Id") ?: -1
val subjectId = event.getJsonObject("Subject")?.getLong("Id") ?: -1
val teamId = event.getJsonObject("Class")?.getLong("Id") ?: -1
@@ -44,18 +46,24 @@ class LibrusApiEvents(override val data: DataLibrus,
val startTime = lessonRange?.startTime ?: Time.fromH_m(event.getString("TimeFrom"))
val addedDate = Date.fromIso(event.getString("AddDate"))
+ event.getJsonObject("onlineLessonUrl")?.let { onlineLesson ->
+ val text = onlineLesson.getString("text")?.let { "$it - " } ?: ""
+ val url = onlineLesson.getString("url")
+ topic += "\n\n$text$url"
+ }
+
val eventObject = Event(
- profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- type,
- false,
- teacherId,
- subjectId,
- teamId
+ profileId = profileId,
+ id = id,
+ date = eventDate,
+ time = startTime,
+ topic = topic,
+ color = null,
+ type = type,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ teamId = teamId,
+ addedDate = addedDate
)
data.eventList.add(eventObject)
@@ -65,15 +73,17 @@ class LibrusApiEvents(override val data: DataLibrus,
Metadata.TYPE_EVENT,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate
+ profile?.empty ?: false
))
}
- data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
+ data.toRemove.add(DataRemoveModel.Events.futureExceptTypes(listOf(
+ Event.TYPE_HOMEWORK,
+ Event.TYPE_PT_MEETING
+ )))
data.setSyncNext(ENDPOINT_LIBRUS_API_EVENTS, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_EVENTS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeCategories.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeCategories.kt
index 1e4b7151..518e643f 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeCategories.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeCategories.kt
@@ -9,11 +9,13 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
class LibrusApiGradeCategories(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiGradeCategories"
}
@@ -42,7 +44,7 @@ class LibrusApiGradeCategories(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeComments.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeComments.kt
index 05031612..971ac35b 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeComments.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGradeComments.kt
@@ -8,11 +8,13 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
class LibrusApiGradeComments(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiGradeComments"
}
@@ -38,7 +40,7 @@ class LibrusApiGradeComments(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt
index 9cd0b267..c2e2d0ce 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiGrades.kt
@@ -4,22 +4,32 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.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.Grade.Companion.TYPE_YEAR_FINAL
+import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date
class LibrusApiGrades(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiGrades"
}
- init {
+ init { data.profile?.also { profile ->
apiGet(TAG, "Grades") { json ->
- val grades = json.getJsonArray("Grades").asJsonObjectList()
+ val grades = json.getJsonArray("Grades")?.asJsonObjectList()
grades?.forEach { grade ->
val id = grade.getLong("Id") ?: return@forEach
@@ -30,19 +40,16 @@ class LibrusApiGrades(override val data: DataLibrus,
val subjectId = grade.getJsonObject("Subject")?.getLong("Id") ?: -1
val addedDate = Date.fromIso(grade.getString("AddDate"))
- val category = data.gradeCategories.singleOrNull { it.categoryId == categoryId }
- val categoryName = category?.text ?: ""
- val color = category?.color ?: -1
- var weight = category?.weight ?: 0f
- val value = Utils.getGradeValue(name)
-
-
- if (name == "-" || name == "+"
- || name.equals("np", ignoreCase = true)
- || name.equals("bz", ignoreCase = true)) {
- weight = 0f
+ val category = data.gradeCategories.singleOrNull {
+ it.categoryId == categoryId && it.type == GradeCategory.TYPE_NORMAL
}
+ val value = Utils.getGradeValue(name)
+ val weight = if (name == "-" || name == "+"
+ || name.equals("np", ignoreCase = true)
+ || name.equals("bz", ignoreCase = true)) 0f
+ else category?.weight ?: 0f
+
val description = grade.getJsonArray("Comments")?.asJsonObjectList()?.let { comments ->
if (comments.isNotEmpty()) {
data.gradeCategories.singleOrNull {
@@ -53,32 +60,29 @@ class LibrusApiGrades(override val data: DataLibrus,
} ?: ""
val gradeObject = Grade(
- profileId,
- id,
- categoryName,
- color,
- description,
- name,
- value,
- weight,
- semester,
- teacherId,
- subjectId
+ profileId = profileId,
+ id = id,
+ name = name,
+ type = when {
+ grade.getBoolean("IsConstituent") ?: false -> TYPE_NORMAL
+ grade.getBoolean("IsSemester") ?: false -> if (semester == 1) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER2_FINAL
+ grade.getBoolean("IsSemesterProposition") ?: false -> if (semester == 1) TYPE_SEMESTER1_PROPOSED else TYPE_SEMESTER2_PROPOSED
+ grade.getBoolean("IsFinal") ?: false -> TYPE_YEAR_FINAL
+ grade.getBoolean("IsFinalProposition") ?: false -> TYPE_YEAR_PROPOSED
+ else -> TYPE_NORMAL
+ },
+ value = value,
+ weight = weight,
+ color = category?.color ?: -1,
+ category = category?.text ?: "",
+ description = description,
+ comment = null,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ addedDate = addedDate
)
- when {
- grade.getBoolean("IsConstituent") ?: false ->
- gradeObject.type = Grade.TYPE_NORMAL
- grade.getBoolean("IsSemester") ?: false -> // semester final
- gradeObject.type = if (gradeObject.semester == 1) Grade.TYPE_SEMESTER1_FINAL else Grade.TYPE_SEMESTER2_FINAL
- grade.getBoolean("IsSemesterProposition") ?: false -> // semester proposed
- gradeObject.type = if (gradeObject.semester == 1) Grade.TYPE_SEMESTER1_PROPOSED else Grade.TYPE_SEMESTER2_PROPOSED
- grade.getBoolean("IsFinal") ?: false -> // year final
- gradeObject.type = Grade.TYPE_YEAR_FINAL
- grade.getBoolean("IsFinalProposition") ?: false -> // year final
- gradeObject.type = Grade.TYPE_YEAR_PROPOSED
- }
-
grade.getJsonObject("Improvement")?.also {
val historicalId = it.getLong("Id")
data.gradeList.firstOrNull { grade -> grade.id == historicalId }?.also { grade ->
@@ -94,14 +98,24 @@ class LibrusApiGrades(override val data: DataLibrus,
profileId,
Metadata.TYPE_GRADE,
id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate
+ profile.empty,
+ profile.empty
))
}
+ data.toRemove.addAll(listOf(
+ TYPE_NORMAL,
+ TYPE_SEMESTER1_FINAL,
+ TYPE_SEMESTER2_FINAL,
+ TYPE_SEMESTER1_PROPOSED,
+ TYPE_SEMESTER2_PROPOSED,
+ TYPE_YEAR_FINAL,
+ TYPE_YEAR_PROPOSED
+ ).map {
+ DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
+ })
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_NORMAL_GRADES)
}
- }
+ } ?: onSuccess(ENDPOINT_LIBRUS_API_NORMAL_GRADES) }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt
index 16bbac1c..c1183c19 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiHomework.kt
@@ -9,20 +9,22 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_HOMEWORK
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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 LibrusApiHomework(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiHomework"
}
init {
apiGet(TAG, "HomeWorkAssignments") { json ->
- val homeworkList = json.getJsonArray("HomeWorkAssignments").asJsonObjectList()
+ val homeworkList = json.getJsonArray("HomeWorkAssignments")?.asJsonObjectList()
homeworkList?.forEach { homework ->
val id = homework.getLong("Id") ?: return@forEach
@@ -32,17 +34,17 @@ class LibrusApiHomework(override val data: DataLibrus,
val addedDate = Date.fromY_m_d(homework.getString("Date"))
val eventObject = Event(
- profileId,
- id,
- eventDate,
- null,
- topic,
- -1,
- -1,
- false,
- teacherId,
- -1,
- -1
+ profileId = profileId,
+ id = id,
+ date = eventDate,
+ time = null,
+ topic = topic,
+ color = null,
+ type = -1,
+ teacherId = teacherId,
+ subjectId = -1,
+ teamId = -1,
+ addedDate = addedDate.inMillis
)
data.eventList.add(eventObject)
@@ -51,15 +53,14 @@ class LibrusApiHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate.inMillis
+ profile?.empty ?: false
))
}
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
data.setSyncNext(ENDPOINT_LIBRUS_API_HOMEWORK, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_HOMEWORK)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLessons.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLessons.kt
new file mode 100644
index 00000000..e32790c9
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLessons.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-1-6.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LESSONS
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+import pl.szczodrzynski.edziennik.data.db.entity.LibrusLesson
+
+class LibrusApiLessons(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiLessons"
+ }
+
+ init {
+ apiGet(TAG, "Lessons") { json ->
+ val lessons = json.getJsonArray("Lessons")?.asJsonObjectList()
+
+ lessons?.forEach { lesson ->
+ val id = lesson.getLong("Id") ?: return@forEach
+ val teacherId = lesson.getJsonObject("Teacher")?.getLong("Id") ?: return@forEach
+ val subjectId = lesson.getJsonObject("Subject")?.getLong("Id") ?: return@forEach
+ val teamId = lesson.getJsonObject("Class")?.getLong("Id")
+
+ val librusLesson = LibrusLesson(
+ profileId,
+ id,
+ teacherId,
+ subjectId,
+ teamId
+ )
+
+ data.librusLessons.put(id, librusLesson)
+ }
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_LESSONS, 4*DAY)
+ onSuccess(ENDPOINT_LIBRUS_API_LESSONS)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt
index a272a5dd..80e6e299 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiLuckyNumber.kt
@@ -4,28 +4,24 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
-import pl.szczodrzynski.edziennik.DAY
+import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LUCKY_NUMBER
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.getInt
-import pl.szczodrzynski.edziennik.getJsonObject
-import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiLuckyNumber(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiLuckyNumber"
}
init {
- data.profile?.luckyNumber = -1
- data.profile?.luckyNumberDate = null
-
var nextSync = System.currentTimeMillis() + 2*DAY*1000
apiGet(TAG, "LuckyNumbers") { json ->
@@ -37,14 +33,15 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
val luckyNumberDate = Date.fromY_m_d(luckyNumberEl.getString("LuckyNumberDay")) ?: Date.getToday()
val luckyNumber = luckyNumberEl.getInt("LuckyNumber") ?: -1
val luckyNumberObject = LuckyNumber(
- profileId,
- luckyNumberDate,
- luckyNumber
+ profileId = profileId,
+ date = luckyNumberDate,
+ number = luckyNumber
)
- //if (luckyNumberDate > Date.getToday()) {
+ if (luckyNumberDate >= Date.getToday())
nextSync = luckyNumberDate.combineWith(Time(15, 0, 0))
- //}
+ else
+ nextSync = System.currentTimeMillis() + 6*HOUR*1000
data.luckyNumberList.add(luckyNumberObject)
data.metadataList.add(
@@ -52,15 +49,14 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
profileId,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
- profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ true,
+ profile?.empty ?: false
))
}
}
data.setSyncNext(ENDPOINT_LIBRUS_API_LUCKY_NUMBER, syncAt = nextSync)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_LUCKY_NUMBER)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt
index c226cf58..9d5ce1d4 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiMe.kt
@@ -10,7 +10,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
class LibrusApiMe(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiMe"
}
@@ -24,7 +26,7 @@ class LibrusApiMe(override val data: DataLibrus,
data.isPremium = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
val isParent = account?.getInt("GroupId") == 5
- data.profile?.accountNameLong =
+ data.profile?.accountName =
if (isParent)
buildFullName(account?.getString("FirstName"), account?.getString("LastName"))
else null
@@ -33,7 +35,7 @@ class LibrusApiMe(override val data: DataLibrus,
buildFullName(user?.getString("FirstName"), user?.getString("LastName"))
data.setSyncNext(ENDPOINT_LIBRUS_API_ME, 2*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_ME)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt
index 14f251b6..55e753ee 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNoticeTypes.kt
@@ -8,17 +8,19 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NOTICE_TYPES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.notices.NoticeType
+import pl.szczodrzynski.edziennik.data.db.entity.NoticeType
class LibrusApiNoticeTypes(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiNoticeTypes"
}
init {
apiGet(TAG, "Notes/Categories") { json ->
- val noticeTypes = json.getJsonArray("Categories").asJsonObjectList()
+ val noticeTypes = json.getJsonArray("Categories")?.asJsonObjectList()
noticeTypes?.forEach { noticeType ->
val id = noticeType.getLong("Id") ?: return@forEach
@@ -28,7 +30,7 @@ class LibrusApiNoticeTypes(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_NOTICE_TYPES, 4*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_NOTICE_TYPES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt
index 7d2036ca..ba531afe 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiNotices.kt
@@ -9,13 +9,15 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NOTICES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice
+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
import pl.szczodrzynski.edziennik.utils.models.Date
class LibrusApiNotices(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiNotices"
}
@@ -26,7 +28,7 @@ class LibrusApiNotices(override val data: DataLibrus,
}
apiGet(TAG, "Notes") { json ->
- val notes = json.getJsonArray("Notes").asJsonObjectList()
+ val notes = json.getJsonArray("Notes")?.asJsonObjectList()
notes?.forEach { note ->
val id = note.getLong("Id") ?: return@forEach
@@ -44,12 +46,15 @@ class LibrusApiNotices(override val data: DataLibrus,
val semester = profile?.dateToSemester(addedDate) ?: 1
val noticeObject = Notice(
- profileId,
- id,
- categoryText+"\n"+text,
- semester,
- type,
- teacherId
+ profileId = profileId,
+ id = id,
+ type = type,
+ semester = semester,
+ text = text,
+ category = categoryText,
+ points = null,
+ teacherId = teacherId,
+ addedDate = addedDate.inMillis
)
data.noticeList.add(noticeObject)
@@ -59,13 +64,12 @@ class LibrusApiNotices(override val data: DataLibrus,
Metadata.TYPE_NOTICE,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate.inMillis
+ profile?.empty ?: false
))
}
data.setSyncNext(ENDPOINT_LIBRUS_API_NOTICES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_NOTICES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPointGradeCategories.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPointGradeCategories.kt
new file mode 100644
index 00000000..bba6ead9
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPointGradeCategories.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import android.graphics.Color
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+
+class LibrusApiPointGradeCategories(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiPointGradeCategories"
+ }
+
+ init {
+ apiGet(TAG, "PointGrades/Categories") { json ->
+ json.getJsonArray("Categories")?.asJsonObjectList()?.forEach { category ->
+ val id = category.getLong("Id") ?: return@forEach
+ val name = category.getString("Name") ?: ""
+ val color = category.getJsonObject("Color")?.getInt("Id")
+ ?.let { data.getColor(it) } ?: Color.BLUE
+ val countToAverage = category.getBoolean("CountToTheAverage") ?: true
+ val weight = if (countToAverage) category.getFloat("Weight") ?: 0f else 0f
+ val valueFrom = category.getFloat("ValueFrom") ?: 0f
+ val valueTo = category.getFloat("ValueTo") ?: 0f
+
+ val gradeCategoryObject = GradeCategory(
+ profileId,
+ id,
+ weight,
+ color,
+ name
+ ).apply {
+ type = GradeCategory.TYPE_POINT
+ setValueRange(valueFrom, valueTo)
+ }
+
+ data.gradeCategories.put(id, gradeCategoryObject)
+ }
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES, 1 * DAY)
+ onSuccess(ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPointGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPointGrades.kt
new file mode 100644
index 00000000..9da2c435
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPointGrades.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_POINT_GRADES
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+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_POINT_AVG
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+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 LibrusApiPointGrades(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiPointGrades"
+ }
+
+ init { data.profile?.also { profile ->
+ apiGet(TAG, "PointGrades") { json ->
+
+ json.getJsonArray("Grades")?.asJsonObjectList()?.forEach { grade ->
+ val id = grade.getLong("Id") ?: return@forEach
+ val teacherId = grade.getJsonObject("AddedBy")?.getLong("Id") ?: return@forEach
+ val semester = grade.getInt("Semester") ?: return@forEach
+ val subjectId = grade.getJsonObject("Subject")?.getLong("Id") ?: return@forEach
+ val name = grade.getString("Grade") ?: return@forEach
+ val value = grade.getFloat("GradeValue") ?: 0f
+
+ val categoryId = grade.getJsonObject("Category")?.getLong("Id") ?: return@forEach
+
+ val category = data.gradeCategories.singleOrNull {
+ it.categoryId == categoryId && it.type == GradeCategory.TYPE_POINT
+ }
+
+ val addedDate = Date.fromIso(grade.getString("AddDate") ?: return@forEach)
+
+ val gradeObject = Grade(
+ profileId = profileId,
+ id = id,
+ name = name,
+ type = TYPE_POINT_AVG,
+ value = value,
+ weight = category?.weight ?: 0f,
+ color = category?.color ?: -1,
+ category = category?.text ?: "",
+ description = null,
+ comment = null,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ addedDate = addedDate
+ ).apply {
+ valueMax = category?.valueTo ?: 0f
+ }
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Grades.semesterWithType(profile.currentSemester, TYPE_POINT_AVG))
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_POINT_GRADES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_LIBRUS_API_POINT_GRADES)
+ }
+ } ?: onSuccess(ENDPOINT_LIBRUS_API_POINT_GRADES) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt
index a2a3789a..6c0a9dd7 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPtMeetings.kt
@@ -8,20 +8,23 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_PT_MEETINGS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiPtMeetings(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiPtMeetings"
}
init {
apiGet(TAG, "ParentTeacherConferences") { json ->
- val ptMeetings = json.getJsonArray("ParentTeacherConferences").asJsonObjectList()
+ val ptMeetings = json.getJsonArray("ParentTeacherConferences")?.asJsonObjectList()
ptMeetings?.forEach { meeting ->
val id = meeting.getLong("Id") ?: return@forEach
@@ -36,17 +39,16 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
}
val eventObject = Event(
- profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- Event.TYPE_PT_MEETING,
- false,
- teacherId,
- -1,
- data.teamClass?.id ?: -1
+ profileId = profileId,
+ id = id,
+ date = eventDate,
+ time = startTime,
+ topic = topic,
+ color = null,
+ type = Event.TYPE_PT_MEETING,
+ teacherId = teacherId,
+ subjectId = -1,
+ teamId = data.teamClass?.id ?: -1
)
data.eventList.add(eventObject)
@@ -56,13 +58,14 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
Metadata.TYPE_EVENT,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ profile?.empty ?: false
))
}
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_PT_MEETING))
+
data.setSyncNext(ENDPOINT_LIBRUS_API_PT_MEETINGS, 12*HOUR)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_PT_MEETINGS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPushConfig.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPushConfig.kt
new file mode 100644
index 00000000..9073d03f
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiPushConfig.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-2-21.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import pl.szczodrzynski.edziennik.JsonObject
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_PUSH_CONFIG
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.getInt
+import pl.szczodrzynski.edziennik.getJsonObject
+
+class LibrusApiPushConfig(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiPushConfig"
+ }
+
+ init { data.app.config.sync.tokenLibrus?.also { tokenLibrus ->
+ if(tokenLibrus.isEmpty()) {
+ data.setSyncNext(ENDPOINT_LIBRUS_API_PUSH_CONFIG, SYNC_ALWAYS)
+ data.app.config.sync.tokenLibrusList =
+ data.app.config.sync.tokenLibrusList + profileId
+ onSuccess(ENDPOINT_LIBRUS_API_PUSH_CONFIG)
+ return@also
+ }
+
+ apiGet(TAG, "ChangeRegister", payload = JsonObject(
+ "provider" to "FCM",
+ "device" to tokenLibrus,
+ "sendPush" to "1",
+ "appVersion" to 4
+ )) { json ->
+ json.getJsonObject("ChangeRegister")?.getInt("Id")?.let { data.pushDeviceId = it }
+
+ // sync always: this endpoint has .shouldSync set
+ data.setSyncNext(ENDPOINT_LIBRUS_API_PUSH_CONFIG, SYNC_ALWAYS)
+ data.app.config.sync.tokenLibrusList =
+ data.app.config.sync.tokenLibrusList + profileId
+ onSuccess(ENDPOINT_LIBRUS_API_PUSH_CONFIG)
+ }
+ } ?: onSuccess(ENDPOINT_LIBRUS_API_PUSH_CONFIG) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSchools.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSchools.kt
index aff6f569..d405f9bf 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSchools.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSchools.kt
@@ -8,12 +8,14 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_SCHOOLS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
+import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
import pl.szczodrzynski.edziennik.utils.models.Time
import java.util.*
class LibrusApiSchools(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiSchools"
}
@@ -26,12 +28,7 @@ class LibrusApiSchools(override val data: DataLibrus,
// create the school's short name using first letters of each long name's word
// append the town name and save to student data
- var schoolNameShort = ""
- schoolNameLong?.split(" ")?.forEach {
- if (it.isBlank())
- return@forEach
- schoolNameShort += it[0].toLowerCase()
- }
+ val schoolNameShort = schoolNameLong?.firstLettersName
val schoolTown = school?.getString("Town")?.toLowerCase(Locale.getDefault())
data.schoolName = schoolId.toString() + schoolNameShort + "_" + schoolTown
@@ -53,7 +50,7 @@ class LibrusApiSchools(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_SCHOOLS, 4 * DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_SCHOOLS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt
index 4c383933..cfd9bd31 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiSubjects.kt
@@ -8,17 +8,19 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_SUBJECTS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
+import pl.szczodrzynski.edziennik.data.db.entity.Subject
class LibrusApiSubjects(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiSubjects"
}
init {
apiGet(TAG, "Subjects") { json ->
- val subjects = json.getJsonArray("Subjects").asJsonObjectList()
+ val subjects = json.getJsonArray("Subjects")?.asJsonObjectList()
subjects?.forEach { subject ->
val id = subject.getLong("Id") ?: return@forEach
@@ -31,7 +33,7 @@ class LibrusApiSubjects(override val data: DataLibrus,
data.subjectList.put(1, Subject(profileId, 1, "Zachowanie", "zach"))
data.setSyncNext(ENDPOINT_LIBRUS_API_SUBJECTS, 4*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_SUBJECTS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt
index 88c8ce14..e09504bf 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDayTypes.kt
@@ -8,17 +8,19 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.TeacherAbsenceType
+import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsenceType
class LibrusApiTeacherFreeDayTypes(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiTeacherFreeDayTypes"
}
init {
apiGet(TAG, "TeacherFreeDays/Types") { json ->
- val teacherAbsenceTypes = json.getJsonArray("Types").asJsonObjectList()
+ val teacherAbsenceTypes = json.getJsonArray("Types")?.asJsonObjectList()
teacherAbsenceTypes?.forEach { teacherAbsenceType ->
val id = teacherAbsenceType.getLong("Id") ?: return@forEach
@@ -34,7 +36,7 @@ class LibrusApiTeacherFreeDayTypes(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES, 7 * DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt
index 1069ffa3..973ada46 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTeacherFreeDays.kt
@@ -10,13 +10,15 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.TeacherAbsence
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsence
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiTeacherFreeDays(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiTeacherFreeDays"
}
@@ -27,7 +29,7 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
}
apiGet(TAG, "TeacherFreeDays") { json ->
- val teacherAbsences = json.getJsonArray("TeacherFreeDays").asJsonObjectList()
+ val teacherAbsences = json.getJsonArray("TeacherFreeDays")?.asJsonObjectList()
teacherAbsences?.forEach { teacherAbsence ->
val id = teacherAbsence.getLong("Id") ?: return@forEach
@@ -41,15 +43,15 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
val timeTo = teacherAbsence.getString("TimeTo")?.let { Time.fromH_m_s(it) }
val teacherAbsenceObject = TeacherAbsence(
- profileId,
- id,
- teacherId,
- type,
- name,
- dateFrom,
- dateTo,
- timeFrom,
- timeTo
+ profileId = profileId,
+ id = id,
+ type = type,
+ name = name,
+ dateFrom = dateFrom,
+ dateTo = dateTo,
+ timeFrom = timeFrom,
+ timeTo = timeTo,
+ teacherId = teacherId
)
data.teacherAbsenceList.add(teacherAbsenceObject)
@@ -57,14 +59,13 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
profileId,
Metadata.TYPE_TEACHER_ABSENCE,
id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ true,
+ profile?.empty ?: false
))
}
data.setSyncNext(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS, 6*HOUR, DRAWER_ITEM_AGENDA)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTemplate.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTemplate.kt
index 3b111f0c..9fd6afee 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTemplate.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTemplate.kt
@@ -8,7 +8,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
class LibrusApiTemplate(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApi"
}
@@ -17,7 +19,7 @@ class LibrusApiTemplate(override val data: DataLibrus,
/*apiGet(TAG, "") { json ->
data.setSyncNext(ENDPOINT_LIBRUS_API_, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_)
}*/
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTextGradeCategories.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTextGradeCategories.kt
new file mode 100644
index 00000000..45b6b069
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTextGradeCategories.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import android.graphics.Color
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
+
+class LibrusApiTextGradeCategories(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiTextGradeCategories"
+ }
+
+ init {
+ apiGet(TAG, "TextGrades/Categories") { json ->
+ json.getJsonArray("Categories")?.asJsonObjectList()?.forEach { category ->
+ val id = category.getLong("Id") ?: return@forEach
+ val name = category.getString("Name") ?: ""
+ val color = category.getJsonObject("Color")?.getInt("Id")
+ ?.let { data.getColor(it) } ?: Color.BLUE
+
+ val gradeCategoryObject = GradeCategory(
+ profileId,
+ id,
+ -1f,
+ color,
+ name
+ ).apply {
+ type = GradeCategory.TYPE_TEXT
+ }
+
+ data.gradeCategories.put(id, gradeCategoryObject)
+ }
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES, 1 * DAY)
+ onSuccess(ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTextGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTextGrades.kt
new file mode 100644
index 00000000..7b7c8c6f
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTextGrades.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-29
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
+
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEXT_GRADES
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
+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.GradeCategory
+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 LibrusApiTextGrades(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusApiTextGrades"
+ }
+
+ init { data.profile?.also { profile ->
+ apiGet(TAG, "DescriptiveGrades") { json ->
+
+ json.getJsonArray("Grades")?.asJsonObjectList()?.forEach { grade ->
+ val id = grade.getLong("Id") ?: return@forEach
+ val teacherId = grade.getJsonObject("AddedBy")?.getLong("Id") ?: return@forEach
+ val semester = grade.getInt("Semester") ?: return@forEach
+ val subjectId = grade.getJsonObject("Subject")?.getLong("Id") ?: return@forEach
+
+ val map = grade.getString("Map")
+ val realValue = grade.getString("RealGradeValue")
+
+ val name = map ?: realValue ?: return@forEach
+ val description = if (map != null && map != realValue) realValue ?: "" else ""
+
+ val categoryId = grade.getJsonObject("Skill")?.getLong("Id") ?: return@forEach
+
+ val category = data.gradeCategories.singleOrNull {
+ it.categoryId == categoryId && it.type == GradeCategory.TYPE_DESCRIPTIVE
+ }
+
+ val addedDate = Date.fromIso(grade.getString("AddDate") ?: return@forEach)
+
+ val gradeObject = Grade(
+ profileId = profileId,
+ id = id,
+ name = name,
+ type = TYPE_DESCRIPTIVE,
+ value = 0f,
+ weight = 0f,
+ color = category?.color ?: -1,
+ category = category?.text ?: "",
+ description = description,
+ comment = grade.getString("Phrase") /* whatever it is */,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Grades.semesterWithType(profile.currentSemester, TYPE_DESCRIPTIVE))
+
+ data.setSyncNext(ENDPOINT_LIBRUS_API_TEXT_GRADES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_LIBRUS_API_TEXT_GRADES)
+ }
+ } ?: onSuccess(ENDPOINT_LIBRUS_API_TEXT_GRADES) }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTimetables.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTimetables.kt
index ce2af163..9a463a6b 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTimetables.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiTimetables.kt
@@ -11,16 +11,18 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TIMETABLES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
+import pl.szczodrzynski.edziennik.data.db.entity.Lesson
+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 LibrusApiTimetables(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiTimetables"
}
@@ -60,7 +62,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
}
if (day.isNullOrEmpty() || !lessonsFound) {
- data.lessonNewList.add(Lesson(profileId, lessonDate.value.toLong()).apply {
+ data.lessonList.add(Lesson(profileId, lessonDate.value.toLong()).apply {
type = Lesson.TYPE_NO_LESSONS
date = lessonDate
})
@@ -69,9 +71,11 @@ class LibrusApiTimetables(override val data: DataLibrus,
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
+ if (data.timetableNotPublic) data.timetableNotPublic = false
+
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
data.setSyncNext(ENDPOINT_LIBRUS_API_TIMETABLES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_TIMETABLES)
}
}
@@ -194,10 +198,9 @@ class LibrusApiTimetables(override val data: DataLibrus,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
- data.lessonNewList.add(lessonObject)
+ data.lessonList.add(lessonObject)
}}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt
index be4b0087..791283ed 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUnits.kt
@@ -10,7 +10,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
class LibrusApiUnits(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiUnits"
}
@@ -18,12 +20,12 @@ class LibrusApiUnits(override val data: DataLibrus,
init { run {
if (data.unitId == 0L) {
data.setSyncNext(ENDPOINT_LIBRUS_API_UNITS, 12 * DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_UNITS)
return@run
}
apiGet(TAG, "Units") { json ->
- val units = json.getJsonArray("Units").asJsonObjectList()
+ val units = json.getJsonArray("Units")?.asJsonObjectList()
units?.singleOrNull { it.getLong("Id") == data.unitId }?.also { unit ->
val startPoints = unit.getJsonObject("BehaviourGradesSettings")?.getJsonObject("StartPoints")
@@ -38,7 +40,7 @@ class LibrusApiUnits(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_UNITS, 7 * DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_UNITS)
}
}}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt
index 71c18864..0ac9a5ea 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiUsers.kt
@@ -8,28 +8,37 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_USERS
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
class LibrusApiUsers(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiUsers"
}
init {
apiGet(TAG, "Users") { json ->
- val users = json.getJsonArray("Users").asJsonObjectList()
+ val users = json.getJsonArray("Users")?.asJsonObjectList()
users?.forEach { user ->
val id = user.getLong("Id") ?: return@forEach
val firstName = user.getString("FirstName")?.fixName() ?: ""
val lastName = user.getString("LastName")?.fixName() ?: ""
- data.teacherList.put(id, Teacher(profileId, id, firstName, lastName))
+ val teacher = Teacher(profileId, id, firstName, lastName)
+
+ if (user.getBoolean("IsSchoolAdministrator") == true)
+ teacher.setTeacherType(Teacher.TYPE_SCHOOL_ADMIN)
+ if (user.getBoolean("IsPedagogue") == true)
+ teacher.setTeacherType(Teacher.TYPE_PEDAGOGUE)
+
+ data.teacherList.put(id, teacher)
}
data.setSyncNext(ENDPOINT_LIBRUS_API_USERS, 4*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_USERS)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt
index e8249978..9937f808 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiVirtualClasses.kt
@@ -8,17 +8,19 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
-import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
+import pl.szczodrzynski.edziennik.data.db.entity.Team
class LibrusApiVirtualClasses(override val data: DataLibrus,
- val onSuccess: () -> Unit) : LibrusApi(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusApi(data, lastSync) {
companion object {
const val TAG = "LibrusApiVirtualClasses"
}
init {
apiGet(TAG, "VirtualClasses") { json ->
- val virtualClasses = json.getJsonArray("VirtualClasses").asJsonObjectList()
+ val virtualClasses = json.getJsonArray("VirtualClasses")?.asJsonObjectList()
virtualClasses?.forEach { virtualClass ->
val id = virtualClass.getLong("Id") ?: return@forEach
@@ -30,7 +32,7 @@ class LibrusApiVirtualClasses(override val data: DataLibrus,
}
data.setSyncNext(ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES, 4*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetAttachment.kt
index ed447ea8..b54e704b 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetAttachment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetAttachment.kt
@@ -4,27 +4,20 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages
-import kotlinx.coroutines.*
-import org.greenrobot.eventbus.EventBus
-import pl.szczodrzynski.edziennik.data.api.ERROR_FILE_DOWNLOAD
-import pl.szczodrzynski.edziennik.data.api.EXCEPTION_LIBRUS_MESSAGES_REQUEST
-import pl.szczodrzynski.edziennik.data.api.Regexes
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
-import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
-import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent.Companion.TYPE_FINISHED
-import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent.Companion.TYPE_PROGRESS
-import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.get
-import pl.szczodrzynski.edziennik.getString
-import pl.szczodrzynski.edziennik.utils.Utils
-import java.io.File
+import pl.szczodrzynski.edziennik.data.db.entity.Message
import kotlin.coroutines.CoroutineContext
-class LibrusMessagesGetAttachment(
- override val data: DataLibrus, val message: Message, val attachmentId: Long,
- val attachmentName: String, val onSuccess: () -> Unit) : LibrusMessages(data), CoroutineScope {
+class LibrusMessagesGetAttachment(override val data: DataLibrus,
+ val message: Message,
+ val attachmentId: Long,
+ val attachmentName: String,
+ val onSuccess: () -> Unit
+) : LibrusMessages(data, null), CoroutineScope {
companion object {
const val TAG = "LibrusMessagesGetAttachment"
}
@@ -34,8 +27,6 @@ class LibrusMessagesGetAttachment(
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
- private var getAttachmentCheckKeyTries = 0
-
init {
messagesGet(TAG, "GetFileDownloadLink", parameters = mapOf(
"fileId" to attachmentId,
@@ -43,81 +34,8 @@ class LibrusMessagesGetAttachment(
"archive" to 0
)) { doc ->
val downloadLink = doc.select("response GetFileDownloadLink downloadLink").text()
- val keyMatcher = Regexes.LIBRUS_ATTACHMENT_KEY.find(downloadLink)
- if (keyMatcher != null) {
- getAttachmentCheckKeyTries = 0
-
- val attachmentKey = keyMatcher[1]
- getAttachmentCheckKey(attachmentKey) {
- downloadAttachment(attachmentKey)
- }
- } else {
- data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
- .withApiResponse(doc.toString()))
- }
- }
- }
-
- private fun getAttachmentCheckKey(attachmentKey: String, callback: () -> Unit) {
- sandboxGet(TAG, "CSCheckKey",
- parameters = mapOf("singleUseKey" to attachmentKey)) { json ->
-
- when (json.getString("status")) {
- "not_downloaded_yet" -> {
- if (getAttachmentCheckKeyTries++ > 5) {
- data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
- .withApiResponse(json))
- return@sandboxGet
- }
- launch {
- delay(2000)
- getAttachmentCheckKey(attachmentKey, callback)
- }
- }
-
- "ready" -> {
- launch { callback() }
- }
-
- else -> {
- data.error(ApiError(TAG, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
- .withApiResponse(json))
- }
- }
- }
- }
-
- private fun downloadAttachment(attachmentKey: String) {
- val targetFile = File(Utils.getStorageDir(), attachmentName)
-
- sandboxGetFile(TAG, "CSDownload&singleUseKey=$attachmentKey", targetFile, { file ->
-
- val event = AttachmentGetEvent(
- profileId,
- message.id,
- attachmentId,
- TYPE_FINISHED,
- file.absolutePath
- )
-
- val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
- Utils.writeStringToFile(attachmentDataFile, event.fileName)
-
- EventBus.getDefault().post(event)
-
- onSuccess()
-
- }) { written, _ ->
- val event = AttachmentGetEvent(
- profileId,
- message.id,
- attachmentId,
- TYPE_PROGRESS,
- bytesWritten = written
- )
-
- EventBus.getDefault().post(event)
+ LibrusSandboxDownloadAttachment(data, downloadLink, message, attachmentId, attachmentName, onSuccess)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt
index 373fab34..9f962bf9 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt
@@ -11,18 +11,19 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESSAGES_RECEIVED
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESSAGES_SENT
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
+import pl.szczodrzynski.edziennik.data.db.entity.*
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
+import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date
-class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int = TYPE_RECEIVED,
- archived: Boolean = false, val onSuccess: () -> Unit) : LibrusMessages(data) {
+class LibrusMessagesGetList(override val data: DataLibrus,
+ override val lastSync: Long?,
+ private val type: Int = TYPE_RECEIVED,
+ archived: Boolean = false,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusMessages(data, lastSync) {
companion object {
const val TAG = "LibrusMessagesGetList"
}
@@ -33,6 +34,10 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
Message.TYPE_SENT -> "Outbox/action/GetList"
else -> null
}
+ val endpointId = when (type) {
+ TYPE_RECEIVED -> ENDPOINT_LIBRUS_MESSAGES_RECEIVED
+ else -> ENDPOINT_LIBRUS_MESSAGES_SENT
+ }
if (endpoint != null) {
messagesGet(TAG, endpoint, parameters = mapOf(
@@ -51,12 +56,12 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
val recipientFirstName = element.select(when (type) {
TYPE_RECEIVED -> "senderFirstName"
else -> "receiverFirstName"
- }).text().trim()
+ }).text().fixName()
val recipientLastName = element.select(when (type) {
TYPE_RECEIVED -> "senderLastName"
else -> "receiverLastName"
- }).text().trim()
+ }).text().fixName()
val recipientId = data.teacherList.singleOrNull {
it.name == recipientFirstName && it.surname == recipientLastName
@@ -73,7 +78,7 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
val senderId = when (type) {
TYPE_RECEIVED -> recipientId
- else -> -1
+ else -> null
}
val receiverId = when (type) {
@@ -87,13 +92,13 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
}
val messageObject = Message(
- profileId,
- id,
- subject,
- null,
- type,
- senderId,
- -1
+ profileId = profileId,
+ id = id,
+ type = type,
+ subject = subject,
+ body = null,
+ senderId = senderId,
+ addedDate = sentDate
)
val messageRecipientObject = MessageRecipient(
@@ -104,15 +109,19 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
id
)
- data.messageIgnoreList.add(messageObject)
+ element.select("isAnyFileAttached")?.text()?.let {
+ if (it == "1")
+ messageObject.hasAttachments = true
+ }
+
+ data.messageList.add(messageObject)
data.messageRecipientList.add(messageRecipientObject)
- data.metadataList.add(Metadata(
+ data.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
notified,
- notified,
- sentDate
+ notified
))
}
@@ -120,11 +129,11 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)
}
- onSuccess()
+ onSuccess(endpointId)
}
} else {
data.error(TAG, ERROR_NOT_IMPLEMENTED)
- onSuccess()
+ onSuccess(endpointId)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt
index 27c21be8..49ee0d52 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt
@@ -9,21 +9,23 @@ import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.entity.Teacher
+import pl.szczodrzynski.edziennik.data.db.full.MessageFull
+import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
import pl.szczodrzynski.edziennik.fixName
+import pl.szczodrzynski.edziennik.isNotNullNorEmpty
+import pl.szczodrzynski.edziennik.notEmptyOrNull
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
import java.nio.charset.Charset
-class LibrusMessagesGetMessage(
- override val data: DataLibrus,
- private val messageObject: MessageFull,
- val onSuccess: () -> Unit
-) : LibrusMessages(data) {
+class LibrusMessagesGetMessage(override val data: DataLibrus,
+ private val messageObject: MessageFull,
+ val onSuccess: () -> Unit
+) : LibrusMessages(data, null) {
companion object {
const val TAG = "LibrusMessagesGetMessage"
}
@@ -56,24 +58,57 @@ class LibrusMessagesGetMessage(
when (messageObject.type) {
TYPE_RECEIVED -> {
- val senderLoginId = message.select("senderId").text()
- data.teacherList.singleOrNull { it.id == messageObject.senderId }?.loginId = senderLoginId
+ val senderLoginId = message.select("senderId").text().notEmptyOrNull()
+ val senderGroupId = message.select("senderGroupId").text().toIntOrNull()
+ val userClass = message.select("userClass").text().notEmptyOrNull()
+ data.teacherList.singleOrNull { it.id == messageObject.senderId }?.apply {
+ loginId = senderLoginId
+ setTeacherType(when (senderGroupId) {
+ /* https://api.librus.pl/2.0/Messages/Role */
+ 0, 1, 99 -> Teacher.TYPE_SUPER_ADMIN
+ 2 -> Teacher.TYPE_SCHOOL_ADMIN
+ 3 -> Teacher.TYPE_PRINCIPAL
+ 4 -> Teacher.TYPE_TEACHER
+ 5, 9 -> {
+ if (typeDescription == null)
+ typeDescription = userClass
+ Teacher.TYPE_PARENT
+ }
+ 7 -> Teacher.TYPE_SECRETARIAT
+ 8 -> {
+ if (typeDescription == null)
+ typeDescription = userClass
+ Teacher.TYPE_STUDENT
+ }
+ 10 -> Teacher.TYPE_PEDAGOGUE
+ 11 -> Teacher.TYPE_LIBRARIAN
+ 12 -> Teacher.TYPE_SPECIALIST
+ 21 -> {
+ typeDescription = "Jednostka Nadrzędna"
+ Teacher.TYPE_OTHER
+ }
+ 50 -> {
+ typeDescription = "Jednostka Samorządu Terytorialnego"
+ Teacher.TYPE_OTHER
+ }
+ else -> Teacher.TYPE_OTHER
+ })
+ }
val readDateText = message.select("readDate").text()
- val readDate = when (readDateText.isNotEmpty()) {
+ val readDate = when (readDateText.isNotNullNorEmpty()) {
true -> Date.fromIso(readDateText)
else -> 0
}
val messageRecipientObject = MessageRecipientFull(
- profileId,
- -1,
- -1,
- readDate,
- messageObject.id
+ profileId = profileId,
+ id = -1,
+ messageId = messageObject.id,
+ readDate = readDate
)
- messageRecipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong
+ messageRecipientObject.fullName = profile.accountName ?: profile.studentNameLong ?: ""
messageRecipientList.add(messageRecipientObject)
}
@@ -90,17 +125,16 @@ class LibrusMessagesGetMessage(
teacher?.loginId = receiverLoginId
val readDateText = message.select("readed").text()
- val readDate = when (readDateText.isNotEmpty()) {
+ val readDate = when (readDateText.isNotNullNorEmpty()) {
true -> Date.fromIso(readDateText)
else -> 0
}
val messageRecipientObject = MessageRecipientFull(
- profileId,
- receiverId,
- -1,
- readDate,
- messageObject.id
+ profileId = profileId,
+ id = receiverId,
+ messageId = messageObject.id,
+ readDate = readDate
)
messageRecipientObject.fullName = "$receiverFirstName $receiverLastName"
@@ -111,19 +145,20 @@ class LibrusMessagesGetMessage(
}
if (!messageObject.seen) {
- data.messageMetadataList.add(Metadata(
+ data.setSeenMetadataList.add(Metadata(
messageObject.profileId,
Metadata.TYPE_MESSAGE,
messageObject.id,
true,
- true,
- messageObject.addedDate
+ true
))
}
messageObject.recipients = messageRecipientList
data.messageRecipientList.addAll(messageRecipientList)
+
data.messageList.add(messageObject)
+ data.messageListReplace = true
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
onSuccess()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetRecipientList.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetRecipientList.kt
new file mode 100644
index 00000000..053258d8
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetRecipientList.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2019-12-31.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages
+
+import androidx.core.util.set
+import androidx.room.OnConflictStrategy
+import com.google.gson.JsonArray
+import com.google.gson.JsonObject
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
+import pl.szczodrzynski.edziennik.data.api.events.RecipientListGetEvent
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
+
+class LibrusMessagesGetRecipientList(override val data: DataLibrus,
+ val onSuccess: () -> Unit
+) : LibrusMessages(data, null) {
+ companion object {
+ private const val TAG = "LibrusMessagesGetRecipientList"
+ }
+
+ private val listTypes = mutableListOf>()
+
+ init {
+ messagesGet(TAG, "Receivers/action/GetTypes", parameters = mapOf(
+ "includeClass" to 1
+ )) { doc ->
+ doc.select("response GetTypes data list ArrayItem")?.forEach {
+ val id = it.getElementsByTag("id")?.firstOrNull()?.ownText() ?: return@forEach
+ val name = it.getElementsByTag("name")?.firstOrNull()?.ownText() ?: return@forEach
+ listTypes += id to name
+ }
+
+ getLists()
+ }
+ }
+
+ private fun getLists() {
+ if (listTypes.isEmpty()) {
+ finish()
+ return
+ }
+ val type = listTypes.removeAt(0)
+ if (type.first == "contactsGroups") {
+ getLists()
+ return
+ }
+ messagesGetJson(TAG, "Receivers/action/GetListForType", parameters = mapOf(
+ "receiverType" to type.first
+ )) { json ->
+ val dataEl = json?.getJsonObject("response")?.getJsonObject("GetListForType")?.get("data")
+ if (dataEl is JsonObject) {
+ val listEl = dataEl.get("ArrayItem")
+ if (listEl is JsonArray) {
+ listEl.asJsonObjectList()?.forEach { item ->
+ processElement(item, type.first, type.second)
+ }
+ }
+ if (listEl is JsonObject) {
+ processElement(listEl, type.first, type.second)
+ }
+ }
+
+ getLists()
+ }
+ }
+
+ private fun processElement(element: JsonObject, typeId: String, typeName: String, listName: String? = null) {
+ val listEl = element.getJsonObject("list")?.get("ArrayItem")
+ if (listEl is JsonArray) {
+ listEl.asJsonObjectList()?.let { list ->
+ val label = element.getString("label") ?: ""
+ list.forEach { item ->
+ processElement(item, typeId, typeName, label)
+ }
+ return
+ }
+ }
+ if (listEl is JsonObject) {
+ val label = element.getString("label") ?: ""
+ processElement(listEl, typeId, typeName, label)
+ return
+ }
+ processRecipient(element, typeId, typeName, listName)
+ }
+
+ private fun processRecipient(recipient: JsonObject, typeId: String, typeName: String, listName: String? = null) {
+ val id = recipient.getLong("id") ?: return
+ val label = recipient.getString("label") ?: return
+
+ val fullNameLastFirst: String
+ val description: String?
+ if (typeId == "parentsCouncil" || typeId == "schoolParentsCouncil") {
+ val delimiterIndex = label.lastIndexOf(" - ")
+ if (delimiterIndex == -1) {
+ fullNameLastFirst = label.fixName()
+ description = null
+ }
+ else {
+ fullNameLastFirst = label.substring(0, delimiterIndex).fixName()
+ description = label.substring(delimiterIndex+3)
+ }
+ }
+ else {
+ fullNameLastFirst = label.fixName()
+ description = null
+ }
+
+ var typeDescription: String? = null
+ val type = when (typeId) {
+ "tutors" -> Teacher.TYPE_EDUCATOR
+ "teachers" -> Teacher.TYPE_TEACHER
+ "classParents" -> Teacher.TYPE_PARENT
+ "guardians" -> Teacher.TYPE_PARENT
+ "parentsCouncil" -> {
+ typeDescription = joinNotNullStrings(": ", listName, description)
+ Teacher.TYPE_PARENTS_COUNCIL
+ }
+ "schoolParentsCouncil" -> {
+ typeDescription = joinNotNullStrings(": ", listName, description)
+ Teacher.TYPE_SCHOOL_PARENTS_COUNCIL
+ }
+ "pedagogue" -> Teacher.TYPE_PEDAGOGUE
+ "librarian" -> Teacher.TYPE_LIBRARIAN
+ "admin" -> Teacher.TYPE_SCHOOL_ADMIN
+ "secretary" -> Teacher.TYPE_SECRETARIAT
+ "sadmin" -> Teacher.TYPE_SUPER_ADMIN
+ else -> {
+ typeDescription = typeName
+ Teacher.TYPE_OTHER
+ }
+ }
+
+ // get teacher by fullName AND type or create it
+ val teacher = data.teacherList.singleOrNull {
+ it.fullNameLastFirst == fullNameLastFirst && ((type != Teacher.TYPE_SCHOOL_ADMIN && type != Teacher.TYPE_PEDAGOGUE) || it.isType(type))
+ } ?: Teacher(data.profileId, id).apply {
+ if (typeId == "sadmin" && id == 2L) {
+ name = "Pomoc"
+ surname = "Techniczna LIBRUS"
+ }
+ else {
+ name = fullNameLastFirst
+ fullNameLastFirst.splitName()?.let {
+ name = it.second
+ surname = it.first
+ }
+ }
+ data.teacherList[id] = this
+ }
+
+ teacher.apply {
+ this.loginId = id.toString()
+ this.setTeacherType(type)
+ if (this.typeDescription.isNullOrBlank())
+ this.typeDescription = typeDescription
+ }
+ }
+
+ private fun finish() {
+ 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/librus/data/messages/LibrusMessagesSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt
new file mode 100644
index 00000000..d568135e
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-1-2.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.base64Encode
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
+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
+import pl.szczodrzynski.edziennik.getJsonObject
+import pl.szczodrzynski.edziennik.getLong
+import pl.szczodrzynski.edziennik.getString
+
+class LibrusMessagesSendMessage(override val data: DataLibrus,
+ val recipients: List,
+ val subject: String,
+ val text: String,
+ val onSuccess: () -> Unit
+) : LibrusMessages(data, null) {
+ companion object {
+ const val TAG = "LibrusMessages"
+ }
+
+ init {
+ val params = mapOf(
+ "topic" to subject.base64Encode(),
+ "message" to text.base64Encode(),
+ "receivers" to recipients
+ .filter { it.loginId != null }
+ .joinToString(",") { it.loginId ?: "" },
+ "actions" to " ".base64Encode()
+ )
+
+ messagesGetJson(TAG, "SendMessage", parameters = params) { json ->
+
+ val response = json.getJsonObject("response").getJsonObject("SendMessage")
+ val id = response.getLong("data")
+
+ if (response.getString("status") != "ok" || id == null) {
+ val message = response.getString("message")
+ // TODO error
+ return@messagesGetJson
+ }
+
+ LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = null) {
+ val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id }
+ 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/librus/data/messages/LibrusMessagesTemplate.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesTemplate.kt
index 797bb2ca..6115e136 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesTemplate.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesTemplate.kt
@@ -7,7 +7,9 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
-class LibrusMessagesTemplate(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusMessages(data) {
+class LibrusMessagesTemplate(override val data: DataLibrus,
+ val onSuccess: () -> Unit
+) : LibrusMessages(data, null) {
companion object {
const val TAG = "LibrusMessages"
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusSandboxDownloadAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusSandboxDownloadAttachment.kt
new file mode 100644
index 00000000..567071aa
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusSandboxDownloadAttachment.kt
@@ -0,0 +1,117 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages
+
+import kotlinx.coroutines.*
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages
+import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.Utils
+import java.io.File
+import kotlin.coroutines.CoroutineContext
+
+class LibrusSandboxDownloadAttachment(override val data: DataLibrus,
+ downloadLink: String,
+ val owner: Any,
+ val attachmentId: Long,
+ val attachmentName: String,
+ val onSuccess: () -> Unit
+) : LibrusMessages(data, null), CoroutineScope {
+ companion object {
+ const val TAG = "LibrusSandboxDownloadAttachment"
+ }
+
+ private var job = Job()
+
+ override val coroutineContext: CoroutineContext
+ get() = job + Dispatchers.Default
+
+ private var getAttachmentCheckKeyTries = 0
+
+ init {
+ val keyMatcher = Regexes.LIBRUS_ATTACHMENT_KEY.find(downloadLink)
+
+ when {
+ downloadLink.contains("CSDownloadFailed") -> {
+ data.error(ApiError(TAG, ERROR_LIBRUS_MESSAGES_ATTACHMENT_NOT_FOUND))
+ onSuccess()
+ }
+ keyMatcher != null -> {
+ getAttachmentCheckKeyTries = 0
+
+ val attachmentKey = keyMatcher[1]
+ getAttachmentCheckKey(attachmentKey) {
+ downloadAttachment("${LIBRUS_SANDBOX_URL}CSDownload&singleUseKey=$attachmentKey", method = POST)
+ }
+ }
+ else -> {
+ downloadAttachment("$downloadLink/get", method = GET)
+ }
+ }
+ }
+
+ private fun getAttachmentCheckKey(attachmentKey: String, callback: () -> Unit) {
+ sandboxGet(TAG, "CSCheckKey",
+ parameters = mapOf("singleUseKey" to attachmentKey)) { json ->
+
+ when (json.getString("status")) {
+ "not_downloaded_yet" -> {
+ if (getAttachmentCheckKeyTries++ > 5) {
+ data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
+ .withApiResponse(json))
+ return@sandboxGet
+ }
+ launch {
+ delay(2000)
+ getAttachmentCheckKey(attachmentKey, callback)
+ }
+ }
+
+ "ready" -> {
+ launch { callback() }
+ }
+
+ else -> {
+ data.error(ApiError(TAG, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
+ .withApiResponse(json))
+ }
+ }
+ }
+ }
+
+ private fun downloadAttachment(url: String, method: Int = GET) {
+ val targetFile = File(Utils.getStorageDir(), attachmentName)
+
+ sandboxGetFile(TAG, url, targetFile, { 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/librus/data/synergia/LibrusSynergiaGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetAttachment.kt
new file mode 100644
index 00000000..6b1f2eba
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetAttachment.kt
@@ -0,0 +1,24 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
+
+import pl.szczodrzynski.edziennik.data.api.LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusSandboxDownloadAttachment
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+
+class LibrusSynergiaGetAttachment(override val data: DataLibrus,
+ val message: Message,
+ val attachmentId: Long,
+ val attachmentName: String,
+ val onSuccess: () -> Unit
+) : LibrusSynergia(data, null) {
+ companion object {
+ const val TAG = "LibrusSynergiaGetAttachment"
+ }
+
+ init {
+ redirectUrlGet(TAG, "$LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL/${message.id}/$attachmentId") { url ->
+ LibrusSandboxDownloadAttachment(data, url, message, attachmentId, attachmentName, onSuccess)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetHomework.kt
new file mode 100644
index 00000000..379bd42d
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetHomework.kt
@@ -0,0 +1,48 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
+
+import android.text.Html
+import org.greenrobot.eventbus.EventBus
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
+import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+
+class LibrusSynergiaGetHomework(override val data: DataLibrus,
+ val event: EventFull,
+ val onSuccess: () -> Unit
+) : LibrusSynergia(data, null) {
+ companion object {
+ const val TAG = "LibrusSynergiaGetHomework"
+ }
+
+ init {
+ synergiaGet(TAG, "moje_zadania/podglad/${event.id}") { text ->
+ val doc = Jsoup.parse(text)
+
+ val table = doc.select("table.decorated tbody > tr")
+
+ event.topic = table[1].select("td")[1].text()
+ event.homeworkBody = Html.fromHtml(table[5].select("td")[1].html()).toString()
+
+ event.attachmentIds = mutableListOf()
+ event.attachmentNames = mutableListOf()
+
+ if (table.size > 6) {
+ table[6].select("a").forEach { a ->
+ val attachmentId = a.attr("href").split('/')
+ .last().toLongOrNull() ?: return@forEach
+ val filename = a.text()
+ event.attachmentIds?.add(attachmentId)
+ event.attachmentNames?.add(filename)
+ }
+ }
+
+ 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/librus/data/synergia/LibrusSynergiaGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetMessage.kt
new file mode 100644
index 00000000..4cb1e246
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetMessage.kt
@@ -0,0 +1,160 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
+
+import org.greenrobot.eventbus.EventBus
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
+import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
+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 pl.szczodrzynski.edziennik.data.db.full.MessageFull
+import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.isNotNullNorEmpty
+import pl.szczodrzynski.edziennik.singleOrNull
+import pl.szczodrzynski.edziennik.swapFirstLastName
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class LibrusSynergiaGetMessage(override val data: DataLibrus,
+ private val messageObject: MessageFull,
+ val onSuccess: () -> Unit) : LibrusSynergia(data, null) {
+ companion object {
+ const val TAG = "LibrusSynergiaGetMessage"
+ }
+
+ init {
+ val endpoint = when (messageObject.type) {
+ Message.TYPE_SENT -> "wiadomosci/1/6/${messageObject.id}/f0"
+ else -> "wiadomosci/1/5/${messageObject.id}/f0"
+ }
+
+ data.profile?.also { profile ->
+ synergiaGet(TAG, endpoint) { text ->
+ val doc = Jsoup.parse(text)
+
+ val messageElement = doc.select(".container-message tr")[0].child(1)
+ val detailsElement = messageElement.child(1)
+ val readElement = messageElement.children().last()
+
+ val body = messageElement.select(".container-message-content").html()
+
+ messageObject.apply {
+ this.body = body
+
+ clearAttachments()
+ if (messageElement.children().size >= 5) {
+ messageElement.child(3).select("tr").forEachIndexed { i, attachment ->
+ if (i == 0) return@forEachIndexed // Skip the header
+ val filename = attachment.child(0).text().trim()
+ val attachmentId = "wiadomosci\\\\/pobierz_zalacznik\\\\/[0-9]+?\\\\/([0-9]+)\"".toRegex()
+ .find(attachment.select("img").attr("onclick"))?.get(1)
+ ?: return@forEachIndexed
+ addAttachment(attachmentId.toLong(), filename, -1)
+ }
+ }
+ }
+
+ val messageRecipientList = mutableListOf()
+
+ when (messageObject.type) {
+ Message.TYPE_RECEIVED -> {
+ val senderFullName = detailsElement.child(0).select(".left").text()
+ val senderGroupName = "\\[(.+?)]".toRegex().find(senderFullName)?.get(1)?.trim()
+
+ data.teacherList.singleOrNull { it.id == messageObject.senderId }?.apply {
+ setTeacherType(when (senderGroupName) {
+ /* https://api.librus.pl/2.0/Messages/Role */
+ "Pomoc techniczna Librus", "SuperAdministrator" -> Teacher.TYPE_SUPER_ADMIN
+ "Administrator szkoły" -> Teacher.TYPE_SCHOOL_ADMIN
+ "Dyrektor Szkoły" -> Teacher.TYPE_PRINCIPAL
+ "Nauczyciel" -> Teacher.TYPE_TEACHER
+ "Rodzic", "Opiekun" -> Teacher.TYPE_PARENT
+ "Sekretariat" -> Teacher.TYPE_SECRETARIAT
+ "Uczeń" -> Teacher.TYPE_STUDENT
+ "Pedagog/Psycholog szkolny" -> Teacher.TYPE_PEDAGOGUE
+ "Pracownik biblioteki" -> Teacher.TYPE_LIBRARIAN
+ "Inny specjalista" -> Teacher.TYPE_SPECIALIST
+ "Jednostka Nadrzędna" -> {
+ typeDescription = "Jednostka Nadrzędna"
+ Teacher.TYPE_OTHER
+ }
+ "Jednostka Samorządu Terytorialnego" -> {
+ typeDescription = "Jednostka Samorządu Terytorialnego"
+ Teacher.TYPE_OTHER
+ }
+ else -> Teacher.TYPE_OTHER
+ })
+ }
+
+ val readDateText = readElement.select(".left").text()
+ val readDate = when (readDateText.isNotNullNorEmpty()) {
+ true -> Date.fromIso(readDateText)
+ else -> 0
+ }
+
+ val messageRecipientObject = MessageRecipientFull(
+ profileId = profileId,
+ id = -1,
+ messageId = messageObject.id,
+ readDate = readDate
+ )
+
+ messageRecipientObject.fullName = profile.accountName
+ ?: profile.studentNameLong
+
+ messageRecipientList.add(messageRecipientObject)
+ }
+
+ Message.TYPE_SENT -> {
+
+ readElement.select("tr").forEachIndexed { i, receiver ->
+ if (i == 0) return@forEachIndexed // Skip the header
+
+ val receiverFullName = receiver.child(0).text()
+ val receiverName = receiverFullName.split('(')[0].swapFirstLastName()
+
+ val teacher = data.teacherList.singleOrNull { it.fullName == receiverName }
+ val receiverId = teacher?.id ?: -1
+
+ val readDate = when (val readDateText = receiver.child(1).text().trim()) {
+ "NIE" -> 0
+ else -> Date.fromIso(readDateText)
+ }
+
+ val messageRecipientObject = MessageRecipientFull(
+ profileId = profileId,
+ id = receiverId,
+ messageId = messageObject.id,
+ readDate = readDate
+ )
+
+ messageRecipientObject.fullName = receiverName
+
+ messageRecipientList.add(messageRecipientObject)
+ }
+ }
+ }
+
+ if (!messageObject.seen) {
+ data.setSeenMetadataList.add(Metadata(
+ messageObject.profileId,
+ Metadata.TYPE_MESSAGE,
+ messageObject.id,
+ true,
+ true
+ ))
+ }
+
+ messageObject.recipients = messageRecipientList
+ data.messageRecipientList.addAll(messageRecipientList)
+
+ data.messageList.add(messageObject)
+ data.messageListReplace = true
+
+ EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
+ onSuccess()
+ }
+ } ?: onSuccess()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetMessages.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetMessages.kt
new file mode 100644
index 00000000..ffc8133a
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaGetMessages.kt
@@ -0,0 +1,116 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.ERROR_NOT_IMPLEMENTED
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
+import pl.szczodrzynski.edziennik.data.db.entity.*
+import pl.szczodrzynski.edziennik.utils.Utils
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class LibrusSynergiaGetMessages(override val data: DataLibrus,
+ override val lastSync: Long?,
+ private val type: Int = Message.TYPE_RECEIVED,
+ archived: Boolean = false,
+ val onSuccess: (Int) -> Unit) : LibrusSynergia(data, lastSync) {
+ companion object {
+ const val TAG = "LibrusSynergiaGetMessages"
+ }
+
+ init {
+ val endpoint = when (type) {
+ Message.TYPE_RECEIVED -> "wiadomosci/5"
+ Message.TYPE_SENT -> "wiadomosci/6"
+ else -> null
+ }
+ val endpointId = when (type) {
+ Message.TYPE_RECEIVED -> ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_RECEIVED
+ else -> ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_SENT
+ }
+
+ if (endpoint != null) {
+ synergiaGet(TAG, endpoint) { text ->
+ val doc = Jsoup.parse(text)
+
+ fun getRecipientId(name: String): Long = data.teacherList.singleOrNull {
+ it.fullNameLastFirst == name
+ }?.id ?: {
+ val teacherObject = Teacher(
+ profileId,
+ -1 * Utils.crc16(name.swapFirstLastName().toByteArray()).toLong(),
+ name.splitName()?.second!!,
+ name.splitName()?.first!!
+ )
+ data.teacherList.put(teacherObject.id, teacherObject)
+ teacherObject.id
+ }.invoke()
+
+ doc.select(".decorated.stretch tbody > tr").forEach { messageElement ->
+ val url = messageElement.select("a").first().attr("href")
+ val id = Regexes.LIBRUS_MESSAGE_ID.find(url)?.get(1)?.toLong() ?: return@forEach
+ val subject = messageElement.child(3).text()
+ val sentDate = Date.fromIso(messageElement.child(4).text())
+ val recipientName = messageElement.child(2).text().split('(')[0].fixName()
+ val recipientId = getRecipientId(recipientName)
+ val read = messageElement.child(2).attr("style").isNullOrBlank()
+
+ val senderId = when (type) {
+ Message.TYPE_RECEIVED -> recipientId
+ else -> null
+ }
+
+ val receiverId = when (type) {
+ Message.TYPE_RECEIVED -> -1
+ else -> recipientId
+ }
+
+ val notified = when (type) {
+ Message.TYPE_SENT -> true
+ else -> read || profile?.empty ?: false
+ }
+
+ val messageObject = Message(
+ profileId = profileId,
+ id = id,
+ type = type,
+ subject = subject,
+ body = null,
+ senderId = senderId,
+ addedDate = sentDate
+ )
+
+ val messageRecipientObject = MessageRecipient(
+ profileId,
+ receiverId,
+ -1,
+ if (read) 1 else 0,
+ id
+ )
+
+ messageObject.hasAttachments = !messageElement.child(1).select("img").isEmpty()
+
+ data.messageList.add(messageObject)
+ data.messageRecipientList.add(messageRecipientObject)
+ data.setSeenMetadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_MESSAGE,
+ id,
+ notified,
+ notified
+ ))
+ }
+
+ when (type) {
+ Message.TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
+ Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, MainActivity.DRAWER_ITEM_MESSAGES)
+ }
+ onSuccess(endpointId)
+ }
+ } else {
+ data.error(TAG, ERROR_NOT_IMPLEMENTED)
+ onSuccess(endpointId)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomework.kt
index a34ee1e9..d33f6911 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomework.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomework.kt
@@ -12,25 +12,28 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
-class LibrusSynergiaHomework(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusSynergia(data) {
+class LibrusSynergiaHomework(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusSynergia(data, lastSync) {
companion object {
const val TAG = "LibrusSynergiaHomework"
}
- init {
+ init { data.profile?.also { profile ->
synergiaGet(TAG, "moje_zadania", method = POST, parameters = mapOf(
"dataOd" to
- if (data.profile?.empty != false)
- profile!!.getSemesterStart(1).stringY_m_d
+ if (profile.empty)
+ profile.getSemesterStart(1).stringY_m_d
else
Date.getToday().stringY_m_d,
- "dataDo" to profile!!.getSemesterEnd(profile?.currentSemester ?: 2).stringY_m_d,
+ "dataDo" to Date.getToday().stepForward(0, 0, 7).stringY_m_d,
"przedmiot" to -1
)) { text ->
@@ -39,8 +42,6 @@ class LibrusSynergiaHomework(override val data: DataLibrus, val onSuccess: () ->
doc.select("table.myHomeworkTable > tbody").firstOrNull()?.also { homeworkTable ->
val homeworkElements = homeworkTable.children()
- val graphElements = doc.select("table[border].center td[align=left] tbody").first().children()
-
homeworkElements.forEachIndexed { i, el ->
val elements = el.children()
@@ -51,37 +52,32 @@ class LibrusSynergiaHomework(override val data: DataLibrus, val onSuccess: () ->
val teacherId = data.teacherList.singleOrNull { teacherName == it.fullName }?.id
?: -1
val topic = elements[2].text().trim()
- val addedDate = Date.fromY_m_d(elements[4].text().trim()).inMillis
+ val addedDate = Date.fromY_m_d(elements[4].text().trim())
val eventDate = Date.fromY_m_d(elements[6].text().trim())
val id = "/podglad/([0-9]+)'".toRegex().find(
elements[9].select("input").attr("onclick")
)?.get(1)?.toLong() ?: return@forEachIndexed
- val lessons = data.db.timetableDao().getForDateNow(profileId, eventDate)
+ val lessons = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessons.firstOrNull { it.subjectId == subjectId }?.startTime
- val moreInfo = graphElements[2 * i + 1].select("td[title]")
- .attr("title").trim()
- val description = "Treść: (.*)".toRegex(RegexOption.DOT_MATCHES_ALL).find(moreInfo)
- ?.get(1)?.replace(" ".toRegex(), "\n")?.trim()
-
- val seen = when (profile?.empty) {
+ val seen = when (profile.empty) {
true -> true
else -> eventDate < Date.getToday()
}
val eventObject = Event(
- profileId,
- id,
- eventDate,
- startTime,
- "$topic\n$description",
- -1,
- Event.TYPE_HOMEWORK,
- false,
- teacherId,
- subjectId,
- data.teamClass?.id ?: -1
+ 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)
@@ -90,17 +86,16 @@ class LibrusSynergiaHomework(override val data: DataLibrus, val onSuccess: () ->
Metadata.TYPE_HOMEWORK,
id,
seen,
- seen,
- addedDate
+ seen
))
}
}
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
- // because this requires a synergia login (2 more requests) sync this every two hours or if explicit :D
- data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK, 2 * HOUR, DRAWER_ITEM_HOMEWORK)
- onSuccess()
+ // because this requires a synergia login (2 more requests!!!) sync this every few hours or if explicit :D
+ data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK, 5 * HOUR, DRAWER_ITEM_HOMEWORK)
+ onSuccess(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK)
}
- }
+ } ?: onSuccess(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK) }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomeworkGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomeworkGetAttachment.kt
new file mode 100644
index 00000000..a6d4b94b
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaHomeworkGetAttachment.kt
@@ -0,0 +1,25 @@
+package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
+
+import pl.szczodrzynski.edziennik.data.api.LIBRUS_SYNERGIA_HOMEWORK_ATTACHMENT_URL
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusSandboxDownloadAttachment
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+
+class LibrusSynergiaHomeworkGetAttachment(
+ override val data: DataLibrus,
+ val event: EventFull,
+ val attachmentId: Long,
+ val attachmentName: String,
+ val onSuccess: () -> Unit
+) : LibrusSynergia(data, null) {
+ companion object {
+ const val TAG = "LibrusSynergiaHomeworkGetAttachment"
+ }
+
+ init {
+ redirectUrlGet(TAG, "$LIBRUS_SYNERGIA_HOMEWORK_ATTACHMENT_URL/$attachmentId") { url ->
+ LibrusSandboxDownloadAttachment(data, url, event, attachmentId, attachmentName, onSuccess)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaInfo.kt
index 3ccb230f..66e11785 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaInfo.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaInfo.kt
@@ -10,7 +10,10 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_SYNERGIA_INFO
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
-class LibrusSynergiaInfo(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusSynergia(data) {
+class LibrusSynergiaInfo(override val data: DataLibrus,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : LibrusSynergia(data, lastSync) {
companion object {
const val TAG = "LibrusSynergiaInfo"
}
@@ -28,7 +31,7 @@ class LibrusSynergiaInfo(override val data: DataLibrus, val onSuccess: () -> Uni
}
data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_INFO, MONTH)
- onSuccess()
+ onSuccess(ENDPOINT_LIBRUS_SYNERGIA_INFO)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaMarkAllAnnouncementsAsRead.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaMarkAllAnnouncementsAsRead.kt
index 4a0ca241..04a7f5b6 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaMarkAllAnnouncementsAsRead.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaMarkAllAnnouncementsAsRead.kt
@@ -6,14 +6,18 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
-class LibrusSynergiaMarkAllAnnouncementsAsRead(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusSynergia(data) {
+class LibrusSynergiaMarkAllAnnouncementsAsRead(override val data: DataLibrus,
+ val onSuccess: () -> Unit
+) : LibrusSynergia(data, null) {
companion object {
const val TAG = "LibrusSynergiaMarkAllAnnouncementsAsRead"
}
init {
synergiaGet(TAG, "ogloszenia") {
+ data.app.db.metadataDao().setAllSeen(profileId, Metadata.TYPE_ANNOUNCEMENT, true)
onSuccess()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaTemplate.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaTemplate.kt
index af519128..ddfb4457 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaTemplate.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/synergia/LibrusSynergiaTemplate.kt
@@ -7,7 +7,9 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
-class LibrusSynergiaTemplate(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusSynergia(data) {
+class LibrusSynergiaTemplate(override val data: DataLibrus,
+ val onSuccess: () -> Unit
+) : LibrusSynergia(data, null) {
companion object {
const val TAG = "LibrusSynergia"
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt
index 1301222b..68f44269 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt
@@ -2,10 +2,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin
import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.ERROR_NO_STUDENTS_IN_ACCOUNT
-import pl.szczodrzynski.edziennik.data.api.FAKE_LIBRUS_ACCOUNTS
-import pl.szczodrzynski.edziennik.data.api.LIBRUS_ACCOUNTS_URL
-import pl.szczodrzynski.edziennik.data.api.LOGIN_MODE_LIBRUS_EMAIL
+import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusPortal
@@ -13,9 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginApi
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPortal
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.data.api.models.AppError.CODE_LIBRUS_DISCONNECTED
-import pl.szczodrzynski.edziennik.data.api.models.AppError.CODE_SYNERGIA_NOT_ACTIVATED
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
companion object {
@@ -23,10 +18,14 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
}
private val portal = LibrusPortal(data)
- private val api = LibrusApi(data)
+ private val api = LibrusApi(data, null)
private val profileList = mutableListOf()
init {
+ val loginStoreId = data.loginStore.id
+ val loginStoreType = LOGIN_TYPE_LIBRUS
+ var firstProfileId = loginStoreId
+
if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) {
// email login: use Portal for account list
LibrusLoginPortal(data) {
@@ -34,9 +33,8 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
val accounts = json.getJsonArray("accounts")
if (accounts == null || accounts.size() < 1) {
- data.error(ApiError(TAG, ERROR_NO_STUDENTS_IN_ACCOUNT)
- .withResponse(response)
- .withApiResponse(json))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(), data.loginStore))
+ onSuccess()
return@portalGet
}
val accountDataTime = json.getLong("lastModification")
@@ -46,8 +44,8 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
val state = account.getString("state")
when (state) {
- "requiring_an_action" -> CODE_LIBRUS_DISCONNECTED
- "need-activation" -> CODE_SYNERGIA_NOT_ACTIVATED
+ "requiring_an_action" -> ERROR_LIBRUS_PORTAL_SYNERGIA_DISCONNECTED
+ "need-activation" -> ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED
else -> null
}?.let { errorCode ->
data.error(ApiError(TAG, errorCode)
@@ -56,26 +54,34 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
return@portalGet
}
+ val isParent = account.getString("group") == "parent"
+
val id = account.getInt("id") ?: continue
val login = account.getString("login") ?: continue
val token = account.getString("accessToken") ?: continue
val tokenTime = (accountDataTime ?: 0) + DAY
- val name = account.getString("studentName")?.fixName() ?: ""
+ val studentNameLong = account.getString("studentName").fixName()
+ val studentNameShort = studentNameLong.getShortName()
- val profile = Profile()
- profile.studentNameLong = name
- profile.studentNameShort = name.getShortName()
- profile.name = profile.studentNameLong
- profile.subname = data.portalEmail
- profile.empty = true
- profile.putStudentData("accountId", id)
- profile.putStudentData("accountLogin", login)
- profile.putStudentData("accountToken", token)
- profile.putStudentData("accountTokenTime", tokenTime)
+ val profile = Profile(
+ firstProfileId++,
+ loginStoreId,
+ loginStoreType,
+ studentNameLong,
+ data.portalEmail,
+ studentNameLong,
+ studentNameShort,
+ if (isParent) studentNameLong else null /* temporarily - there is no parent name provided, only the type */
+ ).apply {
+ studentData["accountId"] = id
+ studentData["accountLogin"] = login
+ studentData["accountToken"] = token
+ studentData["accountTokenTime"] = tokenTime
+ }
profileList.add(profile)
}
- EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
onSuccess()
}
}
@@ -85,35 +91,40 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
LibrusLoginApi(data) {
api.apiGet(TAG, "Me") { json ->
- val profile = Profile()
-
val me = json.getJsonObject("Me")
val account = me?.getJsonObject("Account")
val user = me?.getJsonObject("User")
- profile.putStudentData("isPremium", account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true)
+ val login = account.getString("Login")
+ val isParent = account?.getInt("GroupId") in 5..6
- val isParent = account?.getInt("GroupId") == 5
- profile.accountNameLong =
- if (isParent)
- buildFullName(account?.getString("FirstName"), account?.getString("LastName"))
- else null
+ val studentNameLong = buildFullName(user?.getString("FirstName"), user?.getString("LastName"))
+ val studentNameShort = studentNameLong.getShortName()
+ val accountNameLong = if (isParent)
+ buildFullName(account?.getString("FirstName"), account?.getString("LastName"))
+ else null
- profile.studentNameLong =
- buildFullName(user?.getString("FirstName"), user?.getString("LastName"))
-
- profile.studentNameShort = profile.studentNameLong?.getShortName()
- profile.name = profile.studentNameLong
- profile.subname = account.getString("Login")
- profile.empty = true
- profile.putStudentData("accountId", account.getInt("Id") ?: 0)
- profile.putStudentData("accountLogin", profile.subname)
- profile.putStudentData("accountToken", data.apiAccessToken)
- profile.putStudentData("accountRefreshToken", data.apiRefreshToken)
- profile.putStudentData("accountTokenTime", data.apiTokenExpiryTime)
+ val profile = Profile(
+ firstProfileId++,
+ loginStoreId,
+ loginStoreType,
+ studentNameLong,
+ login,
+ studentNameLong,
+ studentNameShort,
+ accountNameLong
+ ).apply {
+ studentData["isPremium"] = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
+ studentData["accountId"] = account.getInt("Id") ?: 0
+ studentData["accountLogin"] = data.apiLogin ?: login
+ studentData["accountPassword"] = data.apiPassword
+ studentData["accountToken"] = data.apiAccessToken
+ studentData["accountTokenTime"] = data.apiTokenExpiryTime
+ studentData["accountRefreshToken"] = data.apiRefreshToken
+ }
profileList.add(profile)
- EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
onSuccess()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginApi.kt
index 0f843a88..7151cf29 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginApi.kt
@@ -18,6 +18,7 @@ import pl.szczodrzynski.edziennik.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
import java.net.HttpURLConnection.*
+@Suppress("ConvertSecondaryConstructorToPrimary")
class LibrusLoginApi {
companion object {
private const val TAG = "LoginLibrusApi"
@@ -137,6 +138,7 @@ class LibrusLoginApi {
"librus_change_password_error" -> ERROR_LOGIN_LIBRUS_API_CHANGE_PASSWORD_ERROR
"librus_password_change_required" -> ERROR_LOGIN_LIBRUS_API_PASSWORD_CHANGE_REQUIRED
"invalid_grant" -> ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN
+ "invalid_request" -> ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST
else -> ERROR_LOGIN_LIBRUS_API_OTHER
}.let { errorCode ->
data.error(ApiError(TAG, errorCode)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginMessages.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginMessages.kt
index 9767683b..9bfad99f 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginMessages.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginMessages.kt
@@ -8,9 +8,9 @@ import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.TextCallbackHandler
-import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
+import pl.szczodrzynski.edziennik.data.api.edziennik.librus.LibrusRecaptchaHelper
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
@@ -36,17 +36,39 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess()
}
+ text?.contains("grecaptcha.ready") == true -> {
+ val url = response?.request()?.url()?.toString() ?: run {
+ //data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
+ data.messagesLoginSuccessful = false
+ onSuccess()
+ return
+ }
+
+ LibrusRecaptchaHelper(data.app, url, text, onSuccess = { newUrl ->
+ loginWithSynergia(newUrl)
+ }, onTimeout = {
+ //data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_TIMEOUT, response, text)
+ data.messagesLoginSuccessful = false
+ onSuccess()
+ })
+ }
+
text?.contains("ok ") == true -> {
saveSessionId(response, text)
onSuccess()
}
text?.contains("Niepoprawny login i/lub hasło. ") == true -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
- text?.contains("eAccessDeny") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
+ text?.contains("eAccessDeny") == true -> {
+ // data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
+ data.messagesLoginSuccessful = false
+ onSuccess()
+ }
text?.contains("OffLine") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
text?.contains("error ") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
text?.contains("eVarWhitThisNameNotExists ") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
text?.contains("") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
+ else -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
}
}
@@ -64,21 +86,15 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
}
if (data.isMessagesLoginValid()) {
- data.app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("DZIENNIKSID")
- .value(data.messagesSessionId!!)
- .domain("wiadomosci.librus.pl")
- .secure().httpOnly().build()
- ))
+ data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
onSuccess()
}
else {
- data.app.cookieJar.clearForDomain("wiadomosci.librus.pl")
+ data.app.cookieJar.clear("wiadomosci.librus.pl")
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) {
loginWithSynergia()
}
- else if (data.apiLogin != null && data.apiPassword != null) {
+ else if (data.apiLogin != null && data.apiPassword != null && false) {
loginWithCredentials()
}
else {
@@ -148,7 +164,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
}
private fun saveSessionId(response: Response?, text: String?) {
- var sessionId = data.app.cookieJar.getCookie("wiadomosci.librus.pl", "DZIENNIKSID")
+ var sessionId = data.app.cookieJar.get("wiadomosci.librus.pl", "DZIENNIKSID")
sessionId = sessionId?.replace("-MAINT", "") // dunno what's this
sessionId = sessionId?.replace("MAINT", "") // dunno what's this
if (sessionId == null) {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt
index 41ad6255..f164e3ed 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt
@@ -7,14 +7,12 @@ import im.wangchao.mhttp.Response
import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.JsonCallbackHandler
import im.wangchao.mhttp.callback.TextCallbackHandler
+import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.getInt
-import pl.szczodrzynski.edziennik.getString
-import pl.szczodrzynski.edziennik.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
-import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
+import java.net.HttpURLConnection.*
import java.util.*
import java.util.regex.Pattern
@@ -38,11 +36,21 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess()
}
else if (data.portalRefreshToken != null) {
- data.app.cookieJar.clearForDomain("portal.librus.pl")
+ if (data.fakeLogin) {
+ data.app.cookieJar.clear("librus.szkolny.eu")
+ }
+ else {
+ data.app.cookieJar.clear("portal.librus.pl")
+ }
accessToken(null, data.portalRefreshToken)
}
else {
- data.app.cookieJar.clearForDomain("portal.librus.pl")
+ if (data.fakeLogin) {
+ data.app.cookieJar.clear("librus.szkolny.eu")
+ }
+ else {
+ data.app.cookieJar.clear("portal.librus.pl")
+ }
authorize(if (data.fakeLogin) FAKE_LIBRUS_AUTHORIZE else LIBRUS_AUTHORIZE_URL)
}
}}
@@ -55,23 +63,31 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
.userAgent(LIBRUS_USER_AGENT)
.withClient(data.app.httpLazy)
.callback(object : TextCallbackHandler() {
- override fun onSuccess(json: String, response: Response) {
+ override fun onSuccess(text: String, response: Response) {
val location = response.headers().get("Location")
if (location != null) {
- val authMatcher = Pattern.compile("http://localhost/bar\\?code=([A-z0-9]+?)$", Pattern.DOTALL or Pattern.MULTILINE).matcher(location)
- if (authMatcher.find()) {
- accessToken(authMatcher.group(1), null)
- } else {
- authorize(location)
+ val authMatcher = Pattern.compile("$LIBRUS_REDIRECT_URL\\?code=([A-z0-9]+?)$", Pattern.DOTALL or Pattern.MULTILINE).matcher(location)
+ when {
+ authMatcher.find() -> {
+ accessToken(authMatcher.group(1), null)
+ }
+ location.contains("rejected_client") -> {
+ data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_INVALID_CLIENT_ID)
+ .withResponse(response)
+ .withApiResponse("Location: $location\n$text"))
+ }
+ else -> {
+ authorize(location)
+ }
}
} else {
- val csrfMatcher = Pattern.compile("name=\"csrf-token\" content=\"([A-z0-9=+/\\-_]+?)\"", Pattern.DOTALL).matcher(json)
+ val csrfMatcher = Pattern.compile("name=\"csrf-token\" content=\"([A-z0-9=+/\\-_]+?)\"", Pattern.DOTALL).matcher(text)
if (csrfMatcher.find()) {
login(csrfMatcher.group(1))
} else {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING)
.withResponse(response)
- .withApiResponse(json))
+ .withApiResponse(text))
}
}
}
@@ -89,18 +105,29 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
private fun login(csrfToken: String) {
d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL}")
+ val recaptchaCode = data.arguments?.getString("recaptchaCode") ?: data.loginStore.getLoginData("recaptchaCode", null)
+ val recaptchaTime = data.arguments?.getLong("recaptchaTime") ?: data.loginStore.getLoginData("recaptchaTime", 0L)
+ data.loginStore.removeLoginData("recaptchaCode")
+ data.loginStore.removeLoginData("recaptchaTime")
+
Request.builder()
.url(if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL)
.userAgent(LIBRUS_USER_AGENT)
.addParameter("email", data.portalEmail)
.addParameter("password", data.portalPassword)
+ .also {
+ if (recaptchaCode != null && System.currentTimeMillis() - recaptchaTime < 2*60*1000 /* 2 minutes */)
+ it.addParameter("g-recaptcha-response", recaptchaCode)
+ }
.addHeader("X-CSRF-TOKEN", csrfToken)
+ .allowErrorCode(HTTP_BAD_REQUEST)
+ .allowErrorCode(HTTP_FORBIDDEN)
.contentType(MediaTypeUtils.APPLICATION_JSON)
.post()
.callback(object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response) {
val location = response.headers()?.get("Location")
- if (location == "http://localhost/bar?command=close") {
+ if (location == "$LIBRUS_REDIRECT_URL?command=close") {
data.error(ApiError(TAG, ERROR_LIBRUS_PORTAL_MAINTENANCE)
.withApiResponse(json)
.withResponse(response))
@@ -117,8 +144,26 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
.withResponse(response))
return
}
- if (json.get("errors") != null) {
- data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR)
+ val error = if (response.code() == 200) null else
+ json.getJsonArray("errors")?.getString(0)
+ ?: json.getJsonObject("errors")?.entrySet()?.firstOrNull()?.value?.asString
+ error?.let { code ->
+ when {
+ code.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED
+ code.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
+ // this doesn't work anyway: `errors` is an object with `g-recaptcha-response` set
+ code.contains("robotem") -> ERROR_CAPTCHA_LIBRUS_PORTAL
+ code.contains("Podany adres e-mail jest nieprawidłowy.") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
+ else -> ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR
+ }.let { errorCode ->
+ data.error(ApiError(TAG, errorCode)
+ .withApiResponse(json)
+ .withResponse(response))
+ return
+ }
+ }
+ if (json.getBoolean("captchaRequired") == true) {
+ data.error(ApiError(TAG, ERROR_CAPTCHA_LIBRUS_PORTAL)
.withResponse(response)
.withApiResponse(json))
return
@@ -127,12 +172,6 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
}
override fun onFailure(response: Response, throwable: Throwable) {
- if (response.code() == 403 || response.code() == 401) {
- data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN)
- .withResponse(response)
- .withThrowable(throwable))
- return
- }
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
.withResponse(response)
.withThrowable(throwable))
@@ -142,7 +181,6 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
.enqueue()
}
- private var refreshTokenFailed = false
private fun accessToken(code: String?, refreshToken: String?) {
d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_TOKEN else LIBRUS_TOKEN_URL}")
@@ -160,7 +198,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
return
}
val error = if (response?.code() == 200) null else
- json.getString("hint")
+ json.getString("hint") ?: json.getString("error")
error?.let { code ->
when (code) {
"Authorization code has expired" -> ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED
@@ -171,11 +209,9 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
"Check the `code` parameter" -> ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE
"Check the `refresh_token` parameter" -> ERROR_LOGIN_LIBRUS_PORTAL_NO_REFRESH
"Check the `redirect_uri` parameter" -> ERROR_LOGIN_LIBRUS_PORTAL_NO_REDIRECT
- else -> when (json.getString("error")) {
- "unsupported_grant_type" -> ERROR_LOGIN_LIBRUS_PORTAL_UNSUPPORTED_GRANT
- "invalid_client" -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_CLIENT_ID
- else -> ERROR_LOGIN_LIBRUS_PORTAL_OTHER
- }
+ "unsupported_grant_type" -> ERROR_LOGIN_LIBRUS_PORTAL_UNSUPPORTED_GRANT
+ "invalid_client" -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_CLIENT_ID
+ else -> ERROR_LOGIN_LIBRUS_PORTAL_OTHER
}.let { errorCode ->
data.error(ApiError(TAG, errorCode)
.withApiResponse(json)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginSynergia.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginSynergia.kt
index 3e11d502..4a292cfe 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginSynergia.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginSynergia.kt
@@ -8,7 +8,6 @@ import com.google.gson.JsonObject
import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.TextCallbackHandler
-import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
@@ -18,7 +17,7 @@ import pl.szczodrzynski.edziennik.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d
import java.net.HttpURLConnection
-class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusApi(data) {
+class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Unit) : LibrusApi(data, null) {
companion object {
private const val TAG = "LoginLibrusSynergia"
}
@@ -30,17 +29,11 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
}
if (data.isSynergiaLoginValid()) {
- data.app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name("DZIENNIKSID")
- .value(data.synergiaSessionId!!)
- .domain("synergia.librus.pl")
- .secure().httpOnly().build()
- ))
+ data.app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", data.synergiaSessionId)
onSuccess()
}
else {
- data.app.cookieJar.clearForDomain("synergia.librus.pl")
+ data.app.cookieJar.clear("synergia.librus.pl")
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_API)) {
loginWithApi()
}
@@ -70,7 +63,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
loginWithToken(json.getString("Token"))
}
- apiGet(TAG, "AutoLoginToken", POST, null, onSuccess)
+ apiGet(TAG, "AutoLoginToken", POST, onSuccess = onSuccess)
}
private fun loginWithToken(token: String?) {
@@ -92,7 +85,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
}
if (location?.endsWith("centrum_powiadomien") == true) {
- val sessionId = data.app.cookieJar.getCookie("synergia.librus.pl", "DZIENNIKSID")
+ val sessionId = data.app.cookieJar.get("synergia.librus.pl", "DZIENNIKSID")
if (sessionId == null) {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID)
.withResponse(response)
@@ -117,7 +110,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
}
}
- data.app.cookieJar.clearForDomain("synergia.librus.pl")
+ data.app.cookieJar.clear("synergia.librus.pl")
Request.builder()
.url(LIBRUS_SYNERGIA_TOKEN_LOGIN_URL.replace("TOKEN", token) + "/uczen/widok/centrum_powiadomien")
.userAgent(LIBRUS_USER_AGENT)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/SynergiaTokenExtractor.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/SynergiaTokenExtractor.kt
index d9719606..5072e5a2 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/SynergiaTokenExtractor.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/SynergiaTokenExtractor.kt
@@ -58,11 +58,6 @@ class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () ->
data.apiAccessToken = accountToken
data.apiTokenExpiryTime = response.getUnixDate() + 6 * 60 * 60
- // TODO remove this
- data.profile?.studentNameLong = json.getString("studentName")
- val nameParts = json.getString("studentName")?.split(" ")
- data.profile?.studentNameShort = nameParts?.get(0) + " " + nameParts?.get(1)?.get(0)
-
onSuccess()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt
index 40ba688d..ddfb0113 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt
@@ -5,13 +5,12 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik
import android.util.LongSparseArray
-import androidx.core.util.isNotEmpty
import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_MOBIDZIENNIK_WEB
import pl.szczodrzynski.edziennik.data.api.models.Data
-import pl.szczodrzynski.edziennik.currentTimeUnix
-import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@@ -23,6 +22,10 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
&& webSessionKey.isNotNullNorEmpty()
&& webServerId.isNotNullNorEmpty()
+ fun isApi2LoginValid() = loginEmail.isNotNullNorEmpty()
+ && loginId.isNotNullNorEmpty()
+ && globalId.isNotNullNorEmpty()
+
override fun satisfyLoginMethods() {
loginMethods.clear()
if (isWebLoginValid()) {
@@ -30,23 +33,20 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
}
}
+ override fun generateUserCode() = "$loginServerName:$loginUsername:$studentId"
+
val teachersMap = LongSparseArray()
val subjectsMap = LongSparseArray()
- val gradeAddedDates = LongSparseArray()
- val gradeAverages = LongSparseArray()
- val gradeColors = LongSparseArray()
+ val gradeAddedDates = sortedMapOf()
+ val gradeAverages = sortedMapOf()
+ val gradeColors = sortedMapOf()
private var mLoginServerName: String? = null
var loginServerName: String?
get() { mLoginServerName = mLoginServerName ?: loginStore.getLoginData("serverName", null); return mLoginServerName }
set(value) { loginStore.putLoginData("serverName", value); mLoginServerName = value }
- private var mLoginEmail: String? = null
- var loginEmail: String?
- get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail }
- set(value) { loginStore.putLoginData("email", value); mLoginEmail = value }
-
private var mLoginUsername: String? = null
var loginUsername: String?
get() { mLoginUsername = mLoginUsername ?: loginStore.getLoginData("username", null); return mLoginUsername }
@@ -88,6 +88,48 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("sessionIDTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
set(value) { loginStore.putLoginData("sessionIDTime", value); mWebSessionIdExpiryTime = value }
+ /* _____ _____ ___
+ /\ | __ \_ _| |__ \
+ / \ | |__) || | ) |
+ / /\ \ | ___/ | | / /
+ / ____ \| | _| |_ / /_
+ /_/ \_\_| |_____| |___*/
+ /**
+ * A global ID (whatever it is) used in API 2
+ * and Firebase push from Mobidziennik.
+ */
+ var globalId: String?
+ get() { mGlobalId = mGlobalId ?: profile?.getStudentData("globalId", null); return mGlobalId }
+ set(value) { profile?.putStudentData("globalId", value) ?: return; mGlobalId = value }
+ private var mGlobalId: String? = null
+
+ /**
+ * User's email that may or may not
+ * be retrieved from Web by [MobidziennikWebAccountEmail].
+ * Used to log in to API 2.
+ */
+ var loginEmail: String?
+ get() { mLoginEmail = mLoginEmail ?: profile?.getStudentData("email", null); return mLoginEmail }
+ set(value) { profile?.putStudentData("email", value); mLoginEmail = value }
+ private var mLoginEmail: String? = null
+
+ /**
+ * A login ID used in the API 2.
+ * Looks more or less like "7063@2019@zslpoznan".
+ */
+ var loginId: String?
+ get() { mLoginId = mLoginId ?: profile?.getStudentData("loginId", null); return mLoginId }
+ set(value) { profile?.putStudentData("loginId", value) ?: return; mLoginId = value }
+ private var mLoginId: String? = null
+
+ /**
+ * No need to explain.
+ */
+ var ciasteczkoAutoryzacji: String?
+ get() { mCiasteczkoAutoryzacji = mCiasteczkoAutoryzacji ?: profile?.getStudentData("ciasteczkoAutoryzacji", null); return mCiasteczkoAutoryzacji }
+ set(value) { profile?.putStudentData("ciasteczkoAutoryzacji", value) ?: return; mCiasteczkoAutoryzacji = value }
+ private var mCiasteczkoAutoryzacji: String? = null
+
override fun saveData() {
super.saveData()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/Mobidziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/Mobidziennik.kt
index 4b8b822d..0e002576 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/Mobidziennik.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/Mobidziennik.kt
@@ -6,22 +6,20 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
-import pl.szczodrzynski.edziennik.data.api.CODE_INTERNAL_LIBRUS_ACCOUNT_410
+import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikData
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebGetAttachment
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebGetMessage
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin.MobidziennikFirstLogin
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLogin
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
-import pl.szczodrzynski.edziennik.data.api.mobidziennikLoginMethods
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.data.api.prepare
-import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
+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 Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
@@ -33,6 +31,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
val internalErrorList = mutableListOf()
val data: DataMobidziennik
+ private var afterLogin: (() -> Unit)? = null
init {
data = DataMobidziennik(app, profile, loginStore).apply {
@@ -43,9 +42,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
private fun completed() {
data.saveData()
- data.notify {
- callback.onCompleted()
- }
+ callback.onCompleted()
}
/* _______ _ _ _ _ _
@@ -56,44 +53,80 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
- override fun sync(featureIds: List, viewId: Int?, arguments: JsonObject?) {
+ override fun sync(featureIds: List, viewId: Int?, onlyEndpoints: List?, arguments: JsonObject?) {
data.arguments = arguments
- data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, featureIds, viewId)
- d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
- d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
+ data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, 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(mobidziennikLoginMethods, it) }
+ afterLogin?.let { this.afterLogin = it }
MobidziennikLogin(data) {
- MobidziennikData(data) {
- completed()
- }
+ 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() ?: MobidziennikData(data) {
+ completed()
}
}
override fun getMessage(message: MessageFull) {
- MobidziennikLoginWeb(data) {
+ login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
MobidziennikWebGetMessage(data, message) {
completed()
}
}
}
- override fun markAllAnnouncementsAsRead() {
-
- }
-
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
- MobidziennikLoginWeb(data) {
- MobidziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
+ override fun sendMessage(recipients: List, subject: String, text: String) {
+ login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
+ MobidziennikWebSendMessage(data, recipients, subject, text) {
completed()
}
}
}
- override fun firstLogin() {
- MobidziennikFirstLogin(data) {
- completed()
+ override fun markAllAnnouncementsAsRead() {}
+ override fun getAnnouncement(announcement: AnnouncementFull) {}
+
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
+ login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
+ MobidziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
+ completed()
+ }
}
}
+ override fun getRecipientList() {
+ login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
+ MobidziennikWebGetRecipientList(data) {
+ completed()
+ }
+ }
+ }
+
+ override fun getEvent(eventFull: EventFull) {
+ login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
+ MobidziennikWebGetHomework(data, eventFull) {
+ completed()
+ }
+ }
+ }
+
+ override fun firstLogin() { MobidziennikFirstLogin(data) { completed() } }
override fun cancel() {
d(TAG, "Cancelled")
data.cancel()
@@ -101,28 +134,25 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
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 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) {
- in internalErrorList -> {
- // finish immediately if the same error occurs twice during the same sync
- callback.onError(apiError)
- }
- CODE_INTERNAL_LIBRUS_ACCOUNT_410 -> {
- internalErrorList.add(apiError.errorCode)
- loginStore.removeLoginData("refreshToken") // force a clean login
- //loginLibrus()
+ ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED,
+ ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY,
+ ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE,
+ ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID -> {
+ data.loginMethods.remove(LOGIN_METHOD_MOBIDZIENNIK_WEB)
+ data.prepareFor(mobidziennikLoginMethods, LOGIN_METHOD_MOBIDZIENNIK_WEB)
+ data.webSessionIdExpiryTime = 0
+ login()
}
else -> callback.onError(apiError)
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt
index c08846c9..7b39e455 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt
@@ -17,6 +17,8 @@ const val ENDPOINT_MOBIDZIENNIK_WEB_NOTICES = 2040
const val ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE = 2050
const val ENDPOINT_MOBIDZIENNIK_WEB_MANUALS = 2100
const val ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL = 2200
+const val ENDPOINT_MOBIDZIENNIK_WEB_HOMEWORK = 2300 // not used as an endpoint
+const val ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE = 2400
const val ENDPOINT_MOBIDZIENNIK_API2_MAIN = 3000
val MobidziennikFeatures = listOf(
@@ -27,16 +29,22 @@ val MobidziennikFeatures = listOf(
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), // TODO divide features into separate view IDs (all with API_MAIN)
// push config
- /*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf(
+ Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf(
ENDPOINT_MOBIDZIENNIK_API2_MAIN to LOGIN_METHOD_MOBIDZIENNIK_API2
), listOf(LOGIN_METHOD_MOBIDZIENNIK_API2)).withShouldSync { data ->
- data.app.appConfig.fcmTokens[LOGIN_TYPE_MOBIDZIENNIK]?.second?.contains(data.profileId) == false
- },*/
+ !data.app.config.sync.tokenMobidziennikList.contains(data.profileId)
+ },
+ /**
+ * Timetable - web scraping - does nothing if the API_MAIN timetable is enough.
+ */
+ Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_TIMETABLE, listOf(
+ ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_MOBIDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)),
/**
* Agenda - "API" + web scraping.
*/
@@ -58,10 +66,12 @@ val MobidziennikFeatures = listOf(
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_NOTICES to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)),
- // attendance TODO implement website attendance scraping
- /*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ATTENDANCE, listOf(
+ /**
+ * Attendance - only web scraping.
+ */
+ Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ATTENDANCE, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_MOBIDZIENNIK_WEB
- ), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),*/
+ ), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt
index 0ceeb49a..b82f6355 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt
@@ -7,10 +7,8 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api.MobidziennikApi
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebCalendar
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebGrades
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebMessagesAll
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebMessagesInbox
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2.MobidziennikApi2Main
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
import pl.szczodrzynski.edziennik.utils.Utils
class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
@@ -31,48 +29,66 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
onSuccess()
return
}
- useEndpoint(data.targetEndpointIds.removeAt(0)) {
+ 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, onSuccess: () -> Unit) {
- Utils.d(TAG, "Using endpoint $endpointId")
+ private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
+ Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
when (endpointId) {
ENDPOINT_MOBIDZIENNIK_API_MAIN -> {
data.startProgress(R.string.edziennik_progress_endpoint_data)
- MobidziennikApi(data, onSuccess)
+ MobidziennikApi(data, lastSync, onSuccess)
+ }
+ ENDPOINT_MOBIDZIENNIK_API2_MAIN -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_push_config)
+ MobidziennikApi2Main(data, lastSync, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
- MobidziennikWebMessagesInbox(data) { onSuccess() }
+ MobidziennikWebMessagesInbox(data, lastSync, onSuccess)
+ }
+ ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
+ MobidziennikWebMessagesSent(data, lastSync, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages)
- MobidziennikWebMessagesAll(data) { onSuccess() }
+ MobidziennikWebMessagesAll(data, lastSync, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR -> {
data.startProgress(R.string.edziennik_progress_endpoint_calendar)
- MobidziennikWebCalendar(data) { onSuccess() }
+ MobidziennikWebCalendar(data, lastSync, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_WEB_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grades)
- MobidziennikWebGrades(data) { onSuccess() }
- }/*
- ENDPOINT_MOBIDZIENNIK_WEB_NOTICES -> {
- data.startProgress(R.string.edziennik_progress_endpoint_behaviour)
- MobidziennikWebNotices(data) { onSuccess() }
+ MobidziennikWebGrades(data, lastSync, onSuccess)
+ }
+ ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_account_details)
+ MobidziennikWebAccountEmail(data, lastSync, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
- MobidziennikWebAttendance(data) { onSuccess() }
- }
+ MobidziennikWebAttendance(data, lastSync, onSuccess)
+ }/*
+ ENDPOINT_MOBIDZIENNIK_WEB_NOTICES -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_behaviour)
+ MobidziennikWebNotices(data, lastSync, onSuccess)
+ }]
ENDPOINT_MOBIDZIENNIK_WEB_MANUALS -> {
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
- MobidziennikWebManuals(data) { onSuccess() }
+ MobidziennikWebManuals(data, lastSync, onSuccess)
}*/
- else -> onSuccess()
+ ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE-> {
+ data.startProgress(R.string.edziennik_progress_endpoint_timetable)
+ MobidziennikWebTimetable(data, lastSync, onSuccess)
+ }
+ else -> onSuccess(endpointId)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikWeb.kt
index 6a1fc1dc..cfb4ab49 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikWeb.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikWeb.kt
@@ -8,14 +8,13 @@ import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.FileCallbackHandler
import im.wangchao.mhttp.callback.TextCallbackHandler
-import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils.d
import java.io.File
-open class MobidziennikWeb(open val data: DataMobidziennik) {
+open class MobidziennikWeb(open val data: DataMobidziennik, open val lastSync: Long?) {
companion object {
private const val TAG = "MobidziennikWeb"
}
@@ -26,8 +25,32 @@ open class MobidziennikWeb(open val data: DataMobidziennik) {
val profile
get() = data.profile
- fun webGet(tag: String, endpoint: String, method: Int = GET, onSuccess: (text: String) -> Unit) {
- val url = "https://${data.loginServerName}.mobidziennik.pl$endpoint"
+ /* TODO
+ add error handling:
+
+
+
+
+
Ważna informacja!
+
+
+
+ */
+
+ fun webGet(
+ tag: String,
+ endpoint: String,
+ method: Int = GET,
+ parameters: List> = emptyList(),
+ fullUrl: String? = null,
+ onSuccess: (text: String) -> Unit
+ ) {
+ val url = fullUrl ?: "https://${data.loginServerName}.mobidziennik.pl$endpoint"
d(tag, "Request: Mobidziennik/Web - $url")
@@ -58,6 +81,12 @@ open class MobidziennikWeb(open val data: DataMobidziennik) {
return
}
+ if (text.contains("Problemy z wydajnością ")) {
+ data.error(ApiError(TAG, ERROR_MOBIDZIENNIK_WEB_SERVER_PROBLEM)
+ .withResponse(response))
+ return
+ }
+
try {
onSuccess(text)
} catch (e: Exception) {
@@ -75,22 +104,21 @@ open class MobidziennikWeb(open val data: DataMobidziennik) {
}
}
- data.app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name(data.webSessionKey!!)
- .value(data.webSessionValue!!)
- .domain("${data.loginServerName}.mobidziennik.pl")
- .secure().httpOnly().build(),
- Cookie.Builder()
- .name("SERVERID")
- .value(data.webServerId!!)
- .domain("${data.loginServerName}.mobidziennik.pl")
- .secure().httpOnly().build()
- ))
+ data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", data.webSessionKey, data.webSessionValue)
+ data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", "SERVERID", data.webServerId)
Request.builder()
.url(url)
.userAgent(MOBIDZIENNIK_USER_AGENT)
+ .apply {
+ when (method) {
+ GET -> get()
+ POST -> post()
+ }
+ parameters.map { (name, value) ->
+ addParameter(name, value)
+ }
+ }
.callback(callback)
.build()
.enqueue()
@@ -148,18 +176,8 @@ open class MobidziennikWeb(open val data: DataMobidziennik) {
}
}
- data.app.cookieJar.saveFromResponse(null, listOf(
- Cookie.Builder()
- .name(data.webSessionKey!!)
- .value(data.webSessionValue!!)
- .domain("${data.loginServerName}.mobidziennik.pl")
- .secure().httpOnly().build(),
- Cookie.Builder()
- .name("SERVERID")
- .value(data.webServerId!!)
- .domain("${data.loginServerName}.mobidziennik.pl")
- .secure().httpOnly().build()
- ))
+ data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", data.webSessionKey, data.webSessionValue)
+ data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", "SERVERID", data.webServerId)
Request.builder()
.url(url)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApi.kt
index 543f21dc..323aeb14 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApi.kt
@@ -9,10 +9,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_API_MAIN
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
class MobidziennikApi(override val data: DataMobidziennik,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
companion object {
private const val TAG = "MobidziennikApi"
}
@@ -37,7 +39,7 @@ class MobidziennikApi(override val data: DataMobidziennik,
9 -> MobidziennikApiTeams(data, null, rows)
14 -> MobidziennikApiGradeCategories(data, rows)
15 -> MobidziennikApiLessons(data, rows)
- 16 -> MobidziennikApiAttendance(data, rows)
+ //16 -> MobidziennikApiAttendance(data, rows) // disabled since the new web scrapper is used
17 -> MobidziennikApiNotices(data, rows)
18 -> MobidziennikApiGrades(data, rows)
21 -> MobidziennikApiEvents(data, rows)
@@ -47,7 +49,7 @@ class MobidziennikApi(override val data: DataMobidziennik,
}
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_API_MAIN, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_API_MAIN)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt
index 76369615..473b3691 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt
@@ -5,9 +5,12 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.*
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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_PRESENT
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List) {
init { run {
@@ -23,7 +26,7 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List)
val id = cols[0].toLong()
val lessonId = cols[1].toLong()
data.mobiLessons.singleOrNull { it.id == lessonId }?.let { lesson ->
- val type = when (cols[4]) {
+ val baseType = when (cols[4]) {
"2" -> TYPE_ABSENT
"5" -> TYPE_ABSENT_EXCUSED
"4" -> TYPE_RELEASED
@@ -31,16 +34,37 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List)
}
val semester = data.profile?.dateToSemester(lesson.date) ?: 1
+ val typeName = when (baseType) {
+ TYPE_ABSENT -> "nieobecność"
+ TYPE_ABSENT_EXCUSED -> "nieobecność usprawiedliwiona"
+ TYPE_RELEASED -> "zwolnienie"
+ TYPE_PRESENT -> "obecność"
+ else -> "nieznany rodzaj"
+ }
+ val typeSymbol = when (baseType) {
+ TYPE_ABSENT -> "|"
+ TYPE_ABSENT_EXCUSED -> "+"
+ TYPE_RELEASED -> "z"
+ TYPE_PRESENT -> "."
+ else -> "?"
+ }
+
val attendanceObject = Attendance(
- data.profileId,
- id,
- lesson.teacherId,
- lesson.subjectId,
- semester,
- lesson.topic,
- lesson.date,
- lesson.startTime,
- type)
+ profileId = data.profileId,
+ id = id,
+ baseType = baseType,
+ typeName = typeName,
+ typeShort = data.app.attendanceManager.getTypeShort(baseType),
+ typeSymbol = typeSymbol,
+ typeColor = null,
+ date = lesson.date,
+ startTime = lesson.startTime,
+ semester = semester,
+ teacherId = lesson.teacherId,
+ subjectId = lesson.subjectId
+ ).also {
+ it.lessonTopic = lesson.topic
+ }
data.attendanceList.add(attendanceObject)
data.metadataList.add(
@@ -48,9 +72,8 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List)
data.profileId,
Metadata.TYPE_ATTENDANCE,
id,
- data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
+ data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
+ data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
))
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiEvents.kt
index adfdee11..7a72d3de 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiEvents.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiEvents.kt
@@ -8,8 +8,8 @@ import androidx.core.util.contains
import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import java.text.ParseException
@@ -30,7 +30,7 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List) {
val teacherId = cols[1].toLong()
val subjectId = cols[3].toLong()
var type = Event.TYPE_DEFAULT
- var topic = cols[5]
+ var topic = cols[5].trim()
Regexes.MOBIDZIENNIK_EVENT_TYPE.find(topic)?.let {
val typeText = it.groupValues[1]
when (typeText) {
@@ -51,17 +51,18 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List) {
val eventObject = Event(
- data.profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- type,
- false,
- teacherId,
- subjectId,
- teamId)
+ profileId = data.profileId,
+ id = id,
+ date = eventDate,
+ time = startTime,
+ topic = topic,
+ color = null,
+ type = type,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ teamId = teamId,
+ addedDate = addedDate
+ )
data.eventList.add(eventObject)
data.metadataList.add(
@@ -70,12 +71,13 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List) {
Metadata.TYPE_EVENT,
id,
data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- addedDate
+ data.profile?.empty ?: false
))
}
}
- data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_DEFAULT))
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_EXAM))
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_SHORT_QUIZ))
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGradeCategories.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGradeCategories.kt
index 87b069cc..b3bb8177 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGradeCategories.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGradeCategories.kt
@@ -7,7 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import android.graphics.Color
import androidx.core.util.contains
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
+import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
class MobidziennikApiGradeCategories(val data: DataMobidziennik, rows: List) {
init {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGrades.kt
index 16e73363..c3c1b449 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGrades.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGrades.kt
@@ -5,12 +5,19 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.*
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.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.Grade.Companion.TYPE_YEAR_FINAL
+import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
class MobidziennikApiGrades(val data: DataMobidziennik, rows: List) {
- init { run {
+ init { data.profile?.also { profile -> run {
data.db.gradeDao().getDetails(
data.profileId,
data.gradeAddedDates,
@@ -60,18 +67,25 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List) {
}
val gradeObject = Grade(
- data.profileId,
- id,
- category,
- color,
- description,
- name,
- value,
- weight,
- semester,
- teacherId,
- subjectId)
- gradeObject.type = type
+ profileId = data.profileId,
+ id = id,
+ name = name,
+ type = type,
+ value = value,
+ weight = weight,
+ color = color,
+ category = category,
+ description = description,
+ comment = null,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ addedDate = addedDate
+ )
+
+ if (data.profile?.empty == true) {
+ addedDate = data.profile.dateSemester1Start.inMillis
+ }
data.gradeList.add(gradeObject)
data.metadataList.add(
@@ -80,10 +94,20 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List) {
Metadata.TYPE_GRADE,
id,
data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- addedDate
+ data.profile?.empty ?: false
))
addedDate++
}
- }}
+ data.toRemove.addAll(listOf(
+ TYPE_NORMAL,
+ TYPE_SEMESTER1_FINAL,
+ TYPE_SEMESTER2_FINAL,
+ TYPE_SEMESTER1_PROPOSED,
+ TYPE_SEMESTER2_PROPOSED,
+ TYPE_YEAR_FINAL,
+ TYPE_YEAR_PROPOSED
+ ).map {
+ DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
+ })
+ }}}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiHomework.kt
index 37605401..683a8820 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiHomework.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiHomework.kt
@@ -4,11 +4,12 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
+import android.text.Html
import androidx.core.util.contains
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@@ -25,22 +26,22 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List) {
val id = cols[0].toLong()
val teacherId = cols[7].toLong()
val subjectId = cols[6].toLong()
- val topic = cols[1]
+ val topic = Html.fromHtml(cols[1])?.toString()?.trim() ?: ""
val eventDate = Date.fromYmd(cols[2])
val startTime = Time.fromYmdHm(cols[3])
val eventObject = Event(
- data.profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- Event.TYPE_HOMEWORK,
- false,
- teacherId,
- subjectId,
- teamId)
+ profileId = data.profileId,
+ id = id,
+ date = eventDate,
+ time = startTime,
+ topic = topic,
+ color = null,
+ type = Event.TYPE_HOMEWORK,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ teamId = teamId
+ )
data.eventList.add(eventObject)
data.metadataList.add(
@@ -49,8 +50,7 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List) {
Metadata.TYPE_HOMEWORK,
id,
data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
+ data.profile?.empty ?: false
))
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiNotices.kt
index 5520f490..66bfe1fd 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiNotices.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiNotices.kt
@@ -5,8 +5,8 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikApiNotices(val data: DataMobidziennik, rows: List) {
@@ -33,12 +33,16 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List) {
val addedDate = Date.fromYmd(cols[7]).inMillis
val noticeObject = Notice(
- data.profileId,
- id,
- text,
- semester,
- type,
- teacherId)
+ profileId = data.profileId,
+ id = id,
+ type = type,
+ semester = semester,
+ text = text,
+ category = null,
+ points = null,
+ teacherId = teacherId,
+ addedDate = addedDate
+ )
data.noticeList.add(noticeObject)
data.metadataList.add(
@@ -47,8 +51,7 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List) {
Metadata.TYPE_NOTICE,
id,
data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- addedDate
+ data.profile?.empty ?: false
))
}
}}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiSubjects.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiSubjects.kt
index eb2cef64..ce635860 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiSubjects.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiSubjects.kt
@@ -5,7 +5,7 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
+import pl.szczodrzynski.edziennik.data.db.entity.Subject
class MobidziennikApiSubjects(val data: DataMobidziennik, rows: List) {
init {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt
index 309e9cdb..6440b04e 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt
@@ -5,7 +5,7 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
+import pl.szczodrzynski.edziennik.data.db.entity.Team
import pl.szczodrzynski.edziennik.getById
import pl.szczodrzynski.edziennik.values
@@ -44,7 +44,7 @@ class MobidziennikApiTeams(val data: DataMobidziennik, tableTeams: List?
val studentId = cols[1].toInt()
val teamId = cols[2].toLong()
- val studentNumber = cols[4].toInt()
+ val studentNumber = cols[4].toIntOrNull() ?: -1
if (studentId != data.studentId)
continue
@@ -53,6 +53,7 @@ class MobidziennikApiTeams(val data: DataMobidziennik, tableTeams: List?
if (team.type == 1) {
data.profile?.studentNumber = studentNumber
data.teamClass = team
+ data.profile?.studentClassName = team.name
}
data.teamList.put(teamId, team)
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTimetable.kt
index 1832e2fe..aa07b1c3 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTimetable.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTimetable.kt
@@ -4,11 +4,15 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
+import android.util.SparseArray
+import androidx.core.util.set
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
-import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
+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.fixName
+import pl.szczodrzynski.edziennik.keys
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@@ -28,14 +32,19 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
dataStart.stepForward(0, 0, 1)
}
+ val lessonRanges = SparseArray()
+
for (lesson in lessons) {
val date = Date.fromYmd(lesson[2])
val startTime = Time.fromYmdHm(lesson[3])
val endTime = Time.fromYmdHm(lesson[4])
+ val startTimeValue = startTime.value
+ lessonRanges[startTimeValue] = endTime
+
dataDays.remove(date.value)
- val subjectId = data.subjectList.singleOrNull { it.longName == lesson[5] }?.id ?: -1
+ val subjectId = data.subjectList.singleOrNull { it.longName == lesson[5].trim() }?.id ?: -1
val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == (lesson[7]+" "+lesson[6]).fixName() }?.id ?: -1
val teamId = data.teamList.singleOrNull { it.name == lesson[8]+lesson[9] }?.id ?: -1
val classroom = lesson[11]
@@ -45,6 +54,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
"plan_lekcji", "lekcja" -> {
it.type = Lesson.TYPE_NORMAL
it.date = date
+ it.lessonNumber = startTimeValue
it.startTime = startTime
it.endTime = endTime
it.subjectId = subjectId
@@ -54,9 +64,10 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
}
"lekcja_odwolana" -> {
it.type = Lesson.TYPE_CANCELLED
- it.date = date
- it.startTime = startTime
- it.endTime = endTime
+ it.oldDate = date
+ it.oldLessonNumber = startTimeValue
+ it.oldStartTime = startTime
+ it.oldEndTime = endTime
it.oldSubjectId = subjectId
//it.oldTeacherId = teacherId
it.oldTeamId = teamId
@@ -65,6 +76,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
"zastepstwo" -> {
it.type = Lesson.TYPE_CHANGE
it.date = date
+ it.lessonNumber = startTimeValue
it.startTime = startTime
it.endTime = endTime
it.subjectId = subjectId
@@ -85,117 +97,34 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
Metadata.TYPE_LESSON_CHANGE,
it.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
- data.lessonNewList += it
+ data.lessonList += it
}
}
for (day in dataDays) {
val lessonDate = Date.fromValue(day)
- data.lessonNewList += Lesson(data.profileId, lessonDate.value.toLong()).apply {
+ data.lessonList += Lesson(data.profileId, lessonDate.value.toLong()).apply {
type = Lesson.TYPE_NO_LESSONS
date = lessonDate
}
}
- /*for (lessonStr in rows) {
- if (lessonStr.isNotEmpty()) {
- val lesson = lessonStr.split("|")
-
- if (lesson[0].toInt() != data.studentId)
- continue
-
- if (lesson[1] == "plan_lekcji" || lesson[1] == "lekcja") {
- val lessonObject = Lesson(data.profileId, lesson[2], lesson[3], lesson[4])
-
- data.subjectList.singleOrNull { it.longName == lesson[5] }?.let {
- lessonObject.subjectId = it.id
- }
- data.teacherList.singleOrNull { it.fullNameLastFirst == (lesson[7]+" "+lesson[6]).fixName() }?.let {
- lessonObject.teacherId = it.id
- }
- data.teamList.singleOrNull { it.name == lesson[8]+lesson[9] }?.let {
- lessonObject.teamId = it.id
- }
- lessonObject.classroomName = lesson[11]
- data.lessonList.add(lessonObject)
- }
+ lessonRanges.keys().sorted().forEachIndexed { index, startTime ->
+ data.lessonList.forEach {
+ if (it.lessonNumber == startTime)
+ it.lessonNumber = index + 1
+ if (it.oldLessonNumber == startTime)
+ it.oldLessonNumber = index + 1
}
+ data.lessonRanges[index + 1] = LessonRange(
+ profileId = profile.id,
+ lessonNumber = index + 1,
+ startTime = Time.fromValue(startTime),
+ endTime = lessonRanges[startTime]
+ )
}
-
- // searching for all changes
- for (lessonStr in rows) {
- if (lessonStr.isNotEmpty()) {
- val lesson = lessonStr.split("|")
-
- if (lesson[0].toInt() != data.studentId)
- continue
-
- if (lesson[1] == "zastepstwo" || lesson[1] == "lekcja_odwolana") {
- val lessonChange = LessonChange(data.profileId, lesson[2], lesson[3], lesson[4])
-
- data.subjectList.singleOrNull { it.longName == lesson[5] }?.let {
- lessonChange.subjectId = it.id
- }
- data.teacherList.singleOrNull { it.fullNameLastFirst == (lesson[7]+" "+lesson[6]).fixName() }?.let {
- lessonChange.teacherId = it.id
- }
- data.teamList.singleOrNull { it.name == lesson[8]+lesson[9] }?.let {
- lessonChange.teamId = it.id
- }
-
- if (lesson[1] == "zastepstwo") {
- lessonChange.type = LessonChange.TYPE_CHANGE
- }
- else if (lesson[1] == "lekcja_odwolana") {
- lessonChange.type = LessonChange.TYPE_CANCELLED
- }
- else if (lesson[1] == "lekcja") {
- lessonChange.type = LessonChange.TYPE_ADDED
- }
- lessonChange.classroomName = lesson[11]
-
- val originalLesson = lessonChange.getOriginalLesson(data.lessonList)
-
- if (lessonChange.type == LessonChange.TYPE_ADDED) {
- if (originalLesson == null) {
- // original lesson doesn't exist, save a new addition
- // TODO
- *//*if (!RegisterLessonChange.existsAddition(app.profile, registerLessonChange)) {
- app.profile.timetable.addLessonAddition(registerLessonChange);
- }*//*
- } else {
- // original lesson exists, so we need to compare them
- if (!lessonChange.matches(originalLesson)) {
- // the lessons are different, so it's probably a lesson change
- // ahhh this damn API
- lessonChange.type = LessonChange.TYPE_CHANGE
- }
- }
-
- }
- if (lessonChange.type != LessonChange.TYPE_ADDED) {
- // it's not a lesson addition
- data.lessonChangeList.add(lessonChange)
- data.metadataList.add(
- Metadata(
- data.profileId,
- Metadata.TYPE_LESSON_CHANGE,
- lessonChange.id,
- data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
- ))
- if (originalLesson == null) {
- // there is no original lesson, so we have to add one in order to change it
- data.lessonList.add(Lesson.fromLessonChange(lessonChange))
- }
- }
- }
- }
- }*/
}}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiUsers.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiUsers.kt
index da17657d..b95a55fe 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiUsers.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiUsers.kt
@@ -5,7 +5,7 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.fixName
class MobidziennikApiUsers(val data: DataMobidziennik, rows: List) {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api2/MobidziennikApi2Main.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api2/MobidziennikApi2Main.kt
new file mode 100644
index 00000000..70d32b18
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api2/MobidziennikApi2Main.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-1-12.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2
+
+import com.google.gson.JsonObject
+import im.wangchao.mhttp.Request
+import im.wangchao.mhttp.Response
+import im.wangchao.mhttp.callback.JsonCallbackHandler
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_API2_MAIN
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginApi2
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.getJsonObject
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.Utils
+
+class MobidziennikApi2Main(val data: DataMobidziennik,
+ val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) {
+ companion object {
+ private const val TAG = "MobidziennikApi2Main"
+ }
+
+ val profileId
+ get() = data.profile?.id ?: -1
+
+ val profile
+ get() = data.profile
+
+ init {
+ Utils.d(TAG, "Request: Mobidziennik/Api2/Main - https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
+
+ val callback = object : JsonCallbackHandler() {
+ override fun onSuccess(json: JsonObject?, response: Response?) {
+ if (json == null) {
+ data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return
+ }
+
+ json.getJsonObject("error")?.let {
+ val text = it.getString("type") ?: it.getString("message")
+ when (text) {
+ "LOGIN_ERROR" -> ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN
+ // TODO other error types
+ else -> ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER
+ }.let { errorCode ->
+ data.error(ApiError(TAG, errorCode)
+ .withApiResponse(text)
+ .withResponse(response))
+ return
+ }
+ }
+
+ val user = json.getJsonObject("user")
+ data.ciasteczkoAutoryzacji = user.getString("auth_key")
+
+ // sync always: this endpoint has .shouldSync set
+ data.setSyncNext(ENDPOINT_MOBIDZIENNIK_API2_MAIN, SYNC_ALWAYS)
+ data.app.config.sync.tokenMobidziennikList =
+ data.app.config.sync.tokenMobidziennikList + profileId
+ onSuccess(ENDPOINT_MOBIDZIENNIK_API2_MAIN)
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url("https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
+ .userAgent(MOBIDZIENNIK_USER_AGENT)
+ .contentType("application/x-www-form-urlencoded; charset=UTF-8")
+ .addParameter("login", data.loginId)
+ .addParameter("email", data.loginEmail)
+ .addParameter("haslo", data.loginPassword)
+ .addParameter("device", MobidziennikLoginApi2.getDevice(data.app).toString())
+ .apply {
+ data.ciasteczkoAutoryzacji?.let { addParameter("ciasteczko_autoryzacji", it) }
+ }
+ .post()
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt
index 7aaf7474..ece23d7f 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikLuckyNumberExtractor.kt
@@ -6,23 +6,20 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
-import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String) {
init {
- data.profile?.luckyNumber = -1
- data.profile?.luckyNumberDate = null
-
Regexes.MOBIDZIENNIK_LUCKY_NUMBER.find(text)?.let {
try {
val luckyNumber = it.groupValues[1].toInt()
val luckyNumberObject = LuckyNumber(
- data.profileId,
- Date.getToday(),
- luckyNumber
+ profileId = data.profileId,
+ date = Date.getToday(),
+ number = luckyNumber
)
data.luckyNumberList.add(luckyNumberObject)
@@ -31,9 +28,8 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
data.profileId,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
- data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
+ true,
+ data.profile?.empty ?: false
))
} catch (_: Exception){}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAccountEmail.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAccountEmail.kt
new file mode 100644
index 00000000..ef4c2847
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAccountEmail.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-1-21.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import pl.szczodrzynski.edziennik.DAY
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.get
+
+class MobidziennikWebAccountEmail(override val data: DataMobidziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "MobidziennikWebAccountEmail"
+ }
+
+ init {
+ webGet(TAG, "/dziennik/edytujprofil") { text ->
+ MobidziennikLuckyNumberExtractor(data, text)
+
+ val email = Regexes.MOBIDZIENNIK_ACCOUNT_EMAIL.find(text)?.let { it[1] }
+ data.loginEmail = email
+
+ data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL, if (email == null) 3*DAY else 7*DAY)
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL)
+ }
+ }
+}
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
new file mode 100644
index 00000000..cbd797b1
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-2-18.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import pl.szczodrzynski.edziennik.data.api.POST
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
+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.fixName
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.singleOrNull
+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 MobidziennikWebAttendance(override val data: DataMobidziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "MobidziennikWebAttendance"
+ }
+
+ init { data.profile?.let { profile ->
+ val lastSync = lastSync?.let { Date.fromMillis(it) } ?: profile.dateSemester1Start
+ var weekStart = Week.getWeekStart()
+ val syncWeeks = mutableListOf(weekStart)
+ while (weekStart >= lastSync && weekStart > profile.dateSemester1Start) {
+ weekStart = weekStart.clone().stepForward(0, 0, -7)
+ syncWeeks += weekStart
+ }
+
+ //syncWeeks.clear()
+ //syncWeeks += Date.fromY_m_d("2019-12-19")
+
+ syncWeeks.minByOrNull { it.value }?.let {
+ data.toRemove.add(DataRemoveModel.Attendance.from(it))
+ }
+
+ start(syncWeeks)
+
+ } ?: onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE) }
+
+ private fun start(syncWeeks: MutableList) {
+ if (syncWeeks.isEmpty()) {
+ data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ATTENDANCE)
+ return
+ }
+ sync(syncWeeks.removeAt(0).stringY_m_d) {
+ start(syncWeeks)
+ }
+ }
+
+ private fun sync(weekStart: String, onSuccess: () -> Unit) {
+ val requestTime = System.currentTimeMillis()
+ webGet(TAG, "/dziennik/frekwencja", method = POST, parameters = listOf(
+ "uczen" to data.studentId,
+ "data_poniedzialek" to weekStart
+ )) { text ->
+ MobidziennikLuckyNumberExtractor(data, text)
+
+ val start = System.currentTimeMillis()
+
+ val types = Regexes.MOBIDZIENNIK_ATTENDANCE_TYPES
+ .find(text)
+ ?.get(1)
+ ?.split(" ")
+ ?.map {
+ it.trimEnd(',')
+ .split(" ", limit = 2)
+ .let { it.getOrNull(0) to it.getOrNull(1) }
+ }
+ ?.toMap()
+ val typeSymbols = types?.keys?.filterNotNull() ?: listOf()
+
+ Regexes.MOBIDZIENNIK_ATTENDANCE_TABLE.findAll(text).forEach { tableResult ->
+ val table = tableResult[1]
+
+ val lessonDates = mutableListOf()
+ val entries = mutableListOf()
+ val ranges = mutableListOf()
+
+ Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON_COUNT.findAll(table).forEach {
+ val date = Date.fromY_m_d(it[1])
+ for (i in 0 until (it[2].toIntOrNull() ?: 0)) {
+ lessonDates += date
+ }
+ }
+ Regexes.MOBIDZIENNIK_ATTENDANCE_ENTRIES.findAll(table).mapTo(entries) { it[1] }
+
+ Regexes.MOBIDZIENNIK_ATTENDANCE_COLUMNS.findAll(table).forEach { columns ->
+ var index = 0
+ Regexes.MOBIDZIENNIK_ATTENDANCE_COLUMN.findAll(columns[1]).forEach { column ->
+ if (column[1].contains("colspan")) {
+ val colspan =
+ Regexes.MOBIDZIENNIK_ATTENDANCE_COLUMN_SPAN.find(column[1])
+ ?.get(1)
+ ?.toIntOrNull() ?: 0
+ entries.addAll(index, List(colspan) { "" })
+ ranges.addAll(List(colspan) { null })
+ index += colspan
+ }
+ else {
+ val range = Regexes.MOBIDZIENNIK_ATTENDANCE_RANGE.find(column[2])
+ ranges.add(range)
+ index++
+ }
+ }
+ }
+
+ val dateIterator = lessonDates.iterator()
+ val entriesIterator = entries.iterator()
+
+ val count = ranges.count()
+ // verify the lesson count is the same as dates & entries
+ if (count != lessonDates.count() || count != entries.count())
+ return@forEach
+ ranges.forEach { range ->
+ val lessonDate = dateIterator.next()
+ val entry = entriesIterator.next()
+ if (range == null || entry.isBlank())
+ return@forEach
+ val startTime = Time.fromH_m(range[1])
+
+ range[2].split(" / ").mapNotNull {
+ Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON.find(it)
+ }.forEachIndexed { index, lesson ->
+ processEntry(
+ index,
+ lesson,
+ lessonDate,
+ startTime,
+ entry,
+ types,
+ typeSymbols
+ )
+ }
+ }
+ }
+
+ d(TAG, "Done in ${System.currentTimeMillis()-start} ms (request ${start-requestTime} ms)")
+
+ onSuccess()
+ }
+ }
+
+ private fun processEntry(
+ index: Int,
+ lesson: MatchResult,
+ lessonDate: Date,
+ startTime: Time,
+ entry: String,
+ types: Map?,
+ typeSymbols: List
+ ) {
+ var entry = entry
+
+ val topic = lesson[1].substringAfter(" - ", missingDelimiterValue = "").takeIf { it.isNotBlank() }
+ if (topic?.startsWith("Lekcja odwołana: ") == true || entry.isEmpty())
+ return
+ val subjectName = lesson[1].substringBefore(" - ").trim()
+ //val team = lesson[3]
+ val teacherName = lesson[3].fixName()
+
+ val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1
+ val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1
+
+ var typeSymbol = ""
+ for (symbol in typeSymbols) {
+ if (entry.startsWith(symbol) && symbol.length > typeSymbol.length)
+ typeSymbol = symbol
+ }
+ entry = entry.removePrefix(typeSymbol)
+
+ var isCustom = false
+ val baseType = when (typeSymbol) {
+ "." -> TYPE_PRESENT
+ "|" -> TYPE_ABSENT
+ "+" -> TYPE_ABSENT_EXCUSED
+ "s" -> TYPE_BELATED
+ "z" -> TYPE_RELEASED
+ else -> {
+ isCustom = true
+ when (typeSymbol) {
+ "e" -> TYPE_PRESENT_CUSTOM
+ "en" -> TYPE_ABSENT
+ "ep" -> TYPE_PRESENT_CUSTOM
+ "+ₑ" -> TYPE_ABSENT_EXCUSED
+ else -> TYPE_UNKNOWN
+ }
+ }
+ }
+ val typeName = types?.get(typeSymbol) ?: ""
+ val typeColor = when (typeSymbol) {
+ "e" -> 0xff673ab7
+ "en" -> 0xffec407a
+ "ep" -> 0xff4caf50
+ "+ₑ" -> 0xff795548
+ else -> null
+ }?.toInt()
+
+ val typeShort = if (!isCustom)
+ data.app.attendanceManager.getTypeShort(baseType)
+ else
+ typeSymbol
+
+ val semester = data.profile?.dateToSemester(lessonDate) ?: 1
+
+ val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson[0].hashCode() and 0xFFFF) + index
+
+ val attendanceObject = Attendance(
+ profileId = profileId,
+ id = id,
+ baseType = baseType,
+ typeName = typeName,
+ typeShort = typeShort,
+ typeSymbol = typeSymbol,
+ typeColor = typeColor,
+ date = lessonDate,
+ startTime = startTime,
+ semester = semester,
+ teacherId = teacherId,
+ subjectId = subjectId
+ ).also {
+ it.lessonTopic = topic
+ }
+
+ data.attendanceList.add(attendanceObject)
+ if (baseType != TYPE_PRESENT) {
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_ATTENDANCE,
+ id,
+ data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
+ data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN
+ ))
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt
index c1578af4..95c1f6df 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt
@@ -9,16 +9,18 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.getString
import pl.szczodrzynski.edziennik.utils.Utils.crc16
import pl.szczodrzynski.edziennik.utils.models.Date
import java.util.*
class MobidziennikWebCalendar(override val data: DataMobidziennik,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
companion object {
private const val TAG = "MobidziennikWebCalendar"
}
@@ -59,26 +61,25 @@ class MobidziennikWebCalendar(override val data: DataMobidziennik,
val title = event.getString("title")
val comment = event.getString("comment")
- var topic = title
+ var topic = title ?: ""
if (title != comment) {
topic += "\n" + comment
}
if (id == -1L) {
- id = crc16(topic?.toByteArray()).toLong()
+ id = crc16(topic.toByteArray()).toLong()
}
val eventObject = Event(
- profileId,
- id,
- eventDate, null,
- topic,
- -1,
- eventType,
- false,
- -1,
- -1,
- data.teamClass?.id ?: -1
+ profileId = profileId,
+ id = id,
+ date = eventDate, time = null,
+ topic = topic,
+ color = null,
+ type = eventType,
+ teacherId = -1,
+ subjectId = -1,
+ teamId = data.teamClass?.id ?: -1
)
data.eventList.add(eventObject)
@@ -88,14 +89,14 @@ class MobidziennikWebCalendar(override val data: DataMobidziennik,
Metadata.TYPE_EVENT,
eventObject.id,
profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis() /* no addedDate here though */
+ profile?.empty ?: false
+ /* no addedDate here though */
))
}
}
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetAttachment.kt
index 326553c8..52561a81 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetAttachment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetAttachment.kt
@@ -8,13 +8,18 @@ import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.utils.Utils
+import pl.szczodrzynski.edziennik.utils.models.Date
import java.io.File
-class MobidziennikWebGetAttachment(
- override val data: DataMobidziennik, val message: Message, val attachmentId: Long,
- val attachmentName: String, val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
+ val owner: Any,
+ val attachmentId: Long,
+ val attachmentName: String,
+ val onSuccess: () -> Unit
+) : MobidziennikWeb(data, null) {
companion object {
private const val TAG = "MobidziennikWebGetAttachment"
}
@@ -22,25 +27,40 @@ class MobidziennikWebGetAttachment(
init {
val targetFile = File(Utils.getStorageDir(), attachmentName)
- val typeUrl = if (message.type == Message.TYPE_SENT)
- "wiadwyslana"
- else
- "wiadodebrana"
+ val typeUrl = when (owner) {
+ is Message -> if (owner.type == Message.TYPE_SENT)
+ "dziennik/wiadwyslana/?id="
+ else
+ "dziennik/wiadodebrana/?id="
- webGetFile(TAG, "/dziennik/$typeUrl/?id=${message.id}&zalacznik=$attachmentId", targetFile, { file ->
+ is Event -> if (owner.date >= Date.getToday())
+ "dziennik/wyslijzadanie/?id_zadania="
+ else
+ "dziennik/wyslijzadanie/?id_zadania="
+
+ else -> ""
+ }
+
+ val ownerId = when (owner) {
+ is Message -> owner.id
+ is Event -> owner.id
+ else -> -1
+ }
+
+ webGetFile(TAG, "/$typeUrl${ownerId}&uczen=${data.studentId}&zalacznik=$attachmentId", targetFile, { file ->
val event = AttachmentGetEvent(
profileId,
- message.id,
+ owner,
attachmentId,
AttachmentGetEvent.TYPE_FINISHED,
file.absolutePath
)
- val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
+ val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
Utils.writeStringToFile(attachmentDataFile, event.fileName)
- EventBus.getDefault().post(event)
+ EventBus.getDefault().postSticky(event)
onSuccess()
@@ -48,13 +68,13 @@ class MobidziennikWebGetAttachment(
// TODO make use of bytesTotal
val event = AttachmentGetEvent(
profileId,
- message.id,
+ owner,
attachmentId,
AttachmentGetEvent.TYPE_PROGRESS,
bytesWritten = written
)
- EventBus.getDefault().post(event)
+ EventBus.getDefault().postSticky(event)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetHomework.kt
new file mode 100644
index 00000000..b0699b4b
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetHomework.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-3-31.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class MobidziennikWebGetHomework(override val data: DataMobidziennik,
+ val event: EventFull,
+ val onSuccess: () -> Unit
+) : MobidziennikWeb(data, null) {
+ companion object {
+ private const val TAG = "MobidziennikWebHomework"
+ }
+
+ init {
+ val endpoint = if (event.date >= Date.getToday())
+ "zadaniadomowe"
+ else
+ "zadaniadomowearchiwalne"
+
+ webGet(TAG, "/mobile/$endpoint") { text ->
+ MobidziennikLuckyNumberExtractor(data, text)
+
+ Regexes.MOBIDZIENNIK_HOMEWORK_ROW.findAll(text).forEach { homeworkMatch ->
+ val tableRow = homeworkMatch[1].ifBlank { return@forEach }
+
+ val id = Regexes.MOBIDZIENNIK_HOMEWORK_ID.find(tableRow)?.get(1)?.toLongOrNull() ?: return@forEach
+ if (event.id != id)
+ return@forEach
+
+ event.attachmentIds = mutableListOf()
+ event.attachmentNames = mutableListOf()
+ Regexes.MOBIDZIENNIK_HOMEWORK_ATTACHMENT.findAll(tableRow).forEach {
+ event.attachmentIds?.add(it[2].toLongOrNull() ?: return@forEach)
+ event.attachmentNames?.add(it[3])
+ }
+
+ event.homeworkBody = ""
+ }
+
+ 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/mobidziennik/data/web/MobidziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt
index 8390aa37..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
@@ -10,21 +10,22 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
+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.fixName
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.Utils.monthFromName
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
-class MobidziennikWebGetMessage(
- override val data: DataMobidziennik,
- private val message: MessageFull,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+class MobidziennikWebGetMessage(override val data: DataMobidziennik,
+ private val message: MessageFull,
+ val onSuccess: () -> Unit
+) : MobidziennikWeb(data, null) {
companion object {
private const val TAG = "MobidziennikWebGetMessage"
}
@@ -60,31 +61,29 @@ class MobidziennikWebGetMessage(
}
val recipient = MessageRecipientFull(
- profileId,
- -1,
- -1,
- readDate,
- message.id
+ profileId = profileId,
+ id = -1,
+ messageId = message.id,
+ readDate = readDate
)
- recipient.fullName = profile?.accountNameLong ?: profile?.studentNameLong
+ recipient.fullName = profile?.accountName ?: profile?.studentNameLong ?: ""
messageRecipientList.add(recipient)
} else {
- message.senderId = -1
- message.senderReplyId = -1
+ message.senderId = null
content.select("table.spis tr:has(td)")?.forEach { recipientEl ->
- val senderEl = recipientEl.select("td:eq(0)").first()
- val senderName = senderEl.text()
+ 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,
@@ -99,11 +98,10 @@ class MobidziennikWebGetMessage(
}
val recipient = MessageRecipientFull(
- profileId,
- receiverId,
- -1,
- readDate,
- message.id
+ profileId = profileId,
+ id = receiverId,
+ messageId = message.id,
+ readDate = readDate
)
recipient.fullName = teacher?.fullName ?: "?"
@@ -136,19 +134,20 @@ class MobidziennikWebGetMessage(
}
if (!message.seen) { // TODO discover why this monstrosity instead of MetadataDao.setSeen
- data.messageMetadataList.add(Metadata(
+ data.setSeenMetadataList.add(Metadata(
message.profileId,
Metadata.TYPE_MESSAGE,
message.id,
true,
- true,
- message.addedDate
+ true
))
}
message.recipients = messageRecipientList
data.messageRecipientList.addAll(messageRecipientList)
+
data.messageList.add(message)
+ data.messageListReplace = true
EventBus.getDefault().postSticky(MessageGetEvent(message))
onSuccess()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt
new file mode 100644
index 00000000..0ed1e4a6
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2019-12-22.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import androidx.core.util.set
+import androidx.room.OnConflictStrategy
+import com.google.gson.JsonObject
+import com.google.gson.JsonParser
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.RecipientListGetEvent
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
+
+class MobidziennikWebGetRecipientList(override val data: DataMobidziennik,
+ val onSuccess: () -> Unit
+) : MobidziennikWeb(data, null) {
+ companion object {
+ private const val TAG = "MobidziennikWebGetRecipientList"
+ }
+
+ init {
+ webGet(TAG, "/mobile/dodajwiadomosc") { text ->
+ Regexes.MOBIDZIENNIK_MESSAGE_RECIPIENTS_JSON.find(text)?.let { match ->
+ val recipientLists = JsonParser().parse(match[1]).asJsonArray
+ recipientLists?.asJsonObjectList()?.forEach { list ->
+ val listType = list.getString("typ")?.toIntOrNull() ?: -1
+ val listName = list.getString("nazwa") ?: ""
+ list.getJsonArray("dane")?.asJsonObjectList()?.forEach { recipient ->
+ if (recipient.getBoolean("lista") == true) {
+ recipient.getJsonArray("dane")?.asJsonObjectList()?.forEach {
+ processRecipient(listType, recipient.getString("nazwa") ?: "", it)
+ }
+ }
+ else
+ processRecipient(listType, listName, recipient)
+ }
+ }
+ }
+
+ val event = RecipientListGetEvent(
+ data.profileId,
+ data.teacherList.filter { it.loginId != null }
+ )
+
+ profile?.lastReceiversSync = System.currentTimeMillis()
+
+ data.teacherOnConflictStrategy = OnConflictStrategy.REPLACE
+ EventBus.getDefault().postSticky(event)
+ onSuccess()
+ }
+ }
+
+ private fun processRecipient(listType: Int, listName: String, recipient: JsonObject) {
+ val id = recipient.getString("id") ?: return
+ val idLong = id.replace(Regexes.NOT_DIGITS, "").toLongOrNull() ?: return
+ // get teacher by ID or create it
+ val teacher = data.teacherList[idLong] ?: Teacher(data.profileId, idLong).apply {
+ val fullName = recipient.getString("nazwa")?.fixName()
+ name = fullName ?: ""
+ fullName?.splitName()?.let {
+ name = it.second
+ surname = it.first
+ }
+ data.teacherList[idLong] = this
+ }
+
+ teacher.apply {
+ loginId = id
+ when (listType) {
+ 1 -> setTeacherType(Teacher.TYPE_PRINCIPAL)
+ 2 -> setTeacherType(Teacher.TYPE_TEACHER)
+ 3 -> setTeacherType(Teacher.TYPE_PARENT)
+ 4 -> setTeacherType(Teacher.TYPE_STUDENT)
+ //5 -> Użytkownicy zewnętrzni
+ //6 -> Samorządy klasowe
+ 7 -> setTeacherType(Teacher.TYPE_PARENTS_COUNCIL) // Rady oddziałowe rodziców
+ 8 -> {
+ setTeacherType(Teacher.TYPE_EDUCATOR)
+ typeDescription = listName
+ }
+ 9 -> setTeacherType(Teacher.TYPE_PEDAGOGUE)
+ 10 -> setTeacherType(Teacher.TYPE_SPECIALIST)
+ else -> when (listName) {
+ "Administratorzy" -> setTeacherType(Teacher.TYPE_SCHOOL_ADMIN)
+ "Sekretarka" -> setTeacherType(Teacher.TYPE_SECRETARIAT)
+ "Wsparcie techniczne mobiDziennik" -> setTeacherType(Teacher.TYPE_SUPER_ADMIN)
+ else -> {
+ setTeacherType(Teacher.TYPE_OTHER)
+ typeDescription = listName
+ }
+ }
+ }
+ }
+ }
+}
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 52db5bfa..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
@@ -10,9 +10,10 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+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.fixWhiteSpaces
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.singleOrNull
@@ -20,13 +21,17 @@ import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class MobidziennikWebGrades(override val data: DataMobidziennik,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
companion object {
private const val TAG = "MobidziennikWebGrades"
}
- init {
- webGet(TAG, "/dziennik/oceny?semestr=${profile?.currentSemester ?: 1}") { text ->
+ init { data.profile?.also { profile ->
+ val currentSemester = profile.currentSemester
+
+ webGet(TAG, "/dziennik/oceny?semestr=$currentSemester") { text ->
MobidziennikLuckyNumberExtractor(data, text)
val doc = Jsoup.parse(text)
@@ -41,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" -> {
@@ -90,7 +95,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
)
val time = Time.fromH_m_s(it[4])
gradeAddedDateMillis = gradeAddedDate.combineWith(time)
- gradeSemester = profile?.dateToSemester(gradeAddedDate) ?: 1
+ gradeSemester = profile.dateToSemester(gradeAddedDate)
}
if (Regexes.MOBIDZIENNIK_GRADES_COUNT_TO_AVG.containsMatchIn(html)) {
@@ -108,17 +113,20 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
}
val gradeObject = Grade(
- profileId,
- gradeId,
- gradeCategory,
- gradeColor,
- "NLDŚR, $gradeDescription",
- gradeName,
- gradeValue,
- 0f,
- gradeSemester,
- teacherId,
- subjectId
+ profileId = profileId,
+ id = gradeId,
+ name = gradeName,
+ type = TYPE_NORMAL,
+ value = gradeValue,
+ weight = 0f,
+ color = gradeColor,
+ category = gradeCategory,
+ description = "NLDŚR, $gradeDescription",
+ comment = null,
+ semester = gradeSemester,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ addedDate = gradeAddedDateMillis
)
gradeObject.classAverage = gradeClassAverage
@@ -129,22 +137,20 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
profileId,
Metadata.TYPE_GRADE,
gradeObject.id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- gradeAddedDateMillis
+ profile.empty,
+ profile.empty
))
}
- } else {
- data.gradeAverages.put(gradeId, gradeClassAverage)
- data.gradeAddedDates.put(gradeId, gradeAddedDateMillis)
- data.gradeColors.put(gradeId, gradeColor)
}
+ data.gradeAverages[gradeId] = gradeClassAverage
+ data.gradeAddedDates[gradeId] = gradeAddedDateMillis
+ data.gradeColors[gradeId] = gradeColor
}
}
}
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_GRADES)
}
- }
+ }}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebHomework.kt
new file mode 100644
index 00000000..944b21ea
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebHomework.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-3-31.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_HOMEWORK
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+import pl.szczodrzynski.edziennik.get
+
+class MobidziennikWebHomework(override val data: DataMobidziennik,
+ override val lastSync: Long?,
+ val type: Int = TYPE_CURRENT,
+ val event: EventFull,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "MobidziennikWebHomework"
+ const val TYPE_CURRENT = 0
+ const val TYPE_PAST = 1
+ }
+
+ init {
+ val endpoint = when (type) {
+ TYPE_PAST -> "zadaniadomowearchiwalne"
+ else -> "zadaniadomowe"
+ }
+ webGet(TAG, "/mobile/$endpoint") { text ->
+ MobidziennikLuckyNumberExtractor(data, text)
+
+ Regexes.MOBIDZIENNIK_HOMEWORK_ROW.findAll(text).forEach { homeworkMatch ->
+ val tableRow = homeworkMatch[1].ifBlank { return@forEach }
+
+ /*val items = Regexes.MOBIDZIENNIK_HOMEWORK_ITEM.findAll(tableRow).map { match ->
+ match[1] to match[2].fixWhiteSpaces()
+ }.toList()*/
+
+ val id = Regexes.MOBIDZIENNIK_HOMEWORK_ID.find(tableRow)?.get(1)?.toLongOrNull() ?: return@forEach
+ if (event.id != id)
+ return@forEach
+
+ //val homeworkBody = Regexes.MOBIDZIENNIK_HOMEWORK_BODY.find(tableRow)?.get(1) ?: ""
+
+ event.attachmentIds = mutableListOf()
+ event.attachmentNames = mutableListOf()
+ Regexes.MOBIDZIENNIK_HOMEWORK_ATTACHMENT.findAll(tableRow).forEach {
+ event.attachmentIds?.add(it[1].toLongOrNull() ?: return@forEach)
+ event.attachmentNames?.add(it[2])
+ }
+
+ event.homeworkBody = ""
+ }
+
+ //data.eventList.add(eventObject)
+ //data.metadataList.add(
+ // Metadata(
+ // profileId,
+ // Metadata.TYPE_EVENT,
+ // eventObject.id,
+ // profile?.empty ?: false,
+ // profile?.empty ?: false,
+ // System.currentTimeMillis() /* no addedDate here though */
+ // ))
+
+ // not used as an endpoint
+ //data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
+ data.eventList.add(event)
+ data.eventListReplace = true
+
+ EventBus.getDefault().postSticky(EventGetEvent(event))
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_HOMEWORK)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt
index 56c0015a..5581dcc5 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt
@@ -9,35 +9,40 @@ import pl.szczodrzynski.edziennik.DAY
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+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.MessageRecipient
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
+import java.net.URLEncoder
class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
companion object {
private const val TAG = "MobidziennikWebMessagesAll"
}
init {
- webGet(TAG, "/dziennik/wyszukiwarkawiadomosci?q=+") { text ->
+ val query = URLEncoder.encode(data.profile?.studentNameLong ?: "a", "UTF-8")
+ webGet(TAG, "/dziennik/wyszukiwarkawiadomosci?q=$query") { text ->
MobidziennikLuckyNumberExtractor(data, text)
val doc = Jsoup.parse(text)
- val listElement = doc.getElementsByClass("spis").first()
+ val listElement = doc.getElementsByClass("spis")?.first()
if (listElement == null) {
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL, 7*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL)
return@webGet
}
val list = listElement.getElementsByClass("podswietl")
- for (item in list) {
- val id = item.attr("rel").replace("[^\\d]".toRegex(), "").toLongOrNull() ?: continue
+ list?.forEach { item ->
+ val id = item.attr("rel").replace("[^\\d]".toRegex(), "").toLongOrNull() ?: return@forEach
val subjectEl = item.select("td:eq(0) div").first()
val subject = subjectEl.text()
@@ -51,40 +56,41 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
type = TYPE_SENT
val senderEl = item.select("td:eq(3) div").first()
- var senderId: Long = -1
+ var senderId: Long? = null
if (type == TYPE_RECEIVED) {
// search sender teacher
- val senderName = senderEl.text()
- senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id ?: -1
+ val senderName = senderEl.text().fixName()
+ senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id
data.messageRecipientList.add(MessageRecipient(profileId, -1, id))
} else {
// TYPE_SENT, so multiple recipients possible
val recipientNames = senderEl.text().split(", ")
for (recipientName in recipientNames) {
- val recipientId = data.teacherList.singleOrNull { it.fullNameLastFirst == recipientName }?.id ?: -1
+ val name = recipientName.fixName()
+ val recipientId = data.teacherList.singleOrNull { it.fullNameLastFirst == name }?.id ?: -1
data.messageRecipientIgnoreList.add(MessageRecipient(profileId, recipientId, id))
}
}
val message = Message(
- profileId,
- id,
- subject,
- null,
- type,
- senderId,
- -1
+ profileId = profileId,
+ id = id,
+ type = type,
+ subject = subject,
+ body = null,
+ senderId = senderId,
+ addedDate = addedDate
)
- data.messageIgnoreList.add(message)
- data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate))
+ data.messageList.add(message)
+ data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true))
}
- // sync every 7 days as we probably don't except more than
+ // sync every 7 days as we probably don't expect more than
// 30 received messages during a week, without any normal sync
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL, 7*DAY)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt
index 8e01c560..be762228 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt
@@ -8,15 +8,18 @@ import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
companion object {
private const val TAG = "MobidziennikWebMessagesInbox"
}
@@ -27,15 +30,15 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
if (text.contains("Brak wiadomości odebranych.")) {
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX)
return@webGet
}
val doc = Jsoup.parse(text)
- val list = doc.getElementsByClass("spis").first().getElementsByClass("podswietl")
- for (item in list) {
- val id = item.attr("rel").toLongOrNull() ?: continue
+ val list = doc.getElementsByClass("spis")?.first()?.getElementsByClass("podswietl")
+ list?.forEach { item ->
+ val id = item.attr("rel").toLongOrNull() ?: return@forEach
val subjectEl = item.select("td:eq(0)").first()
var hasAttachments = false
@@ -48,39 +51,38 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
val addedDate = Date.fromIsoHm(addedDateEl.text())
val senderEl = item.select("td:eq(2)").first()
- val senderName = senderEl.ownText()
- val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id ?: -1
+ val senderName = senderEl.ownText().fixName()
+ val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id
data.messageRecipientIgnoreList.add(MessageRecipient(profileId, -1, id))
val isRead = item.select("td:eq(3) span").first().hasClass("wiadomosc_przeczytana")
val message = Message(
- profileId,
- id,
- subject,
- null,
- Message.TYPE_RECEIVED,
- senderId,
- -1
+ profileId = profileId,
+ id = id,
+ type = Message.TYPE_RECEIVED,
+ subject = subject,
+ body = null,
+ senderId = senderId,
+ addedDate = addedDate
)
if (hasAttachments)
- message.setHasAttachments()
+ message.hasAttachments = true
- data.messageIgnoreList.add(message)
- data.messageMetadataList.add(
+ data.messageList.add(message)
+ data.setSeenMetadataList.add(
Metadata(
profileId,
Metadata.TYPE_MESSAGE,
message.id,
isRead,
- isRead || profile?.empty ?: false,
- addedDate
+ isRead || profile?.empty ?: false
))
}
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt
new file mode 100644
index 00000000..543df329
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-2-18.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.DAY
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.fixName
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.singleOrNull
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "MobidziennikWebMessagesSent"
+ }
+
+ init {
+ webGet(TAG, "/dziennik/wiadomosciwyslane") { text ->
+ MobidziennikLuckyNumberExtractor(data, text)
+
+ if (text.contains("Brak wiadomości wysłanych.")) {
+ data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT)
+ return@webGet
+ }
+
+ val doc = Jsoup.parse(text)
+
+ val list = doc.getElementsByClass("spis")?.first()?.getElementsByClass("podswietl")
+ list?.forEach { item ->
+ val id = item.attr("rel").toLongOrNull() ?: return@forEach
+
+ val subjectEl = item.select("td:eq(0)").first()
+ var hasAttachments = false
+ if (subjectEl.getElementsByTag("a").size != 0) {
+ hasAttachments = true
+ }
+ val subject = subjectEl.ownText()
+
+ val readByString = item.select("td:eq(2)").first().text()
+ val (readBy, sentTo) = Regexes.MOBIDZIENNIK_MESSAGE_SENT_READ_BY.find(readByString).let {
+ (it?.get(1)?.toIntOrNull() ?: 0) to (it?.get(2)?.toIntOrNull() ?: 0)
+ }
+
+ val recipientEl = item.select("td:eq(1) a span").first()
+ val recipientNames = recipientEl.ownText().split(", ")
+ val readState = when (readBy) {
+ 0 -> 0
+ sentTo -> 1
+ else -> -1
+ }.toLong()
+ for (recipientName in recipientNames) {
+ val name = recipientName.fixName()
+ val recipientId = data.teacherList.singleOrNull { it.fullNameLastFirst == name }?.id ?: -1
+ data.messageRecipientIgnoreList.add(MessageRecipient(profileId, recipientId, -1, readState, id))
+ }
+
+ val addedDateEl = item.select("td:eq(3) small").first()
+ val addedDate = Date.fromIsoHm(addedDateEl.text())
+
+ val message = Message(
+ profileId = profileId,
+ id = id,
+ type = Message.TYPE_SENT,
+ subject = subject,
+ body = null,
+ senderId = null,
+ addedDate = addedDate
+ )
+
+ if (hasAttachments)
+ message.hasAttachments = true
+
+ data.messageList.add(message)
+ data.setSeenMetadataList.add(
+ Metadata(
+ profileId,
+ Metadata.TYPE_MESSAGE,
+ message.id,
+ true,
+ true
+ ))
+ }
+
+ data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT, 1*DAY, DRAWER_ITEM_MESSAGES)
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt
index d962826c..abf049a8 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt
@@ -7,10 +7,12 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_NOTICES
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
-import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
class MobidziennikWebNotices(override val data: DataMobidziennik,
- val onSuccess: () -> Unit) : MobidziennikWeb(data) {
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
companion object {
private const val TAG = "MobidziennikWebNotices"
}
@@ -18,7 +20,7 @@ class MobidziennikWebNotices(override val data: DataMobidziennik,
init {
// TODO this does no longer work: Mobidziennik changed their mobile page in 2019.09
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_NOTICES, SYNC_ALWAYS)
- onSuccess()
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_NOTICES)
/*webGet(TAG, "/mobile/zachowanie") { text ->
MobidziennikLuckyNumberExtractor(data, text)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt
new file mode 100644
index 00000000..89178b8b
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2019-12-26.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.POST
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+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 MobidziennikWebSendMessage(override val data: DataMobidziennik,
+ val recipients: List,
+ val subject: String,
+ val text: String,
+ val onSuccess: () -> Unit
+) : MobidziennikWeb(data, null) {
+ companion object {
+ private const val TAG = "MobidziennikWebSendMessage"
+ }
+
+ init {
+ val params = mutableListOf>(
+ "nazwa" to subject,
+ "tresc" to text
+ )
+ for (teacher in recipients) {
+ teacher.loginId?.let {
+ params += "odbiorcy[]" to it
+ }
+ }
+
+ webGet(TAG, endpoint = "/dziennik/dodajwiadomosc", method = POST, parameters = params) { text ->
+
+ if (!text.contains(">Wiadomość została wysłana.<")) {
+ // TODO error
+ return@webGet
+ }
+
+ // TODO create MobidziennikWebMessagesSent and replace this
+ MobidziennikWebMessagesAll(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/mobidziennik/data/web/MobidziennikWebTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebTimetable.kt
new file mode 100644
index 00000000..6ceb3fd9
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebTimetable.kt
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2021-9-8.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
+
+import android.annotation.SuppressLint
+import org.jsoup.Jsoup
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
+import pl.szczodrzynski.edziennik.data.db.entity.Lesson
+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 pl.szczodrzynski.edziennik.utils.models.Time
+import pl.szczodrzynski.edziennik.utils.models.Week
+import kotlin.collections.set
+import kotlin.text.replace
+
+class MobidziennikWebTimetable(
+ override val data: DataMobidziennik,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : MobidziennikWeb(data, lastSync) {
+ companion object {
+ private const val TAG = "MobidziennikWebTimetable"
+ }
+
+ private val rangesH = mutableMapOf, Date>()
+ private val hoursV = mutableMapOf>()
+ private var startDate: Date
+
+ private fun parseCss(css: String): Map {
+ return css.split(";").mapNotNull {
+ val spl = it.split(":")
+ if (spl.size != 2)
+ return@mapNotNull null
+ return@mapNotNull spl[0].trim() to spl[1].trim()
+ }.toMap()
+ }
+
+ private fun getRangeH(h: Float): Date? {
+ return rangesH.entries.firstOrNull {
+ h in it.key
+ }?.value
+ }
+
+ private fun stringToDate(date: String): Date? {
+ val items = date.split(" ")
+ val day = items.getOrNull(0)?.toIntOrNull() ?: return null
+ val year = items.getOrNull(2)?.toIntOrNull() ?: return null
+ val month = when (items.getOrNull(1)) {
+ "stycznia" -> 1
+ "lutego" -> 2
+ "marca" -> 3
+ "kwietnia" -> 4
+ "maja" -> 5
+ "czerwca" -> 6
+ "lipca" -> 7
+ "sierpnia" -> 8
+ "września" -> 9
+ "października" -> 10
+ "listopada" -> 11
+ "grudnia" -> 12
+ else -> return null
+ }
+ return Date(year, month, day)
+ }
+
+ init {
+ val currentWeekStart = Week.getWeekStart()
+ val nextWeekEnd = Week.getWeekEnd().stepForward(0, 0, 7)
+ if (Date.getToday().weekDay > 4) {
+ currentWeekStart.stepForward(0, 0, 7)
+ }
+ startDate = data.arguments?.getString("weekStart")?.let {
+ Date.fromY_m_d(it)
+ } ?: currentWeekStart
+
+ val syncFutureDate = startDate > nextWeekEnd
+ // TODO: 2021-09-09 make DataRemoveModel keep extra lessons
+ val syncExtraLessons = false && System.currentTimeMillis() - (lastSync ?: 0) > 2 * DAY * MS
+ if (!syncFutureDate && !syncExtraLessons) {
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE)
+ }
+ else {
+ val types = when {
+ syncFutureDate -> mutableListOf("podstawowy")//, "pozalekcyjny")
+ syncExtraLessons -> mutableListOf("pozalekcyjny")
+ else -> mutableListOf()
+ }
+
+ syncTypes(types, startDate) {
+ // set as synced now only when not syncing future date
+ // (to avoid waiting 2 days for normal sync after future sync)
+ if (syncExtraLessons)
+ data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_TIMETABLE)
+ }
+ }
+ }
+
+ private fun syncTypes(types: MutableList, startDate: Date, onSuccess: () -> Unit) {
+ if (types.isEmpty()) {
+ onSuccess()
+ return
+ }
+ val type = types.removeAt(0)
+ webGet(TAG, "/dziennik/planlekcji?typ=$type&tydzien=${startDate.stringY_m_d}") { html ->
+ MobidziennikLuckyNumberExtractor(data, html)
+ readRangesH(html)
+ readRangesV(html)
+ readLessons(html)
+ syncTypes(types, startDate, onSuccess)
+ }
+ }
+
+ private fun readRangesH(html: String) {
+ val htmlH = Regexes.MOBIDZIENNIK_TIMETABLE_TOP.find(html) ?: return
+ val docH = Jsoup.parse(htmlH.value)
+
+ var posH = 0f
+ for (el in docH.select("div > div")) {
+ val css = parseCss(el.attr("style"))
+ val width = css["width"]
+ ?.trimEnd('%')
+ ?.toFloatOrNull()
+ ?: continue
+ val value = stringToDate(el.attr("title"))
+ ?: continue
+
+ val range = posH.rangeTo(posH + width)
+ posH += width
+
+ rangesH[range] = value
+ }
+ }
+
+ private fun readRangesV(html: String) {
+ val htmlV = Regexes.MOBIDZIENNIK_TIMETABLE_LEFT.find(html) ?: return
+ val docV = Jsoup.parse(htmlV.value)
+
+ for (el in docV.select("div > div")) {
+ val css = parseCss(el.attr("style"))
+ val top = css["top"]
+ ?.trimEnd('%')
+ ?.toFloatOrNull()
+ ?: continue
+ val values = el.text().split(" ")
+
+ val time = values.getOrNull(0)?.let {
+ Time.fromH_m(it)
+ } ?: continue
+ val num = values.getOrNull(1)?.toIntOrNull()
+
+ hoursV[(top * 100).toInt()] = time to num
+ }
+ }
+
+ private val whitespaceRegex = "\\s+".toRegex()
+ private val classroomRegex = "\\((.*)\\)".toRegex()
+ private fun cleanup(str: String): List {
+ return str
+ .replace(whitespaceRegex, " ")
+ .replace("\n", "")
+ .replace("<small>", "$")
+ .replace("</small>", "$")
+ .replace("<br />", "\n")
+ .replace("<br/>", "\n")
+ .replace("<br>", "\n")
+ .replace(" ", "\n")
+ .replace(" ", "\n")
+ .replace(" ", "\n")
+ .replace("", "%")
+ .replace(" ", "%")
+ .replace("", "")
+ .replace(" ", "")
+ .split("\n")
+ .map { it.trim() }
+ }
+
+ @SuppressLint("LongLogTag", "LogNotTimber")
+ private fun readLessons(html: String) {
+ val matches = Regexes.MOBIDZIENNIK_TIMETABLE_CELL.findAll(html)
+
+ val noLessonDays = mutableListOf()
+ for (i in 0..6) {
+ noLessonDays.add(startDate.clone().stepForward(0, 0, i))
+ }
+
+ for (match in matches) {
+ val css = parseCss("${match[1]};${match[2]}")
+ val left = css["left"]?.trimEnd('%')?.toFloatOrNull() ?: continue
+ val top = css["top"]?.trimEnd('%')?.toFloatOrNull() ?: continue
+ val width = css["width"]?.trimEnd('%')?.toFloatOrNull() ?: continue
+ val height = css["height"]?.trimEnd('%')?.toFloatOrNull() ?: continue
+
+ val posH = left + width / 2f
+ val topInt = (top * 100).toInt()
+ val bottomInt = ((top + height) * 100).toInt()
+
+ val lessonDate = getRangeH(posH) ?: continue
+ val (startTime, lessonNumber) = hoursV[topInt] ?: continue
+ val endTime = hoursV[bottomInt]?.first ?: continue
+
+ noLessonDays.remove(lessonDate)
+
+ var typeName: String? = null
+ var subjectName: String? = null
+ var teacherName: String? = null
+ var classroomName: String? = null
+ var teamName: String? = null
+ val items = (cleanup(match[3]) + cleanup(match[4])).toMutableList()
+
+ var length = 0
+ while (items.isNotEmpty() && length != items.size) {
+ length = items.size
+ val toRemove = mutableListOf()
+ items.forEachIndexed { i, item ->
+ when {
+ item.isEmpty() ->
+ toRemove.add(item)
+ item.contains(":") && item.contains(" - ") ->
+ toRemove.add(item)
+
+ item.startsWith("%") -> {
+ subjectName = item.trim('%')
+ // I have no idea what's going on here
+ // ok now seriously.. the subject (long or short) item
+ // may NOT be 0th, as the HH:MM - HH:MM item may be before
+ // or even the typeName item. As these are always **before**,
+ // they are removed in previous iterations, so the first not removed
+ // item should be the long/short subjectName needing to be removed now.
+ toRemove.add(items[toRemove.size])
+ // ...and this has to be added later
+ toRemove.add(item)
+ }
+
+ item.startsWith("&") -> {
+ typeName = item.trim('&')
+ toRemove.add(item)
+ }
+ typeName != null && (item.contains(typeName!!) || item.contains("")) -> {
+ toRemove.add(item)
+ }
+
+ item.contains("(") && item.contains(")") -> {
+ classroomName = classroomRegex.find(item)?.get(1)
+ items[i] = item.replace("($classroomName)", "").trim()
+ }
+ classroomName != null && item.contains(classroomName!!) -> {
+ items[i] = item.replace("($classroomName)", "").trim()
+ }
+
+ item.contains("class=\"wyjatek tooltip\"") ->
+ toRemove.add(item)
+ }
+ }
+ items.removeAll(toRemove)
+ }
+
+ if (items.size == 2 && items[0].contains(" - ")) {
+ val parts = items[0].split(" - ")
+ teamName = parts[0]
+ teacherName = parts[1]
+ }
+ else if (items.size == 2 && typeName?.contains("odwołana") == true) {
+ teamName = items[0]
+ }
+ else if (items.size == 4) {
+ teamName = items[0]
+ teacherName = items[1]
+ }
+
+ val type = when (typeName) {
+ "zastępstwo" -> Lesson.TYPE_CHANGE
+ "lekcja odwołana", "odwołana" -> Lesson.TYPE_CANCELLED
+ else -> Lesson.TYPE_NORMAL
+ }
+ val subject = subjectName?.let { data.getSubject(null, it) }
+ val teacher = teacherName?.let { data.getTeacherByLastFirst(it) }
+ val team = teamName?.let { data.getTeam(
+ id = null,
+ name = it,
+ schoolCode = data.loginServerName ?: return@let null,
+ isTeamClass = false
+ ) }
+
+ Lesson(data.profileId, -1).also {
+ it.type = type
+ if (type == Lesson.TYPE_CANCELLED) {
+ it.oldDate = lessonDate
+ it.oldLessonNumber = lessonNumber
+ it.oldStartTime = startTime
+ it.oldEndTime = endTime
+ it.oldSubjectId = subject?.id ?: -1
+ it.oldTeamId = team?.id ?: -1
+ }
+ else {
+ it.date = lessonDate
+ it.lessonNumber = lessonNumber
+ it.startTime = startTime
+ it.endTime = endTime
+ it.subjectId = subject?.id ?: -1
+ it.teacherId = teacher?.id ?: -1
+ it.teamId = team?.id ?: -1
+ it.classroom = classroomName
+ }
+
+ it.id = it.buildId()
+
+ val seen = profile?.empty == false || lessonDate < Date.getToday()
+
+ if (it.type != Lesson.TYPE_NORMAL) {
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_LESSON_CHANGE,
+ it.id,
+ seen,
+ seen
+ )
+ )
+ }
+ data.lessonList += it
+ }
+ }
+
+ for (date in noLessonDays) {
+ data.lessonList += Lesson(data.profileId, date.value.toLong()).also {
+ it.type = Lesson.TYPE_NO_LESSONS
+ it.date = date
+ }
+ }
+ }
+}
+
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt
index 716f4937..11b668f9 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt
@@ -1,12 +1,14 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin
import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.fixName
+import pl.szczodrzynski.edziennik.set
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
@@ -14,10 +16,14 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
private const val TAG = "MobidziennikFirstLogin"
}
- private val web = MobidziennikWeb(data)
+ private val web = MobidziennikWeb(data, null)
private val profileList = mutableListOf()
init {
+ val loginStoreId = data.loginStore.id
+ val loginStoreType = LOGIN_TYPE_MOBIDZIENNIK
+ var firstProfileId = loginStoreId
+
MobidziennikLoginWeb(data) {
web.webGet(TAG, "/api/zrzutbazy") { text ->
val tables = text.split("T@B#LA")
@@ -32,6 +38,21 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
}
}
+ var dateSemester1Start: Date? = null
+ var dateSemester2Start: Date? = null
+ var dateYearEnd: Date? = null
+ for (row in tables[3].split("\n")) {
+ if (row.isEmpty())
+ continue
+ val cols = row.split("|")
+
+ when (cols[1]) {
+ "semestr1_poczatek" -> dateSemester1Start = Date.fromYmd(cols[3])
+ "semestr2_poczatek" -> dateSemester2Start = Date.fromYmd(cols[3])
+ "koniec_roku_szkolnego" -> dateYearEnd = Date.fromYmd(cols[3])
+ }
+ }
+
tables[8].split("\n").forEach { student ->
if (student.isEmpty())
return@forEach
@@ -39,20 +60,32 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
if (student1.size == 2)
return@forEach
- val today = Date.getToday()
- val profile = Profile()
- profile.studentNameLong = "${student1[2]} ${student1[4]}".fixName()
- profile.studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName()
- profile.accountNameLong = if (accountNameLong == profile.studentNameLong) null else accountNameLong
- profile.studentSchoolYear = "${today.year}/${today.year+1}"
- profile.name = profile.studentNameLong
- profile.subname = data.loginUsername
- profile.empty = true
- profile.putStudentData("studentId", student1[0].toInt())
+ val studentNameLong = "${student1[2]} ${student1[4]}".fixName()
+ val studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName()
+ val accountName = if (accountNameLong == studentNameLong) null else accountNameLong
+
+ val profile = Profile(
+ firstProfileId++,
+ loginStoreId,
+ loginStoreType,
+ studentNameLong,
+ data.loginUsername,
+ studentNameLong,
+ studentNameShort,
+ accountName
+ ).apply {
+ studentData["studentId"] = student1[0].toInt()
+ }
+ dateSemester1Start?.let {
+ profile.dateSemester1Start = it
+ profile.studentSchoolYearStart = it.year
+ }
+ dateSemester2Start?.let { profile.dateSemester2Start = it }
+ dateYearEnd?.let { profile.dateYearEnd = it }
profileList.add(profile)
}
- EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
onSuccess()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt
index 498ab2e3..7bc79a7b 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt
@@ -52,7 +52,7 @@ class MobidziennikLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
}
LOGIN_METHOD_MOBIDZIENNIK_API2 -> {
data.startProgress(R.string.edziennik_progress_login_mobidziennik_api2)
- //MobidziennikLoginApi2(data) { onSuccess(loginMethodId) }
+ MobidziennikLoginApi2(data) { onSuccess(loginMethodId) }
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginApi2.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginApi2.kt
new file mode 100644
index 00000000..db750981
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginApi2.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-1-12.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.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 pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.utils.Utils
+
+class MobidziennikLoginApi2(val data: DataMobidziennik, val onSuccess: () -> Unit) {
+ companion object {
+ private const val TAG = "MobidziennikLoginApi2"
+
+ fun getDevice(app: App) = JsonObject(
+ "available" to true,
+ "platform" to "Android",
+ "version" to Build.VERSION.RELEASE,
+ "uuid" to app.deviceId,
+ "cordova" to "7.1.2",
+ "model" to "${Build.MANUFACTURER} ${Build.MODEL}",
+ "manufacturer" to "Aplikacja Szkolny.eu",
+ "isVirtual" to false,
+ "serial" to try { System.getProperty("ro.serialno") ?: System.getProperty("ro.boot.serialno") } catch (_: Exception) { Build.UNKNOWN },
+ "appVersion" to "10.6, 2020.01.09-12.15.53",
+ "pushRegistrationId" to app.config.sync.tokenMobidziennik
+ )
+ }
+
+ init { run {
+ if (data.isApi2LoginValid()) {
+ onSuccess()
+ }
+ else {
+ if (data.loginServerName.isNotNullNorEmpty() && data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
+ loginWithCredentials()
+ }
+ else {
+ data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
+ }
+ }
+ }}
+
+ private fun loginWithCredentials() {
+ Utils.d(TAG, "Request: Mobidziennik/Login/Api2 - https://mobidziennik.pl/logowanie")
+
+ val callback = object : JsonCallbackHandler() {
+ override fun onSuccess(json: JsonObject?, response: Response?) {
+ if (json == null) {
+ data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return
+ }
+
+ json.getJsonObject("error")?.let {
+ val text = it.getString("type") ?: it.getString("message")
+ when (text) {
+ "LOGIN_ERROR" -> ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN
+ // TODO other error types
+ else -> ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER
+ }.let { errorCode ->
+ data.error(ApiError(TAG, errorCode)
+ .withApiResponse(text)
+ .withResponse(response))
+ return
+ }
+ }
+
+ data.loginEmail = json.getString("email")
+ data.globalId = json.getString("id_global")
+ data.loginId = json.getString("login")
+ onSuccess()
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url("https://mobidziennik.pl/logowanie")
+ .userAgent(MOBIDZIENNIK_USER_AGENT)
+ .contentType("application/x-www-form-urlencoded; charset=UTF-8")
+ .addParameter("api2", true)
+ .addParameter("email", data.loginEmail)
+ .addParameter("haslo", data.loginPassword)
+ .addParameter("device", getDevice(data.app).toString())
+ .post()
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginWeb.kt
index dbd3f86f..78526b0c 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginWeb.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginWeb.kt
@@ -26,7 +26,7 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
}
else {
if (data.loginServerName.isNotNullNorEmpty() && data.loginUsername.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
- data.app.cookieJar.clearForDomain(data.loginServerName + ".mobidziennik.pl")
+ data.app.cookieJar.clear("${data.loginServerName}.mobidziennik.pl")
loginWithCredentials()
}
else {
@@ -58,10 +58,10 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
}
}
- val cookies = data.app.cookieJar.getForDomain("${data.loginServerName}.mobidziennik.pl")
- val cookie = cookies.singleOrNull { it.name().length > 32 }
- val sessionKey = cookie?.name()
- val sessionId = cookie?.value()
+ val cookies = data.app.cookieJar.getAll("${data.loginServerName}.mobidziennik.pl")
+ val cookie = cookies.entries.firstOrNull { it.key.length > 32 }
+ val sessionKey = cookie?.key
+ val sessionId = cookie?.value
if (sessionId == null) {
data.error(ApiError(TAG, ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID)
.withResponse(response)
@@ -71,7 +71,7 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
data.webSessionKey = sessionKey
data.webSessionValue = sessionId
- data.webServerId = data.app.cookieJar.getCookie("${data.loginServerName}.mobidziennik.pl", "SERVERID")
+ data.webServerId = data.app.cookieJar.get("${data.loginServerName}.mobidziennik.pl", "SERVERID")
data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */
onSuccess()
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/DataPodlasie.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/DataPodlasie.kt
new file mode 100644
index 00000000..7962de7e
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/DataPodlasie.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie
+
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_PODLASIE_API
+import pl.szczodrzynski.edziennik.data.api.models.Data
+import pl.szczodrzynski.edziennik.data.db.entity.*
+import kotlin.text.replace
+
+class DataPodlasie(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
+
+ fun isApiLoginValid() = apiToken.isNotNullNorEmpty()
+
+ override fun satisfyLoginMethods() {
+ loginMethods.clear()
+ if (isApiLoginValid())
+ loginMethods += LOGIN_METHOD_PODLASIE_API
+ }
+
+ override fun generateUserCode(): String = "$schoolShortName:$loginShort:${studentId?.crc32()}"
+
+ /* _
+ /\ (_)
+ / \ _ __ _
+ / /\ \ | '_ \| |
+ / ____ \| |_) | |
+ /_/ \_\ .__/|_|
+ | |
+ |*/
+ private var mApiToken: String? = null
+ var apiToken: String?
+ get() { mApiToken = mApiToken ?: loginStore.getLoginData("apiToken", null); return mApiToken }
+ set(value) { loginStore.putLoginData("apiToken", value); mApiToken = value }
+
+ private var mApiUrl: String? = null
+ var apiUrl: String?
+ get() { mApiUrl = mApiUrl ?: profile?.getStudentData("apiUrl", null); return mApiUrl }
+ set(value) { profile?.putStudentData("apiUrl", value) ?: return; mApiUrl = 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 mStudentLogin: String? = null
+ var studentLogin: String?
+ get() { mStudentLogin = mStudentLogin ?: profile?.getStudentData("studentLogin", null); return mStudentLogin }
+ set(value) { profile?.putStudentData("studentLogin", value) ?: return; mStudentLogin = value }
+
+ private var mSchoolName: String? = null
+ var schoolName: String?
+ get() { mSchoolName = mSchoolName ?: profile?.getStudentData("schoolName", null); return mSchoolName }
+ set(value) { profile?.putStudentData("schoolName", value) ?: return; mSchoolName = value }
+
+ private var mClassName: String? = null
+ var className: String?
+ get() { mClassName = mClassName ?: profile?.getStudentData("className", null); return mClassName }
+ set(value) { profile?.putStudentData("className", value) ?: return; mClassName = value }
+
+ private var mSchoolYear: String? = null
+ var schoolYear: String?
+ get() { mSchoolYear = mSchoolYear ?: profile?.getStudentData("schoolYear", null); return mSchoolYear }
+ set(value) { profile?.putStudentData("schoolYear", value) ?: return; mSchoolYear = value }
+
+ private var mCurrentSemester: Int? = null
+ var currentSemester: Int
+ get() { mCurrentSemester = mCurrentSemester ?: profile?.getStudentData("currentSemester", 0); return mCurrentSemester ?: 0 }
+ set(value) { profile?.putStudentData("currentSemester", value) ?: return; mCurrentSemester = value }
+
+ val schoolShortName: String?
+ get() = studentLogin?.split('@')?.get(1)?.replace(".podlaskie.pl", "")
+
+ val loginShort: String?
+ get() = studentLogin?.split('@')?.get(0)
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/Podlasie.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/Podlasie.kt
new file mode 100644
index 00000000..d7ec441f
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/Podlasie.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie
+
+import com.google.gson.JsonObject
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.data.api.edziennik.helper.DownloadAttachment
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieData
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin.PodlasieFirstLogin
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLogin
+import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
+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.api.podlasieLoginMethods
+import pl.szczodrzynski.edziennik.data.api.prepare
+import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.data.db.entity.Teacher
+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
+import java.io.File
+
+class Podlasie(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
+ companion object {
+ const val TAG = "Podlasie"
+ }
+
+ val internalErrorList = mutableListOf()
+ val data: DataPodlasie
+
+ init {
+ data = DataPodlasie(app, profile, loginStore).apply {
+ callback = wrapCallback(this@Podlasie.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(podlasieLoginMethods, PodlasieFeatures, featureIds, viewId, onlyEndpoints)
+ Utils.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
+ Utils.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
+ PodlasieLogin(data) {
+ PodlasieData(data) {
+ completed()
+ }
+ }
+ }
+
+ override fun getMessage(message: MessageFull) {
+
+ }
+
+ override fun sendMessage(recipients: List, subject: String, text: String) {
+
+ }
+
+ override fun markAllAnnouncementsAsRead() {
+
+ }
+
+ override fun getAnnouncement(announcement: AnnouncementFull) {
+
+ }
+
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
+ val fileUrl = attachmentName.substringAfter(":")
+ DownloadAttachment(fileUrl,
+ onSuccess = { file ->
+ val event = AttachmentGetEvent(
+ data.profileId,
+ owner,
+ attachmentId,
+ AttachmentGetEvent.TYPE_FINISHED,
+ file.absolutePath
+ )
+
+ val attachmentDataFile = File(Utils.getStorageDir(), ".${data.profileId}_${event.ownerId}_${event.attachmentId}")
+ Utils.writeStringToFile(attachmentDataFile, event.fileName)
+
+ EventBus.getDefault().postSticky(event)
+
+ completed()
+ },
+ onProgress = { written, _ ->
+ val event = AttachmentGetEvent(
+ data.profileId,
+ owner,
+ attachmentId,
+ AttachmentGetEvent.TYPE_PROGRESS,
+ bytesWritten = written
+ )
+
+ EventBus.getDefault().postSticky(event)
+ },
+ onError = { apiError ->
+ data.error(apiError)
+ })
+ }
+
+ override fun getRecipientList() {
+
+ }
+
+ override fun getEvent(eventFull: EventFull) {
+
+ }
+
+ override fun firstLogin() {
+ PodlasieFirstLogin(data) {
+ completed()
+ }
+ }
+
+ override fun cancel() {
+ Utils.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) {
+ // TODO Error handling
+ when (apiError.errorCode) {
+ in internalErrorList -> {
+ // finish immediately if the same error occurs twice during the same sync
+ callback.onError(apiError)
+ }
+ else -> callback.onError(apiError)
+ }
+ }
+
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/PodlasieFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/PodlasieFeatures.kt
new file mode 100644
index 00000000..82c6f659
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/PodlasieFeatures.kt
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie
+
+import pl.szczodrzynski.edziennik.data.api.FEATURE_ALWAYS_NEEDED
+import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_PODLASIE_API
+import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE
+import pl.szczodrzynski.edziennik.data.api.models.Feature
+
+const val ENDPOINT_PODLASIE_API_MAIN = 1001
+
+val PodlasieFeatures = listOf(
+ Feature(LOGIN_TYPE_PODLASIE, FEATURE_ALWAYS_NEEDED, listOf(
+ ENDPOINT_PODLASIE_API_MAIN to LOGIN_METHOD_PODLASIE_API
+ ), listOf(LOGIN_METHOD_PODLASIE_API))
+)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/PodlasieApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/PodlasieApi.kt
new file mode 100644
index 00000000..985b9899
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/PodlasieApi.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data
+
+import com.google.gson.JsonObject
+import im.wangchao.mhttp.Request
+import im.wangchao.mhttp.RequestParams
+import im.wangchao.mhttp.Response
+import im.wangchao.mhttp.callback.JsonCallbackHandler
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.getInt
+import pl.szczodrzynski.edziennik.getJsonObject
+import pl.szczodrzynski.edziennik.toHexString
+import pl.szczodrzynski.edziennik.utils.Utils
+import java.security.MessageDigest
+import java.text.SimpleDateFormat
+import java.util.*
+
+open class PodlasieApi(open val data: DataPodlasie, open val lastSync: Long?) {
+ companion object {
+ const val TAG = "PodlasieApi"
+ }
+
+ val profileId
+ get() = data.profile?.id ?: -1
+
+ val profile
+ get() = data.profile
+
+ fun apiGet(tag: String, endpoint: String, onSuccess: (json: JsonObject) -> Unit) {
+ val url = PODLASIE_API_URL + endpoint
+
+ Utils.d(tag, "Request: Podlasie/Api - $url")
+
+ if (data.apiToken == null) {
+ data.error(tag, ERROR_PODLASIE_API_NO_TOKEN)
+ return
+ }
+
+ val callback = object : JsonCallbackHandler() {
+ override fun onSuccess(json: JsonObject?, response: Response?) {
+ if (json == null || response == null) {
+ data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return
+ }
+
+ val error = json.getJsonObject("system_message")?.getInt("code")
+
+ error?.let { code ->
+ when (code) {
+ 0 -> ERROR_PODLASIE_API_DATA_MISSING
+ 4 -> ERROR_LOGIN_PODLASIE_API_DEVICE_LIMIT
+ 5 -> ERROR_LOGIN_PODLASIE_API_INVALID_TOKEN
+ 200 -> null // Not an error
+ else -> ERROR_PODLASIE_API_OTHER
+ }?.let { errorCode ->
+ data.error(ApiError(tag, errorCode)
+ .withApiResponse(json)
+ .withResponse(response))
+ return@onSuccess
+ }
+ }
+
+ try {
+ onSuccess(json)
+ } catch (e: Exception) {
+ data.error(ApiError(tag, EXCEPTION_PODLASIE_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(SYSTEM_USER_AGENT)
+ .requestParams(RequestParams(mapOf(
+ "token" to data.apiToken,
+ "securityToken" to getSecurityToken(),
+ "mobileId" to data.app.deviceId,
+ "ver" to PODLASIE_API_VERSION
+ )))
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+
+ private fun getSecurityToken(): String {
+ val format = SimpleDateFormat("yyyy-MM-dd HH", Locale.ENGLISH)
+ .also { it.timeZone = TimeZone.getTimeZone("Europe/Warsaw") }.format(System.currentTimeMillis())
+ val instance = MessageDigest.getInstance("SHA-256")
+ val digest = instance.digest("-EYlwYu8u16miVd8tT?oO7cvoUVQrQN0vr!$format".toByteArray()).toHexString()
+ val digest2 = instance.digest((data.apiToken ?: "").toByteArray()).toHexString()
+ return instance.digest("$digest$digest2".toByteArray()).toHexString()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/PodlasieData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/PodlasieData.kt
new file mode 100644
index 00000000..ce1197b8
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/PodlasieData.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data
+
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.ENDPOINT_PODLASIE_API_MAIN
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api.PodlasieApiMain
+import pl.szczodrzynski.edziennik.utils.Utils
+
+class PodlasieData(val data: DataPodlasie, val onSuccess: () -> Unit) {
+ companion object {
+ const val TAG = "PodlasieData"
+ }
+
+ 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) {
+ 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_PODLASIE_API_MAIN -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_data)
+ PodlasieApiMain(data, lastSync, onSuccess)
+ }
+ else -> onSuccess(endpointId)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiEvents.kt
new file mode 100644
index 00000000..8a169ee7
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiEvents.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-13
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api
+
+import com.google.gson.JsonObject
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+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.getLong
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.models.Date
+import pl.szczodrzynski.edziennik.utils.models.Time
+import java.util.*
+
+class PodlasieApiEvents(val data: DataPodlasie, val rows: List) {
+ init {
+ rows.forEach { event ->
+ val id = event.getLong("ExternalId") ?: return@forEach
+ val date = event.getString("DateFrom")?.let { Date.fromY_m_d(it) } ?: return@forEach
+ val time = event.getString("DateFrom")?.let { Time.fromY_m_d_H_m_s(it) }
+ ?: return@forEach
+
+ val name = event.getString("Name")?.replace(""", "\"") ?: ""
+ val description = event.getString("Description")?.replace(""", "\"") ?: ""
+
+ val type = when (event.getString("Category")?.toLowerCase(Locale.getDefault())) {
+ "klasówka" -> Event.TYPE_EXAM
+ "praca domowa" -> Event.TYPE_HOMEWORK
+ "wycieczka" -> Event.TYPE_EXCURSION
+ else -> Event.TYPE_DEFAULT
+ }
+
+ val teacherFirstName = event.getString("PersonEnteringDataFirstName") ?: return@forEach
+ val teacherLastName = event.getString("PersonEnteringDataLastName") ?: return@forEach
+ val teacher = data.getTeacher(teacherFirstName, teacherLastName)
+
+ val lessonList = data.db.timetableDao().getAllForDateNow(data.profileId, date)
+ val lesson = lessonList.firstOrNull { it.startTime == time }
+
+ val addedDate = event.getString("CreateDate")?.let { Date.fromIso(it) }
+ ?: System.currentTimeMillis()
+
+ val eventObject = Event(
+ profileId = data.profileId,
+ id = id,
+ date = date,
+ time = time,
+ topic = name,
+ color = null,
+ type = type,
+ teacherId = teacher.id,
+ subjectId = lesson?.subjectId ?: -1,
+ teamId = data.teamClass?.id ?: -1,
+ addedDate = addedDate
+ ).apply {
+ homeworkBody = description
+ }
+
+ data.eventList.add(eventObject)
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ if (type == Event.TYPE_HOMEWORK) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT,
+ id,
+ data.profile?.empty ?: false,
+ data.profile?.empty ?: false
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Events.future())
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiFinalGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiFinalGrades.kt
new file mode 100644
index 00000000..bb4f696c
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiFinalGrades.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-13
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api
+
+import com.google.gson.JsonObject
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+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_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.Grade.Companion.TYPE_YEAR_FINAL
+import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.getLong
+import pl.szczodrzynski.edziennik.getString
+
+class PodlasieApiFinalGrades(val data: DataPodlasie, val rows: List) {
+ init { data.profile?.also { profile ->
+ rows.forEach { grade ->
+ val id = grade.getLong("ExternalId") ?: return@forEach
+ val mark = grade.getString("Mark") ?: return@forEach
+ val proposedMark = grade.getString("ProposedMark") ?: "0"
+ val name = data.app.gradesManager.getGradeNumberName(mark)
+ val value = data.app.gradesManager.getGradeValue(name)
+ val semester = grade.getString("TermShortcut")?.length ?: return@forEach
+
+ val typeName = grade.getString("Type") ?: return@forEach
+ val type = when (typeName) {
+ "S" -> if (semester == 1) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER2_FINAL
+ "Y", "R" -> TYPE_YEAR_FINAL
+ else -> return@forEach
+ }
+
+ val subjectName = grade.getString("SchoolSubject") ?: return@forEach
+ val subject = data.getSubject(null, subjectName)
+
+ val addedDate = if (profile.empty) profile.getSemesterStart(semester).inMillis
+ else System.currentTimeMillis()
+
+ val gradeObject = Grade(
+ profileId = data.profileId,
+ id = id,
+ name = name,
+ type = type,
+ value = value,
+ weight = 0f,
+ color = -1,
+ category = null,
+ description = null,
+ comment = null,
+ semester = semester,
+ teacherId = -1,
+ subjectId = subject.id,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_GRADE,
+ id,
+ profile.empty,
+ profile.empty
+ ))
+
+ if (proposedMark != "0") {
+ val proposedName = data.app.gradesManager.getGradeNumberName(proposedMark)
+ val proposedValue = data.app.gradesManager.getGradeValue(proposedName)
+
+ val proposedType = when (typeName) {
+ "S" -> if (semester == 1) TYPE_SEMESTER1_PROPOSED else TYPE_SEMESTER2_PROPOSED
+ "Y", "R" -> TYPE_YEAR_PROPOSED
+ else -> return@forEach
+ }
+
+ val proposedGradeObject = Grade(
+ profileId = data.profileId,
+ id = id * (-1),
+ name = proposedName,
+ type = proposedType,
+ value = proposedValue,
+ weight = 0f,
+ color = -1,
+ category = null,
+ description = null,
+ comment = null,
+ semester = semester,
+ teacherId = -1,
+ subjectId = subject.id,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(proposedGradeObject)
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_GRADE,
+ proposedGradeObject.id,
+ profile.empty,
+ profile.empty
+ ))
+ }
+ }
+
+ data.toRemove.addAll(listOf(
+ TYPE_SEMESTER1_FINAL,
+ TYPE_SEMESTER1_PROPOSED,
+ TYPE_SEMESTER2_FINAL,
+ TYPE_SEMESTER2_PROPOSED,
+ TYPE_YEAR_FINAL,
+ TYPE_YEAR_PROPOSED
+ ).map {
+ DataRemoveModel.Grades.allWithType(it)
+ })
+ }}
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiGrades.kt
new file mode 100644
index 00000000..c3946c76
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiGrades.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-13
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api
+
+import android.graphics.Color
+import com.google.gson.JsonObject
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
+import pl.szczodrzynski.edziennik.data.db.entity.Grade
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.getFloat
+import pl.szczodrzynski.edziennik.getInt
+import pl.szczodrzynski.edziennik.getLong
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class PodlasieApiGrades(val data: DataPodlasie, val rows: List